diff --git a/src/transaction_builder.js b/src/transaction_builder.js index d73555b..e481fde 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -49,13 +49,14 @@ function extractInput(txIn) { break case 'multisig': - parsed = scriptSig.chunks.slice(1).filter(function(chunk) { - return chunk !== ops.OP_0 - }).map(ECSignature.parseScriptSignature) + signatures = scriptSig.chunks.slice(1).map(function(chunk) { + if (chunk === ops.OP_0) return chunk - hashType = parsed[0].hashType - signatures = parsed.map(function(p) { return p.signature }) - initialized = true + var parsed = ECSignature.parseScriptSignature(chunk) + hashType = parsed.hashType + + return parsed.signature + }) if (redeemScript) { pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer) @@ -124,10 +125,8 @@ TransactionBuilder.fromTransaction = function(transaction) { // Extract/add signatures txb.inputs = transaction.ins.map(function(txIn) { - // Coinbase inputs not supported - assert(!Array.prototype.every.call(txIn.hash, function(x) { - return x === 0 - }), 'coinbase inputs not supported') + // TODO: remove me after testcase added + assert(!isCoinbase(txIn.hash), 'coinbase inputs not supported') // Ignore empty scripts if (txIn.script.buffer.length === 0) return @@ -236,9 +235,17 @@ TransactionBuilder.prototype.__build = function(allowIncomplete) { case 'multisig': assert(input.signatures, 'Transaction is missing signatures') - var signatures = input.signatures.map(function(signature) { + // Array.prototype.map is sparse-compatible + var msSignatures = input.signatures.map(function(signature) { return signature.toScriptSignature(input.hashType) - }).filter(function(signature) { return !!signature }) + }) + + // fill in blanks with OP_0 + for (var i = 0; i < msSignatures.length; ++i) { + if (msSignatures[i]) continue + + msSignatures[i] = ops.OP_0 + } var redeemScript = allowIncomplete ? undefined : input.redeemScript scriptSig = scripts.multisigInput(signatures, redeemScript) diff --git a/test/transaction_builder.js b/test/transaction_builder.js index ceed7e2..66f89ac 100644 --- a/test/transaction_builder.js +++ b/test/transaction_builder.js @@ -276,11 +276,10 @@ describe('TransactionBuilder', function() { }) }) - // TODO: test for reverse order signing - it('works for the P2SH multisig case', function() { + it('works for the out-of-order P2SH multisig case', function() { var privKeys = [ - "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT" + "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", + "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx" ].map(ECKey.fromWIF) var redeemScript = Script.fromASM("OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG")