From 4f76b9f18c71afaf1de95c8f2f810aa6371ac4a4 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 5 Dec 2015 18:58:27 -0800 Subject: [PATCH] fix scriptInput/signInput for multisig/p2sh. --- lib/bcoin/tx.js | 51 ++++++++++++++++++++++++++------------------- lib/bcoin/wallet.js | 2 +- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index b1243ba5..40445e3e 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -112,7 +112,7 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) { return -1; }; -TX.prototype.signature = function(input, key) { +TX.prototype.signature = function(input, key, type) { // Get the previous output's subscript var s = input.out.tx.getSubscript(input.out.index); @@ -142,13 +142,11 @@ TX.prototype.scriptInput = function(input, pub, nsigs) { // Multisig // raw format: OP_FALSE [sig-1] [sig-2] ... if (bcoin.script.isMultisig(s)) { - if (!nsigs) { + if (!nsigs) throw new Error('`nsigs` is required for multisig'); - } input.script = [ constants.opcodes['false'] ]; - for (var i = 0; i < nsigs; i++) { + for (var i = 0; i < nsigs; i++) input.script[i + 1] = constants.opcodes['0']; - } return; } @@ -157,21 +155,22 @@ TX.prototype.scriptInput = function(input, pub, nsigs) { if (bcoin.script.isScripthash(s)) { input.script = [ constants.opcodes['false'] ]; var m = pub[0] - constants.opcodes['1'] + 1; - for (var i = 0; i < m; i++) { + for (var i = 0; i < m; i++) input.script[i + 1] = constants.opcodes['0']; - } // P2SH requires the redeem script after signatures - if (bcoin.script.isScripthash(s)) { + if (bcoin.script.isScripthash(s)) input.script.push(pub); - } return; } - throw new Error('could not identify prev_out type'); + throw new Error('scriptInput(): could not identify prev_out type'); }; // Sign the now-built scriptSigs -TX.prototype.signInput = function(input, key) { +TX.prototype.signInput = function(input, key, type) { + if (!type) + type = 'all'; + // Get the previous output's subscript var s = input.out.tx.getSubscript(input.out.index); @@ -191,29 +190,39 @@ TX.prototype.signInput = function(input, key) { } // Multisig - // empty array == OP_FALSE == OP_0 // raw format: OP_FALSE [sig-1] [sig-2] ... // p2sh format: OP_FALSE [sig-1] [sig-2] ... [redeem-script] if (bcoin.script.isMultisig(s) || bcoin.script.isScripthash(s)) { - var l = input.script.length; - if (bcoin.script.isScripthash(s)) { - l--; - } - for (var i = 0; i < l; i++) { - input.script[i + 1] = signature; + var len = input.script.length; + + if (bcoin.script.isScripthash(s)) + len--; + + for (var i = 1; i < len; i++) { + // Already signed + if (utils.isEqual(input.script[i], signature)) + break; + + if (input.script[i] === constants.opcodes['0']) { + input.script[i] = signature; + break; + } } + return; } + + throw new Error('signInput(): could not identify prev_out type'); }; // Build the scriptSig and sign it -TX.prototype.scriptSig = function(input, key, pub, nsigs) { +TX.prototype.scriptSig = function(input, key, pub, type, nsigs) { // Build script for input tx.scriptInput(input, pub, nsigs); // Sign input - tx.signInput(input, key); + tx.signInput(input, key, type); - return this.input.script; + return input.script; }; TX.prototype.input = function input(i, index) { diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index df4579d1..db20d8d9 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -347,7 +347,7 @@ Wallet.prototype.sign = function sign(tx, type, inputs) { if (!input.out.tx || !this.ownOutput(input.out.tx)) return false; - tx.scriptSig(input, key, pub, nsigs); + tx.scriptSig(input, key, pub, type, nsigs); return true; }, this);