Browse Source

first 2 sighash cash vector passing

master
Matias Alejo Garcia 7 years ago
parent
commit
95988dd7d3
No known key found for this signature in database GPG Key ID: 2470DB551277AB3
  1. 1
      lib/crypto/signature.js
  2. 175
      lib/transaction/sighash.js
  3. 30
      test/transaction/sighash.js

1
lib/crypto/signature.js

@ -307,6 +307,7 @@ Signature.prototype.toTxFormat = function() {
Signature.SIGHASH_ALL = 0x01;
Signature.SIGHASH_NONE = 0x02;
Signature.SIGHASH_SINGLE = 0x03;
Signature.SIGHASH_FORKID = 0x40;
Signature.SIGHASH_ANYONECANPAY = 0x80;
module.exports = Signature;

175
lib/transaction/sighash.js

@ -11,11 +11,166 @@ var BN = require('../crypto/bn');
var Hash = require('../crypto/hash');
var ECDSA = require('../crypto/ecdsa');
var $ = require('../util/preconditions');
var BufferUtil = require('../util/buffer');
var _ = require('lodash');
var SIGHASH_SINGLE_BUG = '0000000000000000000000000000000000000000000000000000000000000001';
var BITS_64_ON = 'ffffffffffffffff';
var ENABLE_SIGHASH_FORKID = true;
var sighashForForkId = function(transaction, sighashType, inputNumber, subscript, satoshisBN) {
console.log('[sighash.js.56:SIGHASH_FORKID:]'); //TODO
console.log('[sighash.js.29:transaction:]', transaction); //TODO
console.log('[sighash.js.29:sighashType:]', sighashType); //TODO
console.log('[sighash.js.29:inputNumber:]', inputNumber); //TODO
console.log('[sighash.js.29:subscript:]', subscript); //TODO
console.log('[sighash.js.24:satoshisBN:]',satoshisBN); //TODO
console.log('========================================================');
var input = transaction.inputs[inputNumber];
$.checkArgument(
satoshisBN instanceof BN || (input.output && input.output._satoshisBN),
'For ForkId=0 signatures, satoshis or complete input must be provided'
);
function GetForkId() {
return 0; // In the UAHF, a fork id of 0 is used (see [4] REQ-6-2 NOTE 4)
};
function GetPrevoutHash() {
var buf = new BufferWriter()
// for ( n = 0; n < txTo.vin.size(); n++) {
// ss << txTo.vin[n].prevout;
// }
return buf.GetHash();
}
function GetSequenceHash() {
// CHashWriter ss(SER_GETHASH, 0);
// for ( n = 0; n < txTo.vin.size(); n++) {
// ss << txTo.vin[n].nSequence;
// }
//
// return ss.GetHash();
}
function GetOutputsHash(tx) {
var writer = new BufferWriter()
_.each(tx.outputs, function(output) {
output.toBufferWriter(writer);
});
var buf = writer.toBuffer();
var ret = Hash.sha256sha256(buf);
console.log('[sighash.js.58:ret:]',ret); //TODO
return ret;
}
satoshisBN = satoshisBN || input.output._satoshisBN;
var hashPrevouts = BufferUtil.emptyBuffer(32);
var hashSequence = BufferUtil.emptyBuffer(32);
var hashOutputs = BufferUtil.emptyBuffer(32);
if (!(sighashType & Signature.SIGHASH_ANYONECANPAY)) {
console.log('NOT [sighash.js.62:SIGHASH_ANYONECANPAY:]'); //TODO
// hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo);
}
if (!(sighashType & Signature.SIGHASH_ANYONECANPAY) &&
(sighashType & 31) != Signature.SIGHASH_SINGLE &&
(sighashType & 31) != Signature.SIGHASH_NONE) {
console.log('NOT [sighash.js.62:SIGHASH_ANYONECANPAY:] & !SINGLE && !NONE'); //TODO
// hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo);
}
if ((sighashType & 31) != Signature.SIGHASH_SINGLE &&
(sighashType & 31) != Signature.SIGHASH_NONE) {
console.log('!SINGLE && !NONE'); //TODO
hashOutputs = GetOutputsHash(transaction);
console.log('[sighash.js.94:hashOutputs:]',hashOutputs); //TODO
} else if ((sighashType & 31) == Signature.SIGHASH_SINGLE &&
nIn < txTo.vout.size()) {
console.log('SINGLE'); //TODO
// CHashWriter ss(SER_GETHASH, 0);
// ss << txTo.vout[nIn];
// hashOutputs = ss.GetHash();
}
function getHash (w) {
var buf = w.toBuffer();
var ret = Hash.sha256sha256(buf);
ret = new BufferReader(ret).readReverse();
return ret;
};
var writer = new BufferWriter()
// Version
writer.writeInt32LE(transaction.version);
// // Input prevouts/nSequence (none/all, depending on flags)
writer.write(hashPrevouts);
writer.write(hashSequence);
// OK
// outpoint (32-byte hash + 4-byte little endian)
writer.writeReverse(input.prevTxId);
writer.writeUInt32LE(input.outputIndex);
// OK
// scriptCode of the input (serialized as scripts inside CTxOuts)
writer.writeUInt8(subscript.toBuffer().length)
writer.write(subscript.toBuffer());
// OK
// value of the output spent by this input (8-byte little endian)
writer.writeUInt64LEBN(satoshisBN);
// OK
// nSequence of the input (4-byte little endian)
var sequenceNumber = input.sequenceNumber;
writer.writeUInt32LE(sequenceNumber);
//ok
// Outputs (none/one/all, depending on flags)
writer.write(hashOutputs);
//Ok
// Locktime
writer.writeUInt32LE(transaction.nLockTime);
//OK
// sighashType
//writer.writeUInt32LE((GetForkId() << 24) | (sighashType & 31));
console.log('[sighash.js.158:sighashType:]',sighashType); //TODO
writer.writeUInt32LE(sighashType >>>0);
//OK!
var buf = writer.toBuffer();
var ret = Hash.sha256sha256(buf);
ret = new BufferReader(ret).readReverse();
return ret;
//
// writer.writeVarintNum(this.inputs.length);
// _.each(this.inputs, function(input) {
// input.toBufferWriter(writer);
// });
}
/**
* Returns a buffer of length 32 bytes with the hash that needs to be signed
* for OP_CHECKSIG.
@ -25,19 +180,34 @@ var BITS_64_ON = 'ffffffffffffffff';
* @param {number} sighashType the type of the hash
* @param {number} inputNumber the input index for the signature
* @param {Script} subscript the script that will be signed
* @param {opts.satoshis} Optional, only used in ForkId signatures. If not provided, outputs's amount is used.
*
*/
var sighash = function sighash(transaction, sighashType, inputNumber, subscript) {
var sighash = function sighash(transaction, sighashType, inputNumber, subscript, opts) {
opts = opts || {};
var Transaction = require('./transaction');
var Input = require('./input');
var i;
// Copy transaction
var txcopy = Transaction.shallowCopy(transaction);
// Copy script
subscript = new Script(subscript);
console.log('[sighash.js.197] type, ', sighashType, Signature.SIGHASH_FORKID, sighashType & Signature.SIGHASH_FORKID ); //TODO
if ( ( sighashType & Signature.SIGHASH_FORKID) && ENABLE_SIGHASH_FORKID) {
return sighashForForkId(txcopy, sighashType, inputNumber, subscript, opts.satoshisBN);
}
console.log('[sighash.js.200] NO FORKID'); //TODO
// For no ForkId sighash, separators need to be removed.
subscript.removeCodeseparators();
var i;
for (i = 0; i < txcopy.inputs.length; i++) {
// Blank signatures for other inputs
txcopy.inputs[i] = new Input(txcopy.inputs[i]).setScript(Script.empty());
@ -79,6 +249,7 @@ var sighash = function sighash(transaction, sighashType, inputNumber, subscript)
if (sighashType & Signature.SIGHASH_ANYONECANPAY) {
txcopy.inputs = [txcopy.inputs[inputNumber]];
}
console.log('[sighash.js.252:sighashType:]',sighashType); //TODO
var buf = new BufferWriter()
.write(txcopy.toBuffer())

30
test/transaction/sighash.js

@ -6,15 +6,36 @@ var chai = require('chai');
var should = chai.should();
var bitcore = require('../../');
var Script = bitcore.Script;
var BN = bitcore.crypto.BN;
var Transaction = bitcore.Transaction;
var sighash = Transaction.sighash;
var vectors_sighash = require('../data/sighash.json');
describe('sighash', function() {
describe.only('sighash', function() {
it('Should require amount for sigHash ForkId=0', function() {
var vector = ["3eb87070042d16f9469b0080a3c1fe8de0feae345200beef8b1e0d7c62501ae0df899dca1e03000000066a0065525365ffffffffd14a9a335e8babddd89b5d0b6a0f41dd6b18848050a0fc48ce32d892e11817fd030000000863acac00535200527ff62cf3ad30d9064e180eaed5e6303950121a8086b5266b55156e4f7612f2c7ebf223e0020000000100ffffffff6273ca3aceb55931160fa7a3064682b4790ee016b4a5c0c0d101fd449dff88ba01000000055351ac526aa3b8223d0421f25b0400000000026552f92db70500000000075253516a656a53c4a908010000000000b5192901000000000652525251516aa148ca38", "acab53", 3, -1325231124, "fbbc83ed610e416d94dcee2bb3bc35dfea8060b8052c59eabd7e998e3e978328"];
var txbuf = new buffer.Buffer(vector[0], 'hex');
var scriptbuf = new buffer.Buffer(vector[1], 'hex');
var subscript = Script(scriptbuf);
var nin = vector[2];
var nhashtype = vector[3];
var sighashbuf = new buffer.Buffer(vector[4], 'hex');
var tx = new Transaction(txbuf);
//make sure transacion to/from buffer is isomorphic
tx.uncheckedSerialize().should.equal(txbuf.toString('hex'));
//sighash ought to be correct
(function() {
sighash.sighash(tx, nhashtype, nin, subscript).toString('hex').should.equal(sighashbuf.toString('hex'));
}).should.throw('Invalid Argument');
});
var zeroBN = BN.Zero;
console.log('[sighash.js.36:vectors_sighash:]',vectors_sighash.length); //TODO
vectors_sighash.forEach(function(vector, i) {
if (i === 0) {
if (i === 0 || !vector[4]) {
// First element is just a row describing the next ones
return;
}
@ -24,6 +45,7 @@ describe('sighash', function() {
var subscript = Script(scriptbuf);
var nin = vector[2];
var nhashtype = vector[3];
// var nhashtype = vector[3]>>>0;
var sighashbuf = new buffer.Buffer(vector[4], 'hex');
var tx = new Transaction(txbuf);
@ -31,7 +53,9 @@ describe('sighash', function() {
tx.uncheckedSerialize().should.equal(txbuf.toString('hex'));
//sighash ought to be correct
sighash.sighash(tx, nhashtype, nin, subscript).toString('hex').should.equal(sighashbuf.toString('hex'));
sighash.sighash(tx, nhashtype, nin, subscript, {
satoshisBN: zeroBN
}).toString('hex').should.equal(sighashbuf.toString('hex'));
});
});
});

Loading…
Cancel
Save