diff --git a/src/transaction_builder.js b/src/transaction_builder.js index ddddb1a..4180c5e 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -239,6 +239,7 @@ TransactionBuilder.prototype.sign = function(index, privKey, redeemScript, hashT scriptType = scripts.classifyOutput(redeemScript) assert.notEqual(scriptType, 'scripthash', 'RedeemScript can\'t be P2SH') + assert.notEqual(scriptType, 'nulldata', 'RedeemScript not supported (nulldata)') assert.notEqual(scriptType, 'nonstandard', 'RedeemScript not supported (nonstandard)') hash = this.tx.hashForSignature(index, redeemScript, hashType) diff --git a/test/fixtures/transaction_builder.json b/test/fixtures/transaction_builder.json index 86ae18b..c184ef0 100644 --- a/test/fixtures/transaction_builder.json +++ b/test/fixtures/transaction_builder.json @@ -190,6 +190,148 @@ } ], "sign": [ + { + "exception": "pubkeyhash doesn\\'t support multiple signatures", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "privKeys": [ + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + ], + "throws": 1 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, + { + "exception": "RedeemScript not supported \\(nulldata\\)", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "privKeys": [ + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + ], + "redeemScript": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474", + "throws": 0 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, + { + "exception": "PrevOutScript is P2SH, missing redeemScript", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "prevTxScript": "OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL", + "privKeys": [ + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + ], + "throws": 0 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, + { + "exception": "RedeemScript can\\'t be P2SH", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "privKeys": [ + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + ], + "redeemScript": "OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL", + "throws": 0 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, + { + "exception": "PrevOutScript must be P2SH", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "prevTxScript": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "privKeys": [ + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + ], + "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG", + "throws": 0 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, + { + "exception": "Signature already exists", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "privKeys": [ + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", + "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + ], + "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG", + "throws": 1 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, + { + "exception": "privateKey cannot sign for this input", + "inputs": [ + { + "index": 1, + "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "privKeys": [ + "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx" + ], + "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG", + "throws": 0 + } + ], + "outputs": [ + { + "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "value": 1000 + } + ] + }, { "exception": "nulldata not supported", "inputs": [ @@ -197,10 +339,10 @@ "index": 0, "prevTx": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "prevTxScript": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474", - "throws": true, "privKeys": [ "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - ] + ], + "throws": 0 } ], "outputs": [ diff --git a/test/transaction_builder.js b/test/transaction_builder.js index 47f5d3e..6d304f0 100644 --- a/test/transaction_builder.js +++ b/test/transaction_builder.js @@ -106,27 +106,6 @@ describe('TransactionBuilder', function() { }) }) - it('throws if scriptType doesn\'t support multiple signatures', function() { - txb.addInput(prevTxHash, 0) - txb.sign(0, privKey) - - assert.throws(function() { - txb.sign(0, privKey) - }, /pubkeyhash doesn\'t support multiple signatures/) - }) - - describe('when redeemScript is undefined', function() { - it('throws if prevOutScript is P2SH', function() { - var privScriptP2SH = scripts.scriptHashOutput(privScript.getHash()) - - txb.addInput(prevTxHash, 0, undefined, privScriptP2SH) - - assert.throws(function() { - txb.sign(0, privKey) - }, /PrevOutScript is P2SH, missing redeemScript/) - }) - }) - describe('when redeemScript is defined', function() { it('assumes scriptHash', function() { txb.addInput(prevTxHash, 0) @@ -135,24 +114,6 @@ describe('TransactionBuilder', function() { assert.equal(txb.signatures[0].redeemScript, privScript) }) - it('throws if prevOutScript is not P2SH', function() { - txb.addInput(prevTx, 0) - - assert.throws(function() { - txb.sign(0, privKey, privScript) - }, /PrevOutScript must be P2SH/) - }) - - it('throws if redeemScript is P2SH', function() { - txb.addInput(prevTxHash, 0) - - var privScriptP2SH = scripts.scriptHashOutput(privScript.getHash()) - - assert.throws(function() { - txb.sign(0, privKey, privScriptP2SH) - }, /RedeemScript can\'t be P2SH/) - }) - it('throws if hashType is inconsistent', function() { var redeemScript = scripts.multisigOutput(1, [privKey.pub]) @@ -175,35 +136,6 @@ describe('TransactionBuilder', function() { txb.sign(0, privKey, otherScript) }, /Inconsistent redeemScript/) }) - - it('throws if redeemScript not supported', function() { - txb.addInput(prevTxHash, 0) - - assert.throws(function() { - txb.sign(0, privKey, Script.EMPTY) - }, /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/) }) fixtures.invalid.sign.forEach(function(f) { @@ -231,10 +163,10 @@ describe('TransactionBuilder', function() { redeemScript = Script.fromASM(input.redeemScript) } - input.privKeys.forEach(function(wif) { + input.privKeys.forEach(function(wif, i) { var privKey = ECKey.fromWIF(wif) - if (!input.throws) { + if (input.throws !== i) { txb.sign(index, privKey, redeemScript) } else {