From 5de6818fcbdd5584bb8bca45747ee26310e120eb Mon Sep 17 00:00:00 2001
From: Kirill Fomichev <fanatid@ya.ru>
Date: Mon, 23 Nov 2015 17:05:06 +0300
Subject: [PATCH] Fix TransactionBuilder.addOutput

---
 src/transaction_builder.js  |  9 ++++++---
 test/transaction_builder.js | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/transaction_builder.js b/src/transaction_builder.js
index e0dbc25..503ee92 100644
--- a/src/transaction_builder.js
+++ b/src/transaction_builder.js
@@ -227,10 +227,13 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu
 }
 
 TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) {
-  var valid = this.inputs.every(function (input) {
+  var tx = this.tx
+  var valid = this.inputs.every(function (input, index) {
     if (input.hashType === undefined) return true
 
-    return (input.hashType & 0x1f) === Transaction.SIGHASH_SINGLE
+    var hashType = input.hashType & 0x1f
+    return hashType === Transaction.SIGHASH_NONE ||
+           (hashType === Transaction.SIGHASH_SINGLE && index < tx.outs.length)
   })
 
   if (!valid) throw new Error('No, this would invalidate signatures')
@@ -240,7 +243,7 @@ TransactionBuilder.prototype.addOutput = function (scriptPubKey, value) {
     scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network)
   }
 
-  return this.tx.addOutput(scriptPubKey, value)
+  return tx.addOutput(scriptPubKey, value)
 }
 
 TransactionBuilder.prototype.build = function () {
diff --git a/test/transaction_builder.js b/test/transaction_builder.js
index dc1877a..1ee696f 100644
--- a/test/transaction_builder.js
+++ b/test/transaction_builder.js
@@ -202,6 +202,34 @@ describe('TransactionBuilder', function () {
       }, /2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9 has no matching Script/)
     })
 
+    it('add second output after signed first input with SIGHASH_NONE', function () {
+      txb.addInput(txHash, 0)
+      txb.addOutput(scripts[0], 2000)
+      txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE)
+      assert.equal(txb.addOutput(scripts[1], 9000), 1)
+    })
+
+    it('add first output after signed first input with SIGHASH_NONE', function () {
+      txb.addInput(txHash, 0)
+      txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE)
+      assert.equal(txb.addOutput(scripts[0], 2000), 0)
+    })
+
+    it('add second output after signed first input with SIGHASH_SINGLE', function () {
+      txb.addInput(txHash, 0)
+      txb.addOutput(scripts[0], 2000)
+      txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE)
+      assert.equal(txb.addOutput(scripts[1], 9000), 1)
+    })
+
+    it('add first output after signed first input with SIGHASH_SINGLE', function () {
+      txb.addInput(txHash, 0)
+      txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE)
+      assert.throws(function () {
+        txb.addOutput(scripts[0], 2000)
+      }, /No, this would invalidate signatures/)
+    })
+
     it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', function () {
       txb.addInput(txHash, 0)
       txb.addOutput(scripts[0], 2000)