From c19d5c6501a23b2a5c35c1d2b9ac7ca39abf5a36 Mon Sep 17 00:00:00 2001 From: eordano Date: Wed, 18 Feb 2015 09:43:47 -0300 Subject: [PATCH 1/2] Transaction: Check that threshold is less than amount of signatures --- lib/transaction/transaction.js | 2 ++ test/transaction/transaction.js | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index a98b0d651..bbf6b729d 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -447,6 +447,8 @@ Transaction.prototype._fromNonP2SH = function(utxo) { }; Transaction.prototype._fromMultisigUtxo = function(utxo, pubkeys, threshold) { + $.checkArgument(threshold <= pubkeys.length, + 'Number of required signatures must be greater than the number of public keys'); utxo = new UnspentOutput(utxo); this.addInput(new MultiSigScriptHashInput({ output: new Output({ diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index aab1b228c..29b7c154e 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -126,6 +126,10 @@ describe('Transaction', function() { var changeAddress = 'mgBCJAsvzgT2qNNeXsoECg2uPKrUsZ76up'; var changeAddressP2SH = '2N7T3TAetJrSCruQ39aNrJvYLhG1LJosujf'; var privateKey = 'cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY'; + var private1 = '6ce7e97e317d2af16c33db0b9270ec047a91bff3eff8558afb5014afb2bb5976'; + var private2 = 'c9b26b0f771a0d2dad88a44de90f05f416b3b385ff1d989343005546a0032890'; + var public1 = new PrivateKey(private1).publicKey; + var public2 = new PrivateKey(private2).publicKey; var simpleUtxoWith1BTC = { address: fromAddress, @@ -364,10 +368,6 @@ describe('Transaction', function() { expect(deserialized.inputs[0] instanceof Transaction.Input.PublicKeyHash).to.equal(true); }); it('can serialize and deserialize a P2SH input', function() { - var private1 = '6ce7e97e317d2af16c33db0b9270ec047a91bff3eff8558afb5014afb2bb5976'; - var private2 = 'c9b26b0f771a0d2dad88a44de90f05f416b3b385ff1d989343005546a0032890'; - var public1 = new PrivateKey(private1).publicKey; - var public2 = new PrivateKey(private2).publicKey; var transaction = new Transaction() .from({ txId: '0000', // Not relevant @@ -401,6 +401,17 @@ describe('Transaction', function() { transaction.addInput(new Transaction.Input(), Script.empty(), 0); }).to.not.throw(); }); + it('does not allow a threshold number greater than the amount of public keys', function() { + expect(function() { + transaction = new Transaction(); + return transaction.from({ + txId: '0000000000000000000000000000000000000000000000000000000000000000', + outputIndex: 0, + script: Script(), + satoshis: 10000 + }, [], 1); + }).to.throw('Number of required signatures must be greater than the number of public keys'); + }); }); describe('removeInput and removeOutput', function() { From 1a5780e35eff803fe5bf98a21076bb55d014f69d Mon Sep 17 00:00:00 2001 From: eordano Date: Wed, 18 Feb 2015 11:53:22 -0300 Subject: [PATCH 2/2] Script/Address: Add check for valid number of threshold needed --- lib/script/script.js | 2 ++ test/address.js | 6 ++++++ test/script/script.js | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/lib/script/script.js b/lib/script/script.js index 321ffc0b8..0962db986 100644 --- a/lib/script/script.js +++ b/lib/script/script.js @@ -543,6 +543,8 @@ Script.prototype.removeCodeseparators = function() { * public keys before creating the script */ Script.buildMultisigOut = function(publicKeys, threshold, opts) { + $.checkArgument(threshold <= publicKeys.length, + 'Number of required signatures must be less than or equal to the number of public keys'); opts = opts || {}; var script = new Script(); script.add(Opcode.smallInt(threshold)); diff --git a/test/address.js b/test/address.js index 85c7fc36b..f857308b0 100644 --- a/test/address.js +++ b/test/address.js @@ -499,6 +499,12 @@ describe('Address', function() { var address2 = Address.createMultisig(publics, 2); address.toString().should.equal(address2.toString()); }); + + it('fails if invalid array is provided', function() { + expect(function() { + return Address.createMultisig([],3,'testnet'); + }).to.throw('Number of required signatures must be less than or equal to the number of public keys'); + }); }); }); diff --git a/test/script/script.js b/test/script/script.js index a3c6d1d94..5896bdc8f 100644 --- a/test/script/script.js +++ b/test/script/script.js @@ -430,6 +430,12 @@ describe('Script', function() { s.toString().should.equal('OP_2 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9 OP_3 OP_CHECKMULTISIG'); s.isMultisigOut().should.equal(true); }); + it('should fail when number of required signatures is greater than number of pubkeys', function() { + expect(sortkeys.length).to.equal(3); + expect(function() { + return Script.buildMultisigOut(sortkeys, 4); + }).to.throw('Number of required signatures must be less than or equal to the number of public keys'); + }); it('should create unsorted script if specified', function() { var s = Script.buildMultisigOut(sortkeys, 2); var u = Script.buildMultisigOut(sortkeys, 2, {