From 693e39c061e09f4065096639aec8d8b9602b2556 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 26 Nov 2015 12:07:04 +1100 Subject: [PATCH 1/3] script: use Buffer.isBuffer consistently --- src/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script.js b/src/script.js index 5be3c68..6f9b21e 100644 --- a/src/script.js +++ b/src/script.js @@ -16,7 +16,7 @@ var REVERSE_OPS = (function () { var OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 function toASM (chunks) { - if (types.Buffer(chunks)) { + if (Buffer.isBuffer(chunks)) { chunks = decompile(chunks) } @@ -43,7 +43,7 @@ function fromASM (asm) { function compile (chunks) { // TODO: remove me - if (types.Buffer(chunks)) return chunks + if (Buffer.isBuffer(chunks)) return chunks typeforce(types.Array, chunks) From 881a23f9d5a837e97950a3706af46c2905c96c08 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 26 Nov 2015 12:07:32 +1100 Subject: [PATCH 2/3] txbuilder: rename tx.outs.length to nOutputs --- src/transaction_builder.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/transaction_builder.js b/src/transaction_builder.js index 503ee92..5c94ce6 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -227,13 +227,13 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu } TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) { - var tx = this.tx + var nOutputs = this.tx.outs.length var valid = this.inputs.every(function (input, index) { if (input.hashType === undefined) return true - var hashType = input.hashType & 0x1f - return hashType === Transaction.SIGHASH_NONE || - (hashType === Transaction.SIGHASH_SINGLE && index < tx.outs.length) + var hashTypeMod = input.hashType & 0x1f + return (hashTypeMod === Transaction.SIGHASH_NONE) || + (hashTypeMod === Transaction.SIGHASH_SINGLE && index < nOutputs) }) if (!valid) throw new Error('No, this would invalidate signatures') @@ -243,7 +243,7 @@ TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) { scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network) } - return tx.addOutput(scriptPubKey, value) + return this.tx.addOutput(scriptPubKey, value) } TransactionBuilder.prototype.build = function () { From 540a6643ac44aec956dd2b99493474171acdd579 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 26 Nov 2015 12:40:26 +1100 Subject: [PATCH 3/3] txbuilder: clarify SIGHASH invalidation logic in addInput/addOutput --- src/transaction_builder.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/transaction_builder.js b/src/transaction_builder.js index 5c94ce6..73fd12b 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -208,13 +208,16 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu input.prevOutType = prevOutType } - var valid = this.inputs.every(function (input2) { - if (input2.hashType === undefined) return true - - return input2.hashType & Transaction.SIGHASH_ANYONECANPAY - }) - - if (!valid) throw new Error('No, this would invalidate signatures') + // if signatures exist, adding inputs is only acceptable if SIGHASH_ANYONECANPAY is used + // throw if any signatures *didn't* use SIGHASH_ANYONECANPAY + if (!this.inputs.every(function (otherInput) { + // no signature + if (otherInput.hashType === undefined) return true + + return otherInput.hashType & Transaction.SIGHASH_ANYONECANPAY + })) { + throw new Error('No, this would invalidate signatures') + } var prevOut = txHash.toString('hex') + ':' + vout if (this.prevTxMap[prevOut]) throw new Error('Transaction is already an input') @@ -228,15 +231,24 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) { var nOutputs = this.tx.outs.length - var valid = this.inputs.every(function (input, index) { + + // if signatures exist, adding outputs is only acceptable if SIGHASH_NONE or SIGHASH_SINGLE is used + // throws if any signatures didn't use SIGHASH_NONE|SIGHASH_SINGLE + if (!this.inputs.every(function (input, index) { + // no signature if (input.hashType === undefined) return true var hashTypeMod = input.hashType & 0x1f - return (hashTypeMod === Transaction.SIGHASH_NONE) || - (hashTypeMod === Transaction.SIGHASH_SINGLE && index < nOutputs) - }) + if (hashTypeMod === Transaction.SIGHASH_NONE) return true + if (hashTypeMod === Transaction.SIGHASH_SINGLE) { + // account for SIGHASH_SINGLE signing of a non-existing output, aka the "SIGHASH_SINGLE" bug + return index < nOutputs + } - if (!valid) throw new Error('No, this would invalidate signatures') + return false + })) { + throw new Error('No, this would invalidate signatures') + } // Attempt to get a script if it's a base58 address string if (typeof scriptPubKey === 'string') {