From cf20326e98d8c6356a2260295c6005268b98c292 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 7 Dec 2015 14:12:42 -0800 Subject: [PATCH] verify sighash types other than `all`. --- lib/bcoin/script.js | 26 +++++++++++++------------- lib/bcoin/tx.js | 27 +++++++++++++++++---------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index ecd21535..d0785fac 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -128,7 +128,7 @@ script.verify = function verify(hash, sig, pub) { } }; -script.execute = function execute(s, stack, tx) { +script.execute = function execute(s, stack, hasher) { if (s.length > 10000) { return false; } @@ -160,20 +160,20 @@ script.execute = function execute(s, stack, tx) { } } else if (o === 'checksigverify' || o === 'checksig') { - if (!tx || stack.length < 2) + if (!hasher || stack.length < 2) return false; var pub = stack.pop(); var sig = stack.pop(); var type = sig[sig.length - 1]; - if (type !== 1) + if (!constants.rhashType[type & 0x7f]) return false; - // XXX Deal with different hashTypes besides `all` - // if (typeof tx === 'function') - // tx = tx(constants.rhashType[type]); + var hash = hasher; + if (typeof hash === 'function') + hash = hash(type); - var res = script.verify(tx, sig.slice(0, -1), pub); + var res = script.verify(hash, sig.slice(0, -1), pub); if (o === 'checksigverify') { if (!res) return false; @@ -181,7 +181,7 @@ script.execute = function execute(s, stack, tx) { stack.push(res ? [ 1 ] : []); } } else if (o === 'checkmultisigverify' || o === 'checkmultisig') { - if (!tx || stack.length < 3) + if (!hasher || stack.length < 3) return false; var n = stack.pop(); @@ -214,16 +214,16 @@ script.execute = function execute(s, stack, tx) { for (var i = 0, j = 0; i < m && j < n; i++) { var sig = stack.pop(); var type = sig[sig.length - 1]; - if (type !== 1) + if (!constants.rhashType[type & 0x7f]) return false; - // XXX Deal with different hashTypes besides `all` - // if (typeof tx === 'function') - // tx = tx(constants.rhashType[type]); + var hash = hasher; + if (typeof hash === 'function') + hash = hash(type); var res = false; for (; !res && j < n; j++) - res = script.verify(tx, sig.slice(0, -1), keys[j]); + res = script.verify(hash, sig.slice(0, -1), keys[j]); if (res) succ++; } diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index e1f879dd..74d9cea3 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -124,6 +124,12 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) { }; TX.prototype.signature = function(input, key, type) { + if (!type) + type = 'all'; + + if (typeof type === 'string') + type = bcoin.protocol.constants.hashType[type]; + // Get the previous output's subscript var s = input.out.tx.getSubscript(input.out.index); @@ -134,7 +140,7 @@ TX.prototype.signature = function(input, key, type) { var signature = bcoin.ecdsa.sign(hash, key).toDER(); // Add the sighash as a single byte to the signature - signature = signature.concat(constants.hashType[type]); + signature = signature.concat(type); return signature; }; @@ -187,6 +193,9 @@ TX.prototype.signInput = function(input, key, type) { if (!type) type = 'all'; + if (typeof type === 'string') + type = bcoin.protocol.constants.hashType[type]; + // Get the previous output's subscript var s = input.out.tx.getSubscript(input.out.index); @@ -197,7 +206,7 @@ TX.prototype.signInput = function(input, key, type) { var signature = bcoin.ecdsa.sign(hash, key).toDER(); // Add the sighash as a single byte to the signature - signature = signature.concat(constants.hashType[type]); + signature = signature.concat(type); // P2PKH and simple tx if (bcoin.script.isPubkeyhash(s) || bcoin.script.isSimplePubkeyhash(s)) { @@ -329,13 +338,14 @@ TX.prototype.getSubscript = function getSubscript(index) { TX.prototype.subscriptHash = function subscriptHash(index, s, type) { var copy = this.clone(); + if (typeof type === 'string') + type = bcoin.protocol.constants.hashType[type]; + copy.inputs.forEach(function(input, i) { input.script = index === i ? s : []; }); var verifyStr = copy.render(); - verifyStr = verifyStr.concat( - bcoin.protocol.constants.hashType[type], 0, 0, 0 - ); + utils.writeU32(verifyStr, type, verifyStr.length); var hash = utils.dsha256(verifyStr); return hash; @@ -356,15 +366,12 @@ TX.prototype.verify = function verify(index, force) { assert(input.out.tx.outputs.length > input.out.index); var subscript = input.out.tx.getSubscript(input.out.index); - var hash = this.subscriptHash(i, subscript, 'all'); - - // XXX Deal with different hashTypes besides `all` - // var hash = this.subscriptHash.bind(this, i, subscript); + var hasher = this.subscriptHash.bind(this, i, subscript); var stack = []; bcoin.script.execute(input.script, stack); var prev = input.out.tx.outputs[input.out.index].script; - var res = bcoin.script.execute(prev, stack, hash); + var res = bcoin.script.execute(prev, stack, hasher); if (!res) return false;