example for solveOutput, also checks every sigHash test vector

This commit is contained in:
Thomas Kerin 2016-11-12 15:26:53 +01:00
parent 78faaddf4d
commit c0bbd76ad0
2 changed files with 74 additions and 2 deletions

View File

@ -188,7 +188,7 @@ Transaction.prototype.addOutput = function (scriptPubKey, value) {
Transaction.prototype._hasWitnesses = function () {
return this.ins.some(function (x) {
return x.witness !== EMPTY_WITNESS
return x.witness.length > 0
})
}

View File

@ -2,7 +2,8 @@
var assert = require('assert')
var bscript = require('../src/script')
var bcrypto = require('../src/crypto')
var bufferReverse = require('buffer-reverse')
var Transaction = require('../src/transaction')
var fixtures = require('./fixtures/transaction')
@ -223,4 +224,75 @@ describe('Transaction', function () {
})
})
})
describe('signature hashing', function () {
function unsignedTransactionFromRaw (raw) {
var unsigned = new Transaction()
unsigned.version = raw.version
unsigned.ins = raw.ins.map(function (input) {
return {
hash: bufferReverse(new Buffer(input.hash, 'hex')),
index: input.index,
script: new Buffer(0), // Empty for now
witness: [], // Empty for now
sequence: 4294967295
}
})
unsigned.outs = raw.outs.map(function (output) {
return {
value: output.value,
script: new Buffer(output.scriptHex, 'hex')
}
})
unsigned.locktime = 0
return unsigned
}
function checkInputsMatchSigHash (f) {
var unsigned = unsignedTransactionFromRaw(f.raw)
f.raw.ins.forEach(function (input) {
it('determines the correct sighash for all inputs', function () {
var prevOutScript = new Buffer(input.scriptPubKey, 'hex')
var valueOut = input.value ? input.value : 0
var redeemScript = input.redeemScript ? new Buffer(input.redeemScript, 'hex') : undefined
var witnessScript = input.witnessScript ? new Buffer(input.witnessScript, 'hex') : undefined
var expectedSigHash = new Buffer(input.sigHash, 'hex')
var tx = unsigned
// This is example usage of solveOutput
var sigVersion = 0
var solution = bscript.solveOutput(prevOutScript)
if (solution.type === bscript.types.P2SH) {
// This line is useless given the example, but illustrates usage
if (solution.solvedBy.equals(bcrypto.hash160(redeemScript))) {
solution = bscript.solveOutput(redeemScript)
}
}
// We again use solvedBy (result of the script.*.output.decode() function)
// But notice, here we don't know if it's witness due to (i) scriptPubKey or (ii) redeemScript
// so it's nice solveOutput also returns solvedBy
if (solution.type === bscript.types.P2WPKH) {
sigVersion = 1
solution = bscript.solveOutput(bscript.pubKeyHash.output.encode(solution.solvedBy))
} else if (solution.type === bscript.types.P2WSH) {
sigVersion = 1
solution = bscript.solveOutput(witnessScript)
}
assert([bscript.types.P2PKH, bscript.types.P2PK, bscript.types.MULTISIG].indexOf(solution.type) !== -1, 'should have found a signable type')
var hash = sigVersion === 1
? tx.hashForWitnessV0(0, solution.script, valueOut, Transaction.SIGHASH_ALL)
: tx.hashForSignature(0, solution.script, Transaction.SIGHASH_ALL)
assert.equal(hash.toString('hex'), expectedSigHash.toString('hex'))
})
})
}
fixtures.witness.forEach(checkInputsMatchSigHash)
})
})