From dfe74fa0d23b2a0c4ba3753fabfbd27405b257b3 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 12 Dec 2014 15:19:03 +1100 Subject: [PATCH] TxBuilder: sign now signs inputs in known publicKey order --- src/transaction_builder.js | 40 +++++++++++++++++++++++++++---------- test/transaction_builder.js | 21 +++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/transaction_builder.js b/src/transaction_builder.js index ede0283..d05ee5b 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -33,10 +33,9 @@ function extractSignature(txIn) { switch (scriptType) { case 'pubkeyhash': parsed = ECSignature.parseScriptSignature(scriptSig.chunks[0]) - var pubKey = ECPubKey.fromBuffer(scriptSig.chunks[1]) - hashType = parsed.hashType - pubKeys = [pubKey] + + pubKeys = [ECPubKey.fromBuffer(scriptSig.chunks[1])] signatures = [parsed.signature] break @@ -50,6 +49,10 @@ function extractSignature(txIn) { pubKeys = [] signatures = parsed.map(function(p) { return p.signature }) + if (redeemScript) { + pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer) + } + break case 'pubkey': @@ -59,6 +62,10 @@ function extractSignature(txIn) { pubKeys = [] signatures = [parsed.signature] + if (redeemScript) { + pubKeys = [ECPubKey.fromBuffer(redeemScript.chunks[0])] + } + break default: @@ -249,15 +256,26 @@ TransactionBuilder.prototype.sign = function(index, privKey, redeemScript, hashT var input = this.signatures[index] if (!input) { + var pubKeys = [] + + if (redeemScript && scriptType === 'multisig') { + pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer) + + } else { + pubKeys.push(privKey.pub) + } + input = { hashType: hashType, - pubKeys: [], + pubKeys: pubKeys, redeemScript: redeemScript, scriptType: scriptType, signatures: [] } this.signatures[index] = input + this.prevOutScripts[index] = prevOutScript + this.prevOutTypes[index] = prevOutType } else { assert.equal(scriptType, 'multisig', scriptType + ' doesn\'t support multiple signatures') @@ -265,13 +283,15 @@ TransactionBuilder.prototype.sign = function(index, privKey, redeemScript, hashT assert.deepEqual(input.redeemScript, redeemScript, 'Inconsistent redeemScript') } - this.prevOutScripts[index] = prevOutScript - this.prevOutTypes[index] = prevOutType + // enforce signing in order of public keys + assert(input.pubKeys.some(function(pubKey, i) { + if (!privKey.pub.Q.equals(pubKey.Q)) return false // FIXME: could be better? + + assert(!input.signatures[i], 'Signature already exists') + input.signatures[i] = privKey.sign(hash) - // TODO: order signatures for multisig, enforce m < n - var signature = privKey.sign(hash) - input.pubKeys.push(privKey.pub) - input.signatures.push(signature) + return true + }), 'privateKey cannot sign for this input') } module.exports = TransactionBuilder diff --git a/test/transaction_builder.js b/test/transaction_builder.js index cde634b..a53cdaf 100644 --- a/test/transaction_builder.js +++ b/test/transaction_builder.js @@ -184,6 +184,27 @@ describe('TransactionBuilder', function() { }, /RedeemScript not supported \(nonstandard\)/) }) }) + + it('throws if signature already exists', function() { + var redeemScript = scripts.multisigOutput(1, [privKey.pub]) + + txb.addInput(prevTxHash, 0) + txb.sign(0, privKey, redeemScript) + + assert.throws(function() { + txb.sign(0, privKey, redeemScript) + }, /Signature already exists/) + }) + + it('throws if private key is unable to sign for that input', function() { + var redeemScript = scripts.multisigOutput(1, [privKey.pub]) + + txb.addInput(prevTxHash, 0) + + assert.throws(function() { + txb.sign(0, ECKey.makeRandom(), redeemScript) + }, /privateKey cannot sign for this input/) + }) }) describe('build', function() {