Transaction: re-work hashForSignature for readability

This commit is contained in:
Daniel Cousens 2016-06-22 13:54:55 +10:00
parent 4898cc7b67
commit 697f2da1bc

View file

@ -168,6 +168,10 @@ Transaction.prototype.clone = function () {
var ONE = new Buffer('0000000000000000000000000000000000000000000000000000000000000001', 'hex') var ONE = new Buffer('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
var VALUE_UINT64_MAX = new Buffer('ffffffffffffffff', 'hex') var VALUE_UINT64_MAX = new Buffer('ffffffffffffffff', 'hex')
var BLANK_OUTPUT = {
script: EMPTY_SCRIPT,
valueBuffer: VALUE_UINT64_MAX
}
/** /**
* Hash transaction for signing a specific input. * Hash transaction for signing a specific input.
@ -183,61 +187,55 @@ Transaction.prototype.hashForSignature = function (inIndex, prevOutScript, hashT
// https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L29 // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L29
if (inIndex >= this.ins.length) return ONE if (inIndex >= this.ins.length) return ONE
var txTmp = this.clone() // ignore OP_CODESEPARATOR
var ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) {
// in case concatenating two scripts ends up with two codeseparators,
// or an extra one at the end, this prevents all those possible incompatibilities.
var hashScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) {
return x !== opcodes.OP_CODESEPARATOR return x !== opcodes.OP_CODESEPARATOR
})) }))
var i
// blank out other inputs' signatures var txTmp = this.clone()
txTmp.ins.forEach(function (input) { input.script = EMPTY_SCRIPT })
txTmp.ins[inIndex].script = hashScript
// blank out some of the inputs // SIGHASH_NONE: ignore all outputs? (wildcard payee)
if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) { if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
// wildcard payee
txTmp.outs = [] txTmp.outs = []
// let the others update at will // ignore sequence numbers (except at inIndex)
txTmp.ins.forEach(function (input, i) { txTmp.ins.forEach(function (input, i) {
if (i !== inIndex) { if (i === inIndex) return
input.sequence = 0
} input.sequence = 0
}) })
// SIGHASH_SINGLE: ignore all outputs, except at the same index?
} else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) { } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) {
var nOut = inIndex
// only lock-in the txOut payee at same index as txIn
// https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60 // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60
if (nOut >= this.outs.length) return ONE if (inIndex >= this.outs.length) return ONE
txTmp.outs = txTmp.outs.slice(0, nOut + 1) // truncate outputs after
txTmp.outs.length = inIndex + 1
// blank all other outputs (clear scriptPubKey, value === -1) // "blank" outputs before
var stubOut = { for (var i = 0; i < inIndex; i++) {
script: EMPTY_SCRIPT, txTmp.outs[i] = BLANK_OUTPUT
valueBuffer: VALUE_UINT64_MAX
} }
for (i = 0; i < nOut; i++) { // ignore sequence numbers (except at inIndex)
txTmp.outs[i] = stubOut
}
// let the others update at will
txTmp.ins.forEach(function (input, i) { txTmp.ins.forEach(function (input, i) {
if (i !== inIndex) { if (i === inIndex) return
input.sequence = 0
} input.sequence = 0
}) })
} }
// blank out other inputs completely, not recommended for open transactions // SIGHASH_ANYONECANPAY: ignore inputs entirely?
if (hashType & Transaction.SIGHASH_ANYONECANPAY) { if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
txTmp.ins[0] = txTmp.ins[inIndex] txTmp.ins = [txTmp.ins[inIndex]]
txTmp.ins = txTmp.ins.slice(0, 1) txTmp.ins[0].script = ourScript
// SIGHASH_ALL: only ignore input scripts
} else {
// "blank" others input scripts
txTmp.ins.forEach(function (input) { input.script = EMPTY_SCRIPT })
txTmp.ins[inIndex].script = ourScript
} }
// serialize and hash // serialize and hash