From ee66c41dd45a92af28512fa5cf06c98e0e8c75a0 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 10:21:38 +1000 Subject: [PATCH 1/8] message: add missing test for Address --- test/message.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/message.js b/test/message.js index 5846a4d..d69a41f 100644 --- a/test/message.js +++ b/test/message.js @@ -1,6 +1,7 @@ var assert = require('assert') var networks = require('../src/networks') +var Address = require('../src/address') var BigInteger = require('bigi') var ECKey = require('../src/eckey') var Message = require('../src/message') @@ -20,6 +21,15 @@ describe('Message', function() { }) describe('verify', function() { + it('accepts an Address object', function() { + var f = fixtures.valid.verify[0] + var network = networks[f.network] + + var address = Address.fromBase58Check(f.address) + var signature = new Buffer(f.signature, 'base64') + assert.ok(Message.verify(address, signature, f.message, network)) + }) + fixtures.valid.verify.forEach(function(f) { it('verifies a valid signature for \"' + f.message + '\" (' + f.network + ')', function() { var network = networks[f.network] From 8c5c0a13a6f1b344560e8d838823874b074e5e5f Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 10:22:00 +1000 Subject: [PATCH 2/8] Transaction: remove untested (and broken) functionality --- src/transaction.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/transaction.js b/src/transaction.js index d9c83a7..eed58ed 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -21,10 +21,6 @@ function Transaction(doc) { this.outs = [] if (doc) { - if (typeof doc == "string" || Array.isArray(doc)) { - doc = Transaction.fromBuffer(doc) - } - if (doc.hash) this.hash = doc.hash; if (doc.version) this.version = doc.version; if (doc.locktime) this.locktime = doc.locktime; From 4f8040f8d41fc0512ac7959111cbdd049673a233 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 11:45:01 +1000 Subject: [PATCH 3/8] ecdsa: add invalid test fixtures for recoverPubKey --- src/ecdsa.js | 5 +++-- test/ecdsa.js | 14 ++++++++++++++ test/fixtures/ecdsa.json | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/ecdsa.js b/src/ecdsa.js index ff2a8d7..e4f34f9 100644 --- a/src/ecdsa.js +++ b/src/ecdsa.js @@ -186,7 +186,7 @@ function parseSigCompact(buffer) { * http://www.secg.org/download/aid-780/sec1-v2.pdf */ function recoverPubKey(curve, e, signature, i) { - assert.strictEqual(i & 3, i, 'The recovery param is more than two bits') + assert.strictEqual(i & 3, i, 'Recovery param is more than two bits') var r = signature.r var s = signature.s @@ -223,7 +223,8 @@ function recoverPubKey(curve, e, signature, i) { // 1.4 Check that nR isn't at infinity var R = Point.fromAffine(curve, x, y) - curve.validate(R) + var nR = R.multiply(n) + assert(curve.isInfinity(nR), 'nR is not a valid curve point') // 1.5 Compute -e from e var eNeg = e.negate().mod(n) diff --git a/test/ecdsa.js b/test/ecdsa.js index 8569e08..46d259c 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -37,6 +37,20 @@ describe('ecdsa', function() { var Qprime = ecdsa.recoverPubKey(curve, e, parsed.signature, parsed.i) assert(Q.equals(Qprime)) }) + + fixtures.invalid.recoverPubKey.forEach(function(f) { + it('throws on ' + f.description, function() { + var e = BigInteger.fromHex(f.e) + var signature = { + r: new BigInteger(f.signature.r), + s: new BigInteger(f.signature.s) + } + + assert.throws(function() { + ecdsa.recoverPubKey(curve, e, signature, f.i) + }, new RegExp(f.exception)) + }) + }) }) describe('sign', function() { diff --git a/test/fixtures/ecdsa.json b/test/fixtures/ecdsa.json index 4795d07..c10d691 100644 --- a/test/fixtures/ecdsa.json +++ b/test/fixtures/ecdsa.json @@ -143,6 +143,28 @@ "hex": "300c0204ffffffff0202ffffffff" } ], + "recoverPubKey": [ + { + "description": "Invalid r value (== 0)", + "exception": "nR is not a valid curve point", + "e": "01", + "signature": { + "r": "00", + "s": "02" + }, + "i": 0 + }, + { + "description": "Invalid i value (> 3)", + "exception": "Recovery param is more than two bits", + "e": "01", + "signature": { + "r": "00", + "s": "02" + }, + "i": 4 + } + ], "verifyRaw": [ { "description": "The wrong signature", From 402fa0d85ddce59f86e39dc65c694938cfa7627e Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 11:47:22 +1000 Subject: [PATCH 4/8] ecdsa: amend recoverPubKey SEC comments --- src/ecdsa.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ecdsa.js b/src/ecdsa.js index e4f34f9..1e87e62 100644 --- a/src/ecdsa.js +++ b/src/ecdsa.js @@ -210,10 +210,10 @@ function recoverPubKey(curve, e, signature, i) { curve.P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2) } - // 1.1 Compute x + // 1.1 Let x = r + jn var x = isSecondKey ? r.add(n) : r - // 1.3 Convert x to point + // 1.2, 1.3 Convert x to a point R using routine specified in Section 2.3.4 var alpha = x.pow(3).add(a.multiply(x)).add(b).mod(p) var beta = alpha.modPow(curve.P_OVER_FOUR, p) @@ -221,16 +221,16 @@ function recoverPubKey(curve, e, signature, i) { // otherwise we're done and y == beta. var y = (beta.isEven() ^ isYEven) ? p.subtract(beta) : beta - // 1.4 Check that nR isn't at infinity + // 1.4 Check that nR is at infinity var R = Point.fromAffine(curve, x, y) var nR = R.multiply(n) assert(curve.isInfinity(nR), 'nR is not a valid curve point') - // 1.5 Compute -e from e + // Compute -e from e var eNeg = e.negate().mod(n) - // 1.6 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) var rInv = r.modInverse(n) var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv) @@ -258,6 +258,7 @@ function calcPubKeyRecoveryParam(curve, e, signature, Q) { for (var i = 0; i < 4; i++) { var Qprime = recoverPubKey(curve, e, signature, i) + // 1.6.2 Verify Q if (Qprime.equals(Q)) { return i } From 1a41ea88018682cb398f08d09f4d1e7e998f4da1 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 21:06:30 +1000 Subject: [PATCH 5/8] ecdsa: add more extensive tests for recoverPubKey --- src/ecdsa.js | 4 ---- test/ecdsa.js | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/ecdsa.js b/src/ecdsa.js index 1e87e62..76e779e 100644 --- a/src/ecdsa.js +++ b/src/ecdsa.js @@ -236,10 +236,6 @@ function recoverPubKey(curve, e, signature, i) { var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv) curve.validate(Q) - if (!verifyRaw(curve, e, signature, Q)) { - throw new Error("Pubkey recovery unsuccessful") - } - return Q } diff --git a/test/ecdsa.js b/test/ecdsa.js index 46d259c..4b2b1f1 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -25,17 +25,43 @@ describe('ecdsa', function() { }) describe('recoverPubKey', function() { - it('succesfully recovers a public key', function() { - var d = BigInteger.ONE - var signature = new Buffer('INcvXVVEFyIfHLbDX+xoxlKFn3Wzj9g0UbhObXdMq+YMKC252o5RHFr0/cKdQe1WsBLUBi4morhgZ77obDJVuV0=', 'base64') + fixtures.valid.forEach(function(f) { + it('recovers the pubKey for ' + f.d, function() { + var d = BigInteger.fromHex(f.d) + var Q = curve.params.G.multiply(d) + var signature = { + r: new BigInteger(f.signature.r), + s: new BigInteger(f.signature.s) + } + var h1 = crypto.sha256(f.message) + var e = BigInteger.fromBuffer(h1) + var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.compact.i) + + assert(Qprime.equals(Q)) + }) + }) - var Q = curve.params.G.multiply(d) + describe('with i ∈ {0,1,2,3}', function() { var hash = message.magicHash('1111', networks.bitcoin) var e = BigInteger.fromBuffer(hash) - var parsed = ecdsa.parseSigCompact(signature) - var Qprime = ecdsa.recoverPubKey(curve, e, parsed.signature, parsed.i) - assert(Q.equals(Qprime)) + var signature = new Buffer('INcvXVVEFyIfHLbDX+xoxlKFn3Wzj9g0UbhObXdMq+YMKC252o5RHFr0/cKdQe1WsBLUBi4morhgZ77obDJVuV0=', 'base64') + var parsed = ecdsa.parseSigCompact(signature) + var points = [ + '03e3a8c44a8bf712f1fbacee274fb19c0239b1a9e877eff0075ea335f2be8ff380', + '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '03d49e765f0bc27525c51a1b98fb1c99dacd59abe85a203af90f758260550b56c5', + '027eea09d46ac7fb6aa2e96f9c576677214ffdc238eb167734a9b39d1eb4c3d30d' + ] + + points.forEach(function(expectedHex, i) { + it('recovers an expected point for i of ' + i, function() { + var Qprime = ecdsa.recoverPubKey(curve, e, parsed.signature, i) + var QprimeHex = Qprime.getEncoded().toString('hex') + + assert.equal(QprimeHex, expectedHex) + }) + }) }) fixtures.invalid.recoverPubKey.forEach(function(f) { From 576d5dfa3fe53ddf83a73c7277b9ef357d296627 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 23:30:34 +1000 Subject: [PATCH 6/8] Scripts: move test data to fixtures --- test/fixtures/scripts.json | 80 ++++++++++++++++ test/scripts.js | 185 ++++++++++++++++++++----------------- 2 files changed, 182 insertions(+), 83 deletions(-) create mode 100644 test/fixtures/scripts.json diff --git a/test/fixtures/scripts.json b/test/fixtures/scripts.json new file mode 100644 index 0000000..58eb32e --- /dev/null +++ b/test/fixtures/scripts.json @@ -0,0 +1,80 @@ +{ + "valid": { + "pubKey": [ + { + "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "scriptPubKey": "2102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1ac", + "scriptSig": "47304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" + } + ], + "pubKeyHash": [ + { + "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "scriptPubKey": "76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac", + "scriptSig": "47304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca28012102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1" + } + ], + "multisig": [ + { + "pubKeys": [ + "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a" + ], + "signatures": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" + ], + "scriptPubKey": "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", + "scriptSig": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" + }, + { + "pubKeys": [ + "02ea1297665dd733d444f31ec2581020004892cdaaf3dd6c0107c615afb839785f", + "02fab2dea1458990793f56f42e4a47dbf35a12a351f26fa5d7e0cc7447eaafa21f", + "036c6802ce7e8113723dd92cdb852e492ebb157a871ca532c3cb9ed08248ff0e19" + ], + "signatures": [], + "scriptPubKey": "532102ea1297665dd733d444f31ec2581020004892cdaaf3dd6c0107c615afb839785f2102fab2dea1458990793f56f42e4a47dbf35a12a351f26fa5d7e0cc7447eaafa21f21036c6802ce7e8113723dd92cdb852e492ebb157a871ca532c3cb9ed08248ff0e1953ae", + "scriptSig": "" + } + ], + "scripthash": [ + { + "redeemScript": "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", + "redeemScriptSig": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", + "scriptSig": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d14050147522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", + "scriptPubKey": "a914722ff0bc2c3f47b35c20df646c395594da24e90e87" + } + ] + }, + "invalid": { + "multisig": [ + { + "exception": "Not enough pubKeys provided", + "m": 4, + "pubKeys": [ + "02ea1297665dd733d444f31ec2581020004892cdaaf3dd6c0107c615afb839785f", + "02fab2dea1458990793f56f42e4a47dbf35a12a351f26fa5d7e0cc7447eaafa21f", + "036c6802ce7e8113723dd92cdb852e492ebb157a871ca532c3cb9ed08248ff0e19" + ], + "signatures": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" + ], + "scriptPubKey": true + }, + { + "exception": "Not enough signatures provided", + "pubKeys": [ + "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a" + ], + "signatures": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" + ], + "scriptPubKey": false + } + ] + } +} diff --git a/test/scripts.js b/test/scripts.js index 19222e5..b6b07e5 100644 --- a/test/scripts.js +++ b/test/scripts.js @@ -8,9 +8,7 @@ var ECPubKey = require('../src/ecpubkey') var Script = require('../src/script') var fixtures = require('./fixtures/script.json') - -function b2h(b) { return new Buffer(b).toString('hex') } -function h2b(h) { return new Buffer(h, 'hex') } +var fixtures2 = require('./fixtures/scripts.json') describe('Scripts', function() { describe('classifyInput', function() { @@ -39,106 +37,127 @@ describe('Scripts', function() { }) }) - // FIXME: bad - describe('pay-to-pubKeyHash', function() { - it('matches the test data', function() { - var f = fixtures.valid[2] - var address = Address.fromBase58Check('19E6FV3m3kEPoJD5Jz6dGKdKwTVvjsWUvu') - var script = scripts.pubKeyHashOutput(address.hash) - - assert.equal(script.toHex(), f.hex) - }) - }) - - // FIXME: bad - describe('pay-to-pubkey', function() { - describe('input', function() { - it('matches the test data', function() { - var f = fixtures.valid[4] - var signature = new Buffer(f.signature, 'hex') - var script = scripts.pubKeyInput(signature) + describe('pubKey', function() { + fixtures2.valid.pubKey.forEach(function(f) { + describe('input script', function() { + it('is generated correctly for ' + f.pubKey, function() { + var signature = new Buffer(f.signature, 'hex') - assert.equal(script.toHex(), f.hex) + var scriptSig = scripts.pubKeyInput(signature) + assert.equal(scriptSig.toHex(), f.scriptSig) + }) }) - }) - describe('output', function() { - it('matches the test data', function() { - var f = fixtures.valid[0] - var pubKey = ECPubKey.fromHex(f.pubKey) - var script = scripts.pubKeyOutput(pubKey) + describe('output script', function() { + it('is generated correctly for ' + f.pubKey, function() { + var pubKey = ECPubKey.fromHex(f.pubKey) - assert.equal(script.toHex(), f.hex) + var scriptPubKey = scripts.pubKeyOutput(pubKey) + assert.equal(scriptPubKey.toHex(), f.scriptPubKey) + }) }) }) }) - // FIXME: bad - describe('pay-to-scriptHash', function() { - it('matches the test data', function() { - var f = fixtures.valid[1] - var address = Address.fromBase58Check('3NukJ6fYZJ5Kk8bPjycAnruZkE5Q7UW7i8') - var script = scripts.scriptHashOutput(address.hash) + describe('pubKeyHash', function() { + fixtures2.valid.pubKeyHash.forEach(function(f) { + var pubKey = ECPubKey.fromHex(f.pubKey) + var address = pubKey.getAddress() - assert.equal(script.toHex(), f.hex) - }) - }) + describe('input script', function() { + it('is generated correctly for ' + address, function() { + var signature = new Buffer(f.signature, 'hex') - // FIXME: bad - describe('2-of-3 Multi-Signature scriptPubKey', function() { - var pubKeys + var scriptSig = scripts.pubKeyHashInput(signature, pubKey) + assert.equal(scriptSig.toHex(), f.scriptSig) + }) + }) - beforeEach(function() { - pubKeys = [ - '02ea1297665dd733d444f31ec2581020004892cdaaf3dd6c0107c615afb839785f', - '02fab2dea1458990793f56f42e4a47dbf35a12a351f26fa5d7e0cc7447eaafa21f', - '036c6802ce7e8113723dd92cdb852e492ebb157a871ca532c3cb9ed08248ff0e19' - ].map(ECPubKey.fromHex) + describe('output script', function() { + it('is generated correctly for ' + address, function() { + var scriptPubKey = scripts.pubKeyHashOutput(address.hash) + assert.equal(scriptPubKey.toHex(), f.scriptPubKey) + }) + }) }) + }) - it('should create valid redeemScript', function() { - var redeemScript = scripts.multisigOutput(2, pubKeys) - - var hash160 = crypto.hash160(new Buffer(redeemScript.buffer)) - var multisigAddress = new Address(hash160, networks.bitcoin.scripthash) - - assert.equal(multisigAddress.toString(), '32vYjxBb7pHJJyXgNk8UoK3BdRDxBzny2v') + describe('multisig', function() { + fixtures2.valid.multisig.forEach(function(f) { + var pubKeys = f.pubKeys.map(ECPubKey.fromHex) + var scriptPubKey = scripts.multisigOutput(pubKeys.length, pubKeys) + + // FIXME: some missing test data for now + if (f.scriptSig) { + describe('input script', function() { + it('is generated correctly for ' + scriptPubKey.toHex(), function() { + var signatures = f.signatures.map(function(signature) { + return new Buffer(signature, 'hex') + }) + + var scriptSig = scripts.multisigInput(signatures) + assert.equal(scriptSig.toHex(), f.scriptSig) + }) + }) + } + + describe('output script', function() { + it('is generated correctly for ' + scriptPubKey.toHex(), function() { + assert.equal(scriptPubKey.toHex(), f.scriptPubKey) + }) + }) }) - it('should throw on not enough pubKeys provided', function() { - assert.throws(function() { - scripts.multisigOutput(4, pubKeys) - }, /Not enough pubKeys provided/) + fixtures2.invalid.multisig.forEach(function(f) { + var pubKeys = f.pubKeys.map(ECPubKey.fromHex) + var scriptPubKey = scripts.multisigOutput(pubKeys.length, pubKeys) + + if (f.scriptPubKey) { + describe('output script', function() { + it('throws on ' + f.exception, function() { + assert.throws(function() { + scripts.multisigOutput(f.m, pubKeys) + }, new RegExp(f.exception)) + }) + }) + } else { + describe('input script', function() { + it('throws on ' + f.exception, function() { + var signatures = f.signatures.map(function(signature) { + return new Buffer(signature, 'hex') + }) + + assert.throws(function() { + scripts.multisigInput(signatures, scriptPubKey) + }, new RegExp(f.exception)) + }) + }) + } }) }) - // FIXME: bad - describe('2-of-2 Multisig scriptSig', function() { - var pubKeys = [ - '02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1', - '0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a' - ].map(ECPubKey.fromHex) - var signatures = [ - '304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801', - '3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501' - ].map(h2b) - var expected = '0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d14050147522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae' - - it('should create a valid P2SH multisig scriptSig', function() { - var redeemScript = scripts.multisigOutput(2, pubKeys) - var redeemInput = scripts.multisigInput(signatures) - - var scriptSig = scripts.scriptHashInput(redeemInput, redeemScript) - - assert.equal(b2h(scriptSig.buffer), expected) - }) + describe('scripthash', function() { + fixtures2.valid.scripthash.forEach(function(f) { + var redeemScript = Script.fromHex(f.redeemScript) + var redeemScriptSig = Script.fromHex(f.redeemScriptSig) - it('should throw on not enough signatures', function() { - var redeemScript = scripts.multisigOutput(2, pubKeys) + var address = Address.fromOutputScript(Script.fromHex(f.scriptPubKey)) - assert.throws(function() { - scripts.multisigInput(signatures.slice(1), redeemScript) - }, /Not enough signatures provided/) + describe('input script', function() { + it('is generated correctly for ' + address, function() { + var scriptSig = scripts.scriptHashInput(redeemScriptSig, redeemScript) + + assert.equal(scriptSig.toHex(), f.scriptSig) + }) + }) + + describe('output script', function() { + it('is generated correctly for ' + address, function() { + var scriptPubKey = scripts.scriptHashOutput(redeemScript.getHash()) + + assert.equal(scriptPubKey.toHex(), f.scriptPubKey) + }) + }) }) }) }) From 9b89a267ca928d0574b13a4568b0bbc3db253d2d Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 23:44:52 +1000 Subject: [PATCH 7/8] scripts: remove unused imports --- test/scripts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/scripts.js b/test/scripts.js index b6b07e5..8aed551 100644 --- a/test/scripts.js +++ b/test/scripts.js @@ -1,6 +1,4 @@ var assert = require('assert') -var crypto = require('../src/crypto') -var networks = require('../src/networks') var scripts = require('../src/scripts') var Address = require('../src/address') From e49e1796d53898f35bfd733242699430115bd16b Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 14 Jun 2014 23:48:26 +1000 Subject: [PATCH 8/8] Transaction: remove untested TransactionIn constructor params --- src/transaction.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/transaction.js b/src/transaction.js index eed58ed..6ff1c23 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -384,16 +384,9 @@ Transaction.prototype.estimateFee = function(feePerKb){ return feePerKb * Math.ceil(size / 1000) } -var TransactionIn = function (data) { - if (typeof data == "string") { - this.outpoint = { hash: data.split(':')[0], index: data.split(':')[1] } - } else if (data.outpoint) { - this.outpoint = data.outpoint - } else { - this.outpoint = { hash: data.hash, index: data.index } - } - - assert(data.script, 'Invalid TxIn parameters') +function TransactionIn(data) { + assert(data.outpoint && data.script, 'Invalid TxIn parameters') + this.outpoint = data.outpoint this.script = data.script this.sequence = data.sequence == undefined ? DEFAULT_SEQUENCE : data.sequence } @@ -413,8 +406,6 @@ function TransactionOut(data) { this.script = data.script this.value = data.value this.address = data.address - - if (data.address) this.address = data.address } TransactionOut.prototype.clone = function() {