From b0317be4d53e1f285a32e4a835e246230947267b Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 13 Jun 2014 16:43:47 +1000
Subject: [PATCH 01/29] tests: formatting

---
 test/transaction.js | 52 ++++++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/test/transaction.js b/test/transaction.js
index e9bbec6..c9ffab0 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -44,15 +44,15 @@ describe('Transaction', function() {
       assert.equal(buffer.toString('hex'), serializedTx)
     })
 
-    it('decodes version correctly', function(){
+    it('decodes version correctly', function() {
       assert.equal(tx.version, 1)
     })
 
-    it('decodes locktime correctly', function(){
+    it('decodes locktime correctly', function() {
       assert.equal(tx.locktime, 0)
     })
 
-    it('decodes inputs correctly', function(){
+    it('decodes inputs correctly', function() {
       assert.equal(tx.ins.length, 1)
 
       var input = tx.ins[0]
@@ -65,7 +65,7 @@ describe('Transaction', function() {
                    "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
     })
 
-    it('decodes outputs correctly', function(){
+    it('decodes outputs correctly', function() {
       assert.equal(tx.outs.length, 1)
 
       var output = tx.outs[0]
@@ -74,7 +74,7 @@ describe('Transaction', function() {
       assert.deepEqual(output.script, Address.fromBase58Check('n1gqLjZbRH1biT5o4qiVMiNig8wcCPQeB9').toOutputScript())
     })
 
-    it('assigns hash to deserialized object', function(){
+    it('assigns hash to deserialized object', function() {
       var hashHex = "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c"
       assert.equal(tx.hash, hashHex)
     })
@@ -107,18 +107,18 @@ describe('Transaction', function() {
       tx = new Transaction()
     })
 
-    describe('addInput', function(){
-      it('allows a Transaction object to be passed in', function(){
+    describe('addInput', function() {
+      it('allows a Transaction object to be passed in', function() {
         tx.addInput(prevTx, 0)
         verifyTransactionIn()
       })
 
-      it('allows a Transaction hash to be passed in', function(){
+      it('allows a Transaction hash to be passed in', function() {
         tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57", 0)
         verifyTransactionIn()
       })
 
-      it('allows a TransactionIn object to be passed in', function(){
+      it('allows a TransactionIn object to be passed in', function() {
         var txCopy = tx.clone()
         txCopy.addInput(prevTx, 0)
         var transactionIn = txCopy.ins[0]
@@ -127,7 +127,7 @@ describe('Transaction', function() {
         verifyTransactionIn()
       })
 
-      it('allows a string in the form of txhash:index to be passed in', function(){
+      it('allows a string in the form of txhash:index to be passed in', function() {
         tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57:0")
         verifyTransactionIn()
       })
@@ -145,23 +145,23 @@ describe('Transaction', function() {
       }
     })
 
-    describe('addOutput', function(){
-      it('allows an address and a value to be passed in', function(){
+    describe('addOutput', function() {
+      it('allows an address and a value to be passed in', function() {
         tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3", 40000)
         verifyTransactionOut()
       })
 
-      it('allows an Address object and value to be passed in', function(){
+      it('allows an Address object and value to be passed in', function() {
         tx.addOutput(Address.fromBase58Check('15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3'), 40000)
         verifyTransactionOut()
       })
 
-      it('allows a string in the form of address:index to be passed in', function(){
+      it('allows a string in the form of address:index to be passed in', function() {
         tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000")
         verifyTransactionOut()
       })
 
-      it('allows a TransactionOut object to be passed in', function(){
+      it('allows a TransactionOut object to be passed in', function() {
         var txCopy = tx.clone()
         txCopy.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000")
         var transactionOut = txCopy.outs[0]
@@ -170,7 +170,7 @@ describe('Transaction', function() {
         verifyTransactionOut()
       })
 
-      it('supports alternative networks', function(){
+      it('supports alternative networks', function() {
         var addr = 'mkHJaNR7uuwRG1JrmTZsV4MszaTKjCBvCR'
 
         tx.addOutput(addr, 40000)
@@ -179,7 +179,7 @@ describe('Transaction', function() {
         assert.equal(tx.outs[0].address.toString(), addr)
       })
 
-      function verifyTransactionOut(){
+      function verifyTransactionOut() {
         assert.equal(tx.outs.length, 1)
 
         var output = tx.outs[0]
@@ -188,8 +188,8 @@ describe('Transaction', function() {
       }
     })
 
-    describe('sign', function(){
-      it('works', function(){
+    describe('sign', function() {
+      it('works', function() {
         tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57:0")
         tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000")
         tx.addOutput("1Bu3bhwRmevHLAy1JrRB6AfcxfgDG2vXRd:50000")
@@ -204,14 +204,14 @@ describe('Transaction', function() {
       })
     })
 
-    describe('validateInput', function(){
+    describe('validateInput', function() {
       var validTx
 
       beforeEach(function() {
         validTx = Transaction.fromHex(fixtureTx2Hex)
       })
 
-      it('returns true for valid signature', function(){
+      it('returns true for valid signature', function() {
         var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
         var script = prevTx.outs[0].script
         var sig = new Buffer(validTx.ins[0].script.chunks[0])
@@ -220,23 +220,23 @@ describe('Transaction', function() {
       })
     })
 
-    describe('estimateFee', function(){
-      it('works for fixture tx 1', function(){
+    describe('estimateFee', function() {
+      it('works for fixture tx 1', function() {
         var tx = Transaction.fromHex(fixtureTx1Hex)
         assert.equal(tx.estimateFee(), 20000)
       })
 
-      it('works for fixture big tx', function(){
+      it('works for fixture big tx', function() {
         var tx = Transaction.fromHex(fixtureTxBigHex)
         assert.equal(tx.estimateFee(), 60000)
       })
 
-      it('allow feePerKb to be passed in as an argument', function(){
+      it('allow feePerKb to be passed in as an argument', function() {
         var tx = Transaction.fromHex(fixtureTx2Hex)
         assert.equal(tx.estimateFee(10000), 10000)
       })
 
-      it('allow feePerKb to be set to 0', function(){
+      it('allow feePerKb to be set to 0', function() {
         var tx = Transaction.fromHex(fixtureTx2Hex)
         assert.equal(tx.estimateFee(0), 0)
       })

From 8b5647b0b96777c610f976380919e5f25b9b0179 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 16 May 2014 17:12:39 +1000
Subject: [PATCH 02/29] Transaction: remove TxIn/TxOut exports

---
 src/index.js         | 4 +---
 src/transaction.js   | 6 +-----
 src/wallet.js        | 2 +-
 test/bitcoin.core.js | 2 +-
 test/transaction.js  | 2 +-
 test/wallet.js       | 2 +-
 6 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/src/index.js b/src/index.js
index 5af8210..fc46f9b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -15,9 +15,7 @@ module.exports = {
   HDNode: require('./hdnode'),
   Script: require('./script'),
   scripts: require('./scripts'),
-  Transaction: T.Transaction,
-  TransactionIn: T.TransactionIn,
-  TransactionOut: T.TransactionOut,
+  Transaction: require('./transaction'),
   networks: require('./networks'),
   Wallet: require('./wallet')
 }
diff --git a/src/transaction.js b/src/transaction.js
index 6ff1c23..7308d1b 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -416,8 +416,4 @@ TransactionOut.prototype.clone = function() {
   })
 }
 
-module.exports = {
-  Transaction: Transaction,
-  TransactionIn: TransactionIn,
-  TransactionOut: TransactionOut
-}
+module.exports = Transaction
diff --git a/src/wallet.js b/src/wallet.js
index aa9355c..b4acd3f 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -4,7 +4,7 @@ var rng = require('secure-random')
 
 var Address = require('./address')
 var HDNode = require('./hdnode')
-var Transaction = require('./transaction').Transaction
+var Transaction = require('./transaction')
 
 function Wallet(seed, network) {
   network = network || networks.bitcoin
diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js
index 4cd8238..b058385 100644
--- a/test/bitcoin.core.js
+++ b/test/bitcoin.core.js
@@ -6,7 +6,7 @@ var networks = require('../src/networks')
 var Address = require('../src/address')
 var BigInteger = require('bigi')
 var ECKey = require('../src/eckey')
-var Transaction = require('../src/transaction').Transaction
+var Transaction = require('../src/transaction')
 var Script = require('../src/script')
 
 var base58_encode_decode = require("./fixtures/core/base58_encode_decode.json")
diff --git a/test/transaction.js b/test/transaction.js
index c9ffab0..8341fec 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -4,7 +4,7 @@ var scripts = require('../src/scripts')
 
 var Address = require('../src/address')
 var ECKey = require('../src/eckey')
-var Transaction = require('../src/transaction').Transaction
+var Transaction = require('../src/transaction')
 var Script = require('../src/script')
 
 var fixtureTxes = require('./fixtures/mainnet_tx')
diff --git a/test/wallet.js b/test/wallet.js
index 0d857ad..88b7dcd 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -6,7 +6,7 @@ var scripts = require('../src/scripts')
 
 var Address = require('../src/address')
 var HDNode = require('../src/hdnode')
-var Transaction = require('../src/transaction').Transaction
+var Transaction = require('../src/transaction')
 var Wallet = require('../src/wallet')
 
 var fixtureTxes = require('./fixtures/mainnet_tx')

From 40f0c9116262d8098374649815a37924f6b20d4c Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 16 May 2014 17:20:45 +1000
Subject: [PATCH 03/29] Transaction: use TxIn/TxOut consistently

---
 src/transaction.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 7308d1b..7403696 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -293,14 +293,14 @@ Transaction.fromBuffer = function(buffer) {
     var script = readSlice(scriptLen)
     var sequence = readUInt32()
 
-    ins.push({
+    ins.push(new TransactionIn({
       outpoint: {
         hash: hash.toString('hex'),
-        index: vout,
+        index: vout
       },
       script: Script.fromBuffer(script),
       sequence: sequence
-    })
+    }))
   }
 
   var voutLen = readVarInt()
@@ -310,10 +310,10 @@ Transaction.fromBuffer = function(buffer) {
     var scriptLen = readVarInt()
     var script = readSlice(scriptLen)
 
-    outs.push({
+    outs.push(new TransactionOut({
       value: value,
       script: Script.fromBuffer(script)
-    })
+    }))
   }
 
   var locktime = readUInt32()

From 1f2becbb455c4e79df1399685898a40396a1f7c4 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 19 May 2014 08:49:41 +1000
Subject: [PATCH 04/29] Transaction: move all constants to top

---
 src/transaction.js | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 7403696..a4d18a8 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -12,6 +12,10 @@ var ECKey = require('./eckey')
 var Script = require('./script')
 
 var DEFAULT_SEQUENCE = 0xffffffff
+var SIGHASH_ALL = 0x01
+var SIGHASH_NONE = 0x02
+var SIGHASH_SINGLE = 0x03
+var SIGHASH_ANYONECANPAY = 0x80
 
 function Transaction(doc) {
   if (!(this instanceof Transaction)) { return new Transaction(doc) }
@@ -179,11 +183,6 @@ Transaction.prototype.toHex = function() {
   return this.toBuffer().toString('hex')
 }
 
-var SIGHASH_ALL = 0x01
-var SIGHASH_NONE = 0x02
-var SIGHASH_SINGLE = 0x03
-var SIGHASH_ANYONECANPAY = 0x80
-
 /**
  * Hash transaction for signing a specific input.
  *

From a6b9dd9473ca04c11f15804fd1eefa39f36c0566 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 19 May 2014 09:31:16 +1000
Subject: [PATCH 05/29] Transaction: remove hash:index notation

---
 src/transaction.js  | 31 +++++++------------------------
 src/wallet.js       |  5 +++--
 test/transaction.js | 18 ++++--------------
 3 files changed, 14 insertions(+), 40 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index a4d18a8..c75b69b 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -29,15 +29,15 @@ function Transaction(doc) {
     if (doc.version) this.version = doc.version;
     if (doc.locktime) this.locktime = doc.locktime;
     if (doc.ins && doc.ins.length) {
-      doc.ins.forEach(function(input) {
-        this.addInput(new TransactionIn(input))
-      }, this)
+      this.ins = doc.ins.map(function(input) {
+        return new TransactionIn(input)
+      })
     }
 
     if (doc.outs && doc.outs.length) {
-      doc.outs.forEach(function(output) {
-        this.addOutput(new TransactionOut(output))
-      }, this)
+      this.outs = doc.outs.map(function(output) {
+        return new TransactionOut(output)
+      })
     }
 
     this.hash = this.hash || this.getHash()
@@ -52,7 +52,6 @@ function Transaction(doc) {
  * - An existing TransactionIn object
  * - A transaction and an index
  * - A transaction hash and an index
- * - A single string argument of the form txhash:index
  *
  * Note that this method does not sign the created input.
  */
@@ -62,15 +61,7 @@ Transaction.prototype.addInput = function (tx, outIndex) {
     return
   }
 
-  var hash
-  if (arguments[0].length > 65) {
-    var args = arguments[0].split(':')
-    hash = args[0]
-    outIndex = parseInt(args[1])
-
-  } else {
-    hash = typeof tx === "string" ? tx : tx.hash
-  }
+  var hash = typeof tx === "string" ? tx : tx.hash
 
   this.ins.push(new TransactionIn({
     outpoint: {
@@ -88,9 +79,7 @@ Transaction.prototype.addInput = function (tx, outIndex) {
  *
  * i) An existing TransactionOut object
  * ii) An address object or a string address, and a value
- * iii) An address:value string
  *
- * FIXME: This is a bit convoluted
  */
 Transaction.prototype.addOutput = function (address, value) {
   if (arguments[0] instanceof TransactionOut) {
@@ -99,12 +88,6 @@ Transaction.prototype.addOutput = function (address, value) {
   }
 
   if (typeof address === 'string') {
-    if (arguments[0].indexOf(':') >= 0) {
-      var args = arguments[0].split(':')
-      address = args[0]
-      value = parseInt(args[1])
-    }
-
     address = Address.fromBase58Check(address)
   }
 
diff --git a/src/wallet.js b/src/wallet.js
index b4acd3f..657f722 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -190,11 +190,12 @@ function Wallet(seed, network) {
     for (var i = 0; i < utxos.length; ++i) {
       var utxo = utxos[i]
 
-      tx.addInput(utxo.receive)
-      accum += utxo.value
+      var outpoint = utxo.receive.split(':')
+      tx.addInput(outpoint[0], parseInt(outpoint[1]))
 
       var fee = fixedFee == undefined ? estimateFeePadChangeOutput(tx) : fixedFee
 
+      accum += utxo.value
       subTotal = value + fee
       if (accum >= subTotal) {
         var change = accum - subTotal
diff --git a/test/transaction.js b/test/transaction.js
index 8341fec..e76d39c 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -127,11 +127,6 @@ describe('Transaction', function() {
         verifyTransactionIn()
       })
 
-      it('allows a string in the form of txhash:index to be passed in', function() {
-        tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57:0")
-        verifyTransactionIn()
-      })
-
       function verifyTransactionIn() {
         assert.equal(tx.ins.length, 1)
 
@@ -156,14 +151,9 @@ describe('Transaction', function() {
         verifyTransactionOut()
       })
 
-      it('allows a string in the form of address:index to be passed in', function() {
-        tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000")
-        verifyTransactionOut()
-      })
-
       it('allows a TransactionOut object to be passed in', function() {
         var txCopy = tx.clone()
-        txCopy.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000")
+        txCopy.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3", 40000)
         var transactionOut = txCopy.outs[0]
 
         tx.addOutput(transactionOut)
@@ -190,9 +180,9 @@ describe('Transaction', function() {
 
     describe('sign', function() {
       it('works', function() {
-        tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57:0")
-        tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000")
-        tx.addOutput("1Bu3bhwRmevHLAy1JrRB6AfcxfgDG2vXRd:50000")
+        tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57", 0)
+        tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3", 40000)
+        tx.addOutput("1Bu3bhwRmevHLAy1JrRB6AfcxfgDG2vXRd", 50000)
 
         var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
         tx.sign(0, key)

From 5bd636cab73b12a7e773611adb30ccb3cac8768f Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 19 May 2014 14:14:07 +1000
Subject: [PATCH 06/29] Transaction: remove TxIn/TxOut from API

---
 src/transaction.js  | 24 ++++++------------------
 test/transaction.js | 18 ------------------
 2 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index c75b69b..a99dbd2 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -49,18 +49,12 @@ function Transaction(doc) {
  *
  * Can be called with any of:
  *
- * - An existing TransactionIn object
  * - A transaction and an index
  * - A transaction hash and an index
  *
  * Note that this method does not sign the created input.
  */
 Transaction.prototype.addInput = function (tx, outIndex) {
-  if (arguments[0] instanceof TransactionIn) {
-    this.ins.push(arguments[0])
-    return
-  }
-
   var hash = typeof tx === "string" ? tx : tx.hash
 
   this.ins.push(new TransactionIn({
@@ -77,16 +71,10 @@ Transaction.prototype.addInput = function (tx, outIndex) {
  *
  * Can be called with:
  *
- * i) An existing TransactionOut object
- * ii) An address object or a string address, and a value
- *
+ * - An address object and a value
+ * - A base58 address string and a value
  */
 Transaction.prototype.addOutput = function (address, value) {
-  if (arguments[0] instanceof TransactionOut) {
-    this.outs.push(arguments[0])
-    return
-  }
-
   if (typeof address === 'string') {
     address = Address.fromBase58Check(address)
   }
@@ -222,12 +210,12 @@ Transaction.prototype.clone = function () {
   newTx.version = this.version
   newTx.locktime = this.locktime
 
-  this.ins.forEach(function(txin) {
-    newTx.addInput(txin.clone())
+  newTx.ins = this.ins.map(function(txin) {
+    return new TransactionIn(txin)
   })
 
-  this.outs.forEach(function(txout) {
-    newTx.addOutput(txout.clone())
+  newTx.outs = this.outs.map(function(txout) {
+    return new TransactionOut(txout)
   })
 
   return newTx
diff --git a/test/transaction.js b/test/transaction.js
index e76d39c..a00fa2e 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -118,15 +118,6 @@ describe('Transaction', function() {
         verifyTransactionIn()
       })
 
-      it('allows a TransactionIn object to be passed in', function() {
-        var txCopy = tx.clone()
-        txCopy.addInput(prevTx, 0)
-        var transactionIn = txCopy.ins[0]
-
-        tx.addInput(transactionIn)
-        verifyTransactionIn()
-      })
-
       function verifyTransactionIn() {
         assert.equal(tx.ins.length, 1)
 
@@ -151,15 +142,6 @@ describe('Transaction', function() {
         verifyTransactionOut()
       })
 
-      it('allows a TransactionOut object to be passed in', function() {
-        var txCopy = tx.clone()
-        txCopy.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3", 40000)
-        var transactionOut = txCopy.outs[0]
-
-        tx.addOutput(transactionOut)
-        verifyTransactionOut()
-      })
-
       it('supports alternative networks', function() {
         var addr = 'mkHJaNR7uuwRG1JrmTZsV4MszaTKjCBvCR'
 

From 867465a03f666f72787cf6235838ab32bef532db Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 19 May 2014 14:55:54 +1000
Subject: [PATCH 07/29] Transaction: support non-addressable output scripts

---
 src/transaction.js  | 25 +++++++++++++++++++------
 test/transaction.js |  5 +++++
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index a99dbd2..a30308b 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -71,18 +71,31 @@ Transaction.prototype.addInput = function (tx, outIndex) {
  *
  * Can be called with:
  *
- * - An address object and a value
  * - A base58 address string and a value
+ * - An Address object and a value
+ * - A scriptPubKey Script and a value
  */
-Transaction.prototype.addOutput = function (address, value) {
-  if (typeof address === 'string') {
-    address = Address.fromBase58Check(address)
+Transaction.prototype.addOutput = function(scriptPubKey, value) {
+  // Attempt to get a valid address if it's a base58 address string
+  if (typeof scriptPubKey === 'string') {
+    scriptPubKey = Address.fromBase58Check(scriptPubKey)
+  }
+
+  // TODO: remove me
+  var addressString
+
+  // Attempt to get a valid script if it's an Address object
+  if (scriptPubKey instanceof Address) {
+    var address = scriptPubKey
+
+    addressString = address.toBase58Check()
+    scriptPubKey = address.toOutputScript()
   }
 
   this.outs.push(new TransactionOut({
+    script: scriptPubKey,
     value: value,
-    script: address.toOutputScript(),
-    address: address // TODO: Remove me
+    address: addressString
   }))
 }
 
diff --git a/test/transaction.js b/test/transaction.js
index a00fa2e..54d1e7c 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -142,6 +142,11 @@ describe('Transaction', function() {
         verifyTransactionOut()
       })
 
+      it('allows a scriptPubKey and a value to be passed in', function() {
+        tx.addOutput(Address.fromBase58Check('15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3').toOutputScript(), 40000)
+        verifyTransactionOut()
+      })
+
       it('supports alternative networks', function() {
         var addr = 'mkHJaNR7uuwRG1JrmTZsV4MszaTKjCBvCR'
 

From bdc7131d0eb06b246e0df24acb7e9a64a0c88369 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Tue, 20 May 2014 14:07:22 +1000
Subject: [PATCH 08/29] Transaction: renames getHash to getId

In turn also removes the inherent calculation of tx.hash after deserialization.
---
 src/transaction.js  | 17 +++++++++++------
 src/wallet.js       |  6 +++---
 test/transaction.js | 15 ++++++++++-----
 test/wallet.js      |  3 +--
 4 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index a30308b..4479577 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -25,7 +25,6 @@ function Transaction(doc) {
   this.outs = []
 
   if (doc) {
-    if (doc.hash) this.hash = doc.hash;
     if (doc.version) this.version = doc.version;
     if (doc.locktime) this.locktime = doc.locktime;
     if (doc.ins && doc.ins.length) {
@@ -39,8 +38,6 @@ function Transaction(doc) {
         return new TransactionOut(output)
       })
     }
-
-    this.hash = this.hash || this.getHash()
   }
 }
 
@@ -54,8 +51,16 @@ function Transaction(doc) {
  *
  * Note that this method does not sign the created input.
  */
-Transaction.prototype.addInput = function (tx, outIndex) {
-  var hash = typeof tx === "string" ? tx : tx.hash
+Transaction.prototype.addInput = function(tx, outIndex) {
+  var hash
+
+  if (typeof tx === 'string') {
+    hash = tx
+
+  } else {
+    assert(tx instanceof Transaction, 'Unexpected input: ' + tx)
+    hash = tx.getId()
+  }
 
   this.ins.push(new TransactionIn({
     outpoint: {
@@ -209,7 +214,7 @@ Transaction.prototype.hashForSignature = function(prevOutScript, inIndex, hashTy
   return crypto.hash256(buffer)
 }
 
-Transaction.prototype.getHash = function () {
+Transaction.prototype.getId = function () {
   var buffer = crypto.hash256(this.toBuffer())
 
   // Big-endian is used for TxHash
diff --git a/src/wallet.js b/src/wallet.js
index 657f722..87293bb 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -146,9 +146,9 @@ function Wallet(seed, network) {
   }
 
   function processTx(tx, isPending) {
-    var txhash = tx.getHash()
+    var txid = tx.getId()
 
-    tx.outs.forEach(function(txOut, i){
+    tx.outs.forEach(function(txOut, i) {
       var address
 
       try {
@@ -158,7 +158,7 @@ function Wallet(seed, network) {
       }
 
       if (isMyAddress(address)) {
-        var output = txhash + ':' + i
+        var output = txid + ':' + i
 
         me.outputs[output] = {
           receive: output,
diff --git a/test/transaction.js b/test/transaction.js
index 54d1e7c..78a5ca4 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -74,11 +74,6 @@ describe('Transaction', function() {
       assert.deepEqual(output.script, Address.fromBase58Check('n1gqLjZbRH1biT5o4qiVMiNig8wcCPQeB9').toOutputScript())
     })
 
-    it('assigns hash to deserialized object', function() {
-      var hashHex = "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c"
-      assert.equal(tx.hash, hashHex)
-    })
-
     it('decodes large inputs correctly', function() {
       // transaction has only 1 input
       var tx = new Transaction()
@@ -251,5 +246,15 @@ describe('Transaction', function() {
       assert.equal(tx.toHex(), expected)
     })
   })
+
+  describe('getId', function() {
+    it('returns the expected txid', function() {
+      var tx = new Transaction()
+      tx.addInput('d6f72aab8ff86ff6289842a0424319bf2ddba85dc7c52757912297f948286389', 0)
+      tx.addOutput('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r', 1)
+
+      assert.equal(tx.getId(), '7c3275f1212fd1a2add614f47a1f1f7b6d9570a97cb88e0e2664ab1752976e9f')
+    })
+  })
 })
 
diff --git a/test/wallet.js b/test/wallet.js
index 88b7dcd..cc8b760 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -303,7 +303,6 @@ describe('Wallet', function() {
         function outputCount(){
           return Object.keys(wallet.outputs).length
         }
-
       })
 
       describe("when tx ins outpoint contains a known txhash:i", function(){
@@ -340,7 +339,7 @@ describe('Wallet', function() {
 
     function verifyOutputAdded(index, pending) {
       var txOut = tx.outs[index]
-      var key = tx.getHash() + ":" + index
+      var key = tx.getId() + ":" + index
       var output = wallet.outputs[key]
       assert.equal(output.receive, key)
       assert.equal(output.value, txOut.value)

From 2f56e63491a103ea5b57b6769945dfc8ff799063 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sun, 15 Jun 2014 00:04:02 +1000
Subject: [PATCH 09/29] Wallet: avoid transaction inspection when signing

---
 src/wallet.js | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/wallet.js b/src/wallet.js
index 87293bb..88d1695 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -183,12 +183,14 @@ function Wallet(seed, network) {
     var utxos = getCandidateOutputs(value)
     var accum = 0
     var subTotal = value
+    var addresses = []
 
     var tx = new Transaction()
     tx.addOutput(to, value)
 
     for (var i = 0; i < utxos.length; ++i) {
       var utxo = utxos[i]
+      addresses.push(utxo.address)
 
       var outpoint = utxo.receive.split(':')
       tx.addInput(outpoint[0], parseInt(outpoint[1]))
@@ -210,7 +212,7 @@ function Wallet(seed, network) {
 
     assert(accum >= subTotal, 'Not enough funds (incl. fee): ' + accum + ' < ' + subTotal)
 
-    this.sign(tx)
+    this.signWith(tx, addresses)
     return tx
   }
 
@@ -240,13 +242,15 @@ function Wallet(seed, network) {
     return me.changeAddresses[me.changeAddresses.length - 1]
   }
 
-  this.sign = function(tx) {
-    tx.ins.forEach(function(inp,i) {
-      var output = me.outputs[inp.outpoint.hash + ':' + inp.outpoint.index]
-      if (output) {
-        tx.sign(i, me.getPrivateKeyForAddress(output.address))
-      }
+  this.signWith = function(tx, addresses) {
+    assert.equal(tx.ins.length, addresses.length, 'Number of addresses must match number of transaction inputs')
+
+    addresses.forEach(function(address, i) {
+      var key = me.getPrivateKeyForAddress(address)
+
+      tx.sign(i, key)
     })
+
     return tx
   }
 

From 5551c3881235ac712c7b54edd7126926165d4a41 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sun, 15 Jun 2014 00:03:17 +1000
Subject: [PATCH 10/29] Transaction: use hash Buffer instead of hex string

---
 src/transaction.js   | 29 +++++++++++------------------
 src/wallet.js        | 10 ++++++++--
 test/bitcoin.core.js |  9 +++++++--
 test/transaction.js  |  4 ++--
 test/wallet.js       | 25 ++++++++++++++++---------
 5 files changed, 44 insertions(+), 33 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 4479577..90899b9 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -55,11 +55,16 @@ Transaction.prototype.addInput = function(tx, outIndex) {
   var hash
 
   if (typeof tx === 'string') {
-    hash = tx
+    hash = new Buffer(tx, 'hex')
+    assert.equal(hash.length, 32, 'Invalid TX hash')
+
+    // TxHash hex is big-endian, we need little-endian
+    Array.prototype.reverse.call(hash)
 
   } else {
-    assert(tx instanceof Transaction, 'Unexpected input: ' + tx)
-    hash = tx.getId()
+    assert(tx instanceof Transaction, 'Expected Transaction, got ' + tx)
+    hash = crypto.hash256(tx.toBuffer())
+
   }
 
   this.ins.push(new TransactionIn({
@@ -142,13 +147,8 @@ Transaction.prototype.toBuffer = function () {
   writeUInt32(this.version)
   writeVarInt(this.ins.length)
 
-  this.ins.forEach(function(txin) {
-    var hash = new Buffer(txin.outpoint.hash, 'hex') // FIXME: Performance: convert on tx.addInput instead
-
-    // TxHash hex is big-endian, we need little-endian
-    Array.prototype.reverse.call(hash)
-
-    writeSlice(hash)
+  this.ins.forEach(function(txin, i) {
+    writeSlice(txin.outpoint.hash)
     writeUInt32(txin.outpoint.index)
     writeVarInt(txin.script.buffer.length)
     writeSlice(txin.script.buffer)
@@ -240,9 +240,6 @@ Transaction.prototype.clone = function () {
 }
 
 Transaction.fromBuffer = function(buffer) {
-  // Copy because we mutate (reverse TxOutHashs)
-  buffer = new Buffer(buffer)
-
   var offset = 0
   function readSlice(n) {
     offset += n
@@ -272,10 +269,6 @@ Transaction.fromBuffer = function(buffer) {
 
   for (var i = 0; i < vinLen; ++i) {
     var hash = readSlice(32)
-
-    // TxHash is little-endian, we want big-endian hex
-    Array.prototype.reverse.call(hash)
-
     var vout = readUInt32()
     var scriptLen = readVarInt()
     var script = readSlice(scriptLen)
@@ -283,7 +276,7 @@ Transaction.fromBuffer = function(buffer) {
 
     ins.push(new TransactionIn({
       outpoint: {
-        hash: hash.toString('hex'),
+        hash: hash,
         index: vout
       },
       script: Script.fromBuffer(script),
diff --git a/src/wallet.js b/src/wallet.js
index 88d1695..4410b36 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -169,9 +169,15 @@ function Wallet(seed, network) {
       }
     })
 
-    tx.ins.forEach(function(txIn, i){
+    tx.ins.forEach(function(txIn, i) {
       var op = txIn.outpoint
-      var output = op.hash + ':' + op.index
+
+      // copy and convert to big-endian hex
+      var txinHash = new Buffer(op.hash)
+      Array.prototype.reverse.call(txinHash)
+      txinHash = txinHash.toString('hex')
+
+      var output = txinHash + ':' + op.index
 
       if(me.outputs[output]) delete me.outputs[output]
     })
diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js
index b058385..48f594c 100644
--- a/test/bitcoin.core.js
+++ b/test/bitcoin.core.js
@@ -147,7 +147,12 @@ describe('Bitcoin-core', function() {
           var prevOutIndex = input[1]
   //          var prevOutScriptPubKey = input[2] // TODO: we don't have a ASM parser
 
-          assert.equal(txin.outpoint.hash, prevOutHash)
+          var actualHash = txin.outpoint.hash
+
+          // Test data is big-endian
+          Array.prototype.reverse.call(actualHash)
+
+          assert.equal(actualHash.toString('hex'), prevOutHash)
 
           // we read UInt32, not Int32
           assert.equal(txin.outpoint.index & 0xffffffff, prevOutIndex)
@@ -184,7 +189,7 @@ describe('Bitcoin-core', function() {
         }
 
         if (actualHash != undefined) {
-          // BigEndian test data
+          // Test data is big-endian
           Array.prototype.reverse.call(actualHash)
 
           assert.equal(actualHash.toString('hex'), expectedHash)
diff --git a/test/transaction.js b/test/transaction.js
index 78a5ca4..9bacec3 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -59,7 +59,7 @@ describe('Transaction', function() {
       assert.equal(input.sequence, 4294967295)
 
       assert.equal(input.outpoint.index, 0)
-      assert.equal(input.outpoint.hash, "69d02fc05c4e0ddc87e796eee42693c244a3112fffe1f762c3fb61ffcb304634")
+      assert.equal(input.outpoint.hash.toString('hex'), "344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069")
 
       assert.equal(b2h(input.script.buffer),
                    "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
@@ -120,7 +120,7 @@ describe('Transaction', function() {
         assert.equal(input.sequence, 4294967295)
 
         assert.equal(input.outpoint.index, 0)
-        assert.equal(input.outpoint.hash, "0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57")
+        assert.equal(input.outpoint.hash.toString('hex'), "576bc3c3285dbdccd8c3cbd8c03e10d7f77a5c839c744f34c3eb00511059b80c")
 
         assert.equal(input.script, Script.EMPTY)
       }
diff --git a/test/wallet.js b/test/wallet.js
index cc8b760..7562bc5 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -14,7 +14,15 @@ var fixtureTx1Hex = fixtureTxes.prevTx
 var fixtureTx2Hex = fixtureTxes.tx
 
 function fakeTxHash(i) {
-  return "efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe" + i
+  var hash = new Buffer(32)
+  hash.fill(i)
+  return hash
+}
+
+function fakeTxId(i) {
+  var hash = fakeTxHash(i)
+  Array.prototype.reverse.call(hash)
+  return hash.toString('hex')
 }
 
 describe('Wallet', function() {
@@ -263,12 +271,11 @@ describe('Wallet', function() {
     })
 
     describe('processConfirmedTx', function(){
-
       it('does not fail on scripts with no corresponding Address', function() {
         var pubKey = wallet.getPrivateKey(0).pub
         var script = scripts.pubKeyOutput(pubKey)
         var tx2 = new Transaction()
-        tx2.addInput(fakeTxHash(1), 0)
+        tx2.addInput(fakeTxId(1), 0)
 
         // FIXME: Transaction doesn't support custom ScriptPubKeys... yet
         // So for now, we hijack the script with our own, and undefine the cached address
@@ -365,19 +372,19 @@ describe('Wallet', function() {
       // set up 3 utxo
       utxo = [
         {
-          "hash": fakeTxHash(1),
+          "hash": fakeTxId(1),
           "outputIndex": 0,
           "address" : address1,
           "value": 400000 // not enough for value
         },
         {
-          "hash": fakeTxHash(2),
+          "hash": fakeTxId(2),
           "outputIndex": 1,
           "address" : address1,
           "value": 500000 // enough for only value
         },
         {
-          "hash": fakeTxHash(3),
+          "hash": fakeTxId(3),
           "outputIndex": 0,
           "address" : address2,
           "value": 520000 // enough for value and fee
@@ -415,7 +422,7 @@ describe('Wallet', function() {
       it('ignores pending outputs', function(){
         utxo.push(
           {
-            "hash": fakeTxHash(4),
+            "hash": fakeTxId(4),
             "outputIndex": 0,
             "address" : address2,
             "value": 530000,
@@ -437,7 +444,7 @@ describe('Wallet', function() {
         var address = wallet.generateAddress()
 
         wallet.setUnspentOutputs([{
-          hash: fakeTxHash(0),
+          hash: fakeTxId(0),
           outputIndex: 0,
           address: address,
           value: value
@@ -459,7 +466,7 @@ describe('Wallet', function() {
         var address = wallet.generateAddress()
 
         wallet.setUnspentOutputs([{
-          hash: fakeTxHash(0),
+          hash: fakeTxId(0),
           outputIndex: 0,
           address: address,
           value: value

From f85792ba22d016478c5ec731301f6f66a1f06ede Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 21 May 2014 11:38:03 +1000
Subject: [PATCH 11/29] Transaction: remove address from txOut

---
 src/transaction.js  |  9 +--------
 test/transaction.js |  7 ++++---
 test/wallet.js      | 24 ++++++++++++++++++------
 3 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 90899b9..f7935d9 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -91,21 +91,16 @@ Transaction.prototype.addOutput = function(scriptPubKey, value) {
     scriptPubKey = Address.fromBase58Check(scriptPubKey)
   }
 
-  // TODO: remove me
-  var addressString
-
   // Attempt to get a valid script if it's an Address object
   if (scriptPubKey instanceof Address) {
     var address = scriptPubKey
 
-    addressString = address.toBase58Check()
     scriptPubKey = address.toOutputScript()
   }
 
   this.outs.push(new TransactionOut({
     script: scriptPubKey,
     value: value,
-    address: addressString
   }))
 }
 
@@ -386,14 +381,12 @@ TransactionIn.prototype.clone = function () {
 function TransactionOut(data) {
   this.script = data.script
   this.value = data.value
-  this.address = data.address
 }
 
 TransactionOut.prototype.clone = function() {
   return new TransactionOut({
     script: this.script,
-    value: this.value,
-    address: this.address
+    value: this.value
   })
 }
 
diff --git a/test/transaction.js b/test/transaction.js
index 9bacec3..f849ade 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -143,12 +143,13 @@ describe('Transaction', function() {
       })
 
       it('supports alternative networks', function() {
-        var addr = 'mkHJaNR7uuwRG1JrmTZsV4MszaTKjCBvCR'
+        var address = Address.fromBase58Check('mkHJaNR7uuwRG1JrmTZsV4MszaTKjCBvCR')
+        var script = address.toOutputScript()
 
-        tx.addOutput(addr, 40000)
+        tx.addOutput(address, 40000)
         verifyTransactionOut()
 
-        assert.equal(tx.outs[0].address.toString(), addr)
+        assert.deepEqual(tx.outs[0].script, script)
       })
 
       function verifyTransactionOut() {
diff --git a/test/wallet.js b/test/wallet.js
index 7562bc5..ffd75c7 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -455,7 +455,9 @@ describe('Wallet', function() {
 
         var tx = wallet.createTx(to, toValue)
         assert.equal(tx.outs.length, 1)
-        assert.equal(tx.outs[0].address.toString(), to)
+
+        var outAddress = Address.fromOutputScript(tx.outs[0].script, networks.testnet)
+        assert.equal(outAddress.toString(), to)
         assert.equal(tx.outs[0].value, toValue)
       })
     })
@@ -480,10 +482,14 @@ describe('Wallet', function() {
 
         var tx = wallet.createTx(to, toValue, fee, changeAddress)
         assert.equal(tx.outs.length, 2)
-        assert.equal(tx.outs[0].address.toString(), to)
+
+        var outAddress0 = Address.fromOutputScript(tx.outs[0].script, networks.testnet)
+        var outAddress1 = Address.fromOutputScript(tx.outs[1].script, networks.testnet)
+
+        assert.equal(outAddress0.toString(), to)
         assert.equal(tx.outs[0].value, toValue)
 
-        assert.equal(tx.outs[1].address.toString(), changeAddress)
+        assert.equal(outAddress1.toString(), changeAddress)
         assert.equal(tx.outs[1].value, value - (toValue + fee))
       })
     })
@@ -494,7 +500,9 @@ describe('Wallet', function() {
 
         assert.equal(tx.outs.length, 1)
         var out = tx.outs[0]
-        assert.equal(out.address, to)
+        var outAddress = Address.fromOutputScript(out.script)
+
+        assert.equal(outAddress.toString(), to)
         assert.equal(out.value, value)
       })
 
@@ -507,7 +515,9 @@ describe('Wallet', function() {
 
           assert.equal(tx.outs.length, 2)
           var out = tx.outs[1]
-          assert.equal(out.address, wallet.changeAddresses[1])
+          var outAddress = Address.fromOutputScript(out.script)
+
+          assert.equal(outAddress.toString(), wallet.changeAddresses[1])
           assert.equal(out.value, 15000)
         })
 
@@ -519,7 +529,9 @@ describe('Wallet', function() {
 
           assert.equal(wallet.changeAddresses.length, 1)
           var out = tx.outs[1]
-          assert.equal(out.address, wallet.changeAddresses[0])
+          var outAddress = Address.fromOutputScript(out.script)
+
+          assert.equal(outAddress.toString(), wallet.changeAddresses[0])
           assert.equal(out.value, 15000)
         })
 

From 7f9711ef9bc78ae9c5386f515d5a40a9af164290 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 21 May 2014 11:41:25 +1000
Subject: [PATCH 12/29] Transaction: restrict Transaction constructor

---
 src/transaction.js | 39 +++++++--------------------------------
 1 file changed, 7 insertions(+), 32 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index f7935d9..e5ee989 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -17,28 +17,11 @@ var SIGHASH_NONE = 0x02
 var SIGHASH_SINGLE = 0x03
 var SIGHASH_ANYONECANPAY = 0x80
 
-function Transaction(doc) {
-  if (!(this instanceof Transaction)) { return new Transaction(doc) }
+function Transaction() {
   this.version = 1
   this.locktime = 0
   this.ins = []
   this.outs = []
-
-  if (doc) {
-    if (doc.version) this.version = doc.version;
-    if (doc.locktime) this.locktime = doc.locktime;
-    if (doc.ins && doc.ins.length) {
-      this.ins = doc.ins.map(function(input) {
-        return new TransactionIn(input)
-      })
-    }
-
-    if (doc.outs && doc.outs.length) {
-      this.outs = doc.outs.map(function(output) {
-        return new TransactionOut(output)
-      })
-    }
-  }
 }
 
 /**
@@ -256,12 +239,10 @@ Transaction.fromBuffer = function(buffer) {
     return vi.number
   }
 
-  var ins = []
-  var outs = []
+  var tx = new Transaction()
+  tx.version = readUInt32()
 
-  var version = readUInt32()
   var vinLen = readVarInt()
-
   for (var i = 0; i < vinLen; ++i) {
     var hash = readSlice(32)
     var vout = readUInt32()
@@ -269,7 +250,7 @@ Transaction.fromBuffer = function(buffer) {
     var script = readSlice(scriptLen)
     var sequence = readUInt32()
 
-    ins.push(new TransactionIn({
+    tx.ins.push(new TransactionIn({
       outpoint: {
         hash: hash,
         index: vout
@@ -280,27 +261,21 @@ Transaction.fromBuffer = function(buffer) {
   }
 
   var voutLen = readVarInt()
-
   for (i = 0; i < voutLen; ++i) {
     var value = readUInt64()
     var scriptLen = readVarInt()
     var script = readSlice(scriptLen)
 
-    outs.push(new TransactionOut({
+    tx.outs.push(new TransactionOut({
       value: value,
       script: Script.fromBuffer(script)
     }))
   }
 
-  var locktime = readUInt32()
+  tx.locktime = readUInt32()
   assert.equal(offset, buffer.length, 'Invalid transaction')
 
-  return new Transaction({
-    version: version,
-    ins: ins,
-    outs: outs,
-    locktime: locktime
-  })
+  return tx
 }
 
 Transaction.fromHex = function(hex) {

From 3b6f0bb9b35f1726135cbaaaf048bc6c090b0bac Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 21 May 2014 11:42:57 +1000
Subject: [PATCH 13/29] Transaction: fix test name

---
 test/transaction.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/transaction.js b/test/transaction.js
index f849ade..1e2d7d9 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -16,7 +16,7 @@ function b2h(b) { return new Buffer(b).toString('hex') }
 function h2b(h) { return new Buffer(h, 'hex') }
 
 describe('Transaction', function() {
-  describe('deserialize', function() {
+  describe('fromBuffer', function() {
     var tx, serializedTx
     beforeEach(function() {
       serializedTx = [

From 6ac38034831353563537eaa803149d074ff965d0 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 21 May 2014 11:48:30 +1000
Subject: [PATCH 14/29] Transaction: move test to proper section

---
 test/transaction.js | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/test/transaction.js b/test/transaction.js
index 1e2d7d9..dc88684 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -16,6 +16,16 @@ function b2h(b) { return new Buffer(b).toString('hex') }
 function h2b(h) { return new Buffer(h, 'hex') }
 
 describe('Transaction', function() {
+  describe('toBuffer', function() {
+    it('matches the expected output', function() {
+      var expected = '010000000189632848f99722915727c5c75da8db2dbf194342a0429828f66ff88fab2af7d600000000fd1b0100483045022100e5be20d440b2bbbc886161f9095fa6d0bca749a4e41d30064f30eb97adc7a1f5022061af132890d8e4e90fedff5e9365aeeb77021afd8ef1d5c114d575512e9a130a0147304402205054e38e9d7b5c10481b6b4991fde5704cd94d49e344406e3c2ce4d18a43bf8e022051d7ba8479865b53a48bee0cce86e89a25633af5b2918aa276859489e232f51c014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52aeffffffff0101000000000000001976a914751e76e8199196d454941c45d1b3a323f1433bd688ac00000000'
+
+      var actual = Transaction.fromHex(expected).toHex()
+
+      assert.equal(actual, expected)
+    })
+  })
+
   describe('fromBuffer', function() {
     var tx, serializedTx
     beforeEach(function() {
@@ -30,13 +40,6 @@ describe('Transaction', function() {
       tx = Transaction.fromHex(serializedTx)
     })
 
-    it('returns the original after serialized again', function() {
-      var actual = tx.toBuffer()
-      var expected = serializedTx
-
-      assert.equal(b2h(actual), expected)
-    })
-
     it('does not mutate the input buffer', function() {
       var buffer = new Buffer(serializedTx, 'hex')
       Transaction.fromBuffer(buffer)

From 66636f56bbd6a987497e80898de9a49e4715de93 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Wed, 21 May 2014 11:48:54 +1000
Subject: [PATCH 15/29] Transaction: test hex formatting

---
 test/transaction.js | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/test/transaction.js b/test/transaction.js
index dc88684..354b15e 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -13,7 +13,6 @@ var fixtureTx2Hex = fixtureTxes.tx
 var fixtureTxBigHex = fixtureTxes.bigTx
 
 function b2h(b) { return new Buffer(b).toString('hex') }
-function h2b(h) { return new Buffer(h, 'hex') }
 
 describe('Transaction', function() {
   describe('toBuffer', function() {
@@ -29,14 +28,7 @@ describe('Transaction', function() {
   describe('fromBuffer', function() {
     var tx, serializedTx
     beforeEach(function() {
-      serializedTx = [
-        '0100000001344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e78',
-        '7dc0d4e5cc02fd069000000004a493046022100ef89701f460e8660c8',
-        '0808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c0',
-        '72f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c2',
-        '3901ffffffff0100f2052a010000001976a914dd40dedd8f7e3746662',
-        '4c4dacc6362d8e7be23dd88ac00000000'
-      ].join('')
+      serializedTx = '0100000001344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069000000004a493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901ffffffff0100f2052a010000001976a914dd40dedd8f7e37466624c4dacc6362d8e7be23dd88ac00000000'
       tx = Transaction.fromHex(serializedTx)
     })
 
@@ -64,8 +56,7 @@ describe('Transaction', function() {
       assert.equal(input.outpoint.index, 0)
       assert.equal(input.outpoint.hash.toString('hex'), "344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069")
 
-      assert.equal(b2h(input.script.buffer),
-                   "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
+      assert.equal(b2h(input.script.buffer), "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
     })
 
     it('decodes outputs correctly', function() {

From a2d581dec508977d923b0df2cd05dd9d70d2003f Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sat, 24 May 2014 15:29:23 +1000
Subject: [PATCH 16/29] Transaction: rename script -> prevOutScript

---
 src/transaction.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index e5ee989..9871d48 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -312,15 +312,15 @@ Transaction.prototype.setInputScript = function(index, script) {
   this.ins[index].script = script
 }
 
-// FIXME: should probably be validateInput(index, pub)
-Transaction.prototype.validateInput = function(index, script, pub, DERsig) {
+// FIXME: could be validateInput(index, prevTxOut, pub)
+Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, DERsig) {
   var type = DERsig.readUInt8(DERsig.length - 1)
   DERsig = DERsig.slice(0, -1)
 
-  var hash = this.hashForSignature(script, index, type)
-  var sig = ecdsa.parseSig(DERsig)
+  var hash = this.hashForSignature(prevOutScript, index, type)
+  var signature = ecdsa.parseSig(DERsig)
 
-  return pub.verify(hash, sig)
+  return pubKey.verify(hash, signature)
 }
 
 Transaction.feePerKb = 20000

From 8e5fdb78a897d2d64d62eb14b457ce7d8c86ae3a Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 13 Jun 2014 16:25:41 +1000
Subject: [PATCH 17/29] Transaction: rename type to hashType

---
 src/transaction.js | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 9871d48..6bbf613 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -285,26 +285,26 @@ Transaction.fromHex = function(hex) {
 /**
  * Signs a pubKeyHash output at some index with the given key
  */
-Transaction.prototype.sign = function(index, key, type) {
+Transaction.prototype.sign = function(index, key, hashType) {
   var prevOutScript = key.pub.getAddress().toOutputScript()
-  var signature = this.signInput(index, prevOutScript, key, type)
+  var signature = this.signInput(index, prevOutScript, key, hashType)
 
   // FIXME: Assumed prior TX was pay-to-pubkey-hash
   var scriptSig = scripts.pubKeyHashInput(signature, key.pub)
   this.setInputScript(index, scriptSig)
 }
 
-Transaction.prototype.signInput = function(index, prevOutScript, key, type) {
-  type = type || SIGHASH_ALL
+Transaction.prototype.signInput = function(index, prevOutScript, key, hashType) {
+  hashType = hashType || SIGHASH_ALL
   assert(key instanceof ECKey, 'Invalid private key')
 
-  var hash = this.hashForSignature(prevOutScript, index, type)
+  var hash = this.hashForSignature(prevOutScript, index, hashType)
   var signature = key.sign(hash)
   var DERencoded = ecdsa.serializeSig(signature)
 
   return Buffer.concat([
     new Buffer(DERencoded),
-    new Buffer([type])
+    new Buffer([hashType])
   ])
 }
 

From 3b3d19974cf7048e84cb44776499f068e1b5d012 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 13 Jun 2014 16:28:38 +1000
Subject: [PATCH 18/29] tests: avoid b2h where toHex exists

---
 test/transaction.js | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/test/transaction.js b/test/transaction.js
index 354b15e..0acf048 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -12,8 +12,6 @@ var fixtureTx1Hex = fixtureTxes.prevTx
 var fixtureTx2Hex = fixtureTxes.tx
 var fixtureTxBigHex = fixtureTxes.bigTx
 
-function b2h(b) { return new Buffer(b).toString('hex') }
-
 describe('Transaction', function() {
   describe('toBuffer', function() {
     it('matches the expected output', function() {
@@ -56,7 +54,7 @@ describe('Transaction', function() {
       assert.equal(input.outpoint.index, 0)
       assert.equal(input.outpoint.hash.toString('hex'), "344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069")
 
-      assert.equal(b2h(input.script.buffer), "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
+      assert.equal(input.script.toHex(), "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
     })
 
     it('decodes outputs correctly', function() {
@@ -151,7 +149,7 @@ describe('Transaction', function() {
 
         var output = tx.outs[0]
         assert.equal(output.value, 40000)
-        assert.equal(b2h(output.script.buffer), "76a9143443bc45c560866cfeabf1d52f50a6ed358c69f288ac")
+        assert.equal(output.script.toHex(), "76a9143443bc45c560866cfeabf1d52f50a6ed358c69f288ac")
       }
     })
 

From 4f995fcae1c0dc216d30aaddab5c51c95e13ee3b Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 13 Jun 2014 16:29:57 +1000
Subject: [PATCH 19/29] Transaction: tests should show unboxing of parameters

---
 test/transaction.js | 38 ++++++++++++++++++--------------------
 1 file changed, 18 insertions(+), 20 deletions(-)

diff --git a/test/transaction.js b/test/transaction.js
index 0acf048..bcb3179 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -95,13 +95,15 @@ describe('Transaction', function() {
     })
 
     describe('addInput', function() {
-      it('allows a Transaction object to be passed in', function() {
-        tx.addInput(prevTx, 0)
+      it('accepts a transaction hash', function() {
+        var prevTxHash = prevTx.getId()
+
+        tx.addInput(prevTxHash, 0)
         verifyTransactionIn()
       })
 
-      it('allows a Transaction hash to be passed in', function() {
-        tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57", 0)
+      it('accepts a Transaction object', function() {
+        tx.addInput(prevTx, 0)
         verifyTransactionIn()
       })
 
@@ -119,31 +121,27 @@ describe('Transaction', function() {
     })
 
     describe('addOutput', function() {
-      it('allows an address and a value to be passed in', function() {
-        tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3", 40000)
+      it('accepts an address string', function() {
+        var dest = '15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3'
+
+        tx.addOutput(dest, 40000)
         verifyTransactionOut()
       })
 
-      it('allows an Address object and value to be passed in', function() {
-        tx.addOutput(Address.fromBase58Check('15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3'), 40000)
+      it('accepts an Address', function() {
+        var dest = Address.fromBase58Check('15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3')
+
+        tx.addOutput(dest, 40000)
         verifyTransactionOut()
       })
 
-      it('allows a scriptPubKey and a value to be passed in', function() {
-        tx.addOutput(Address.fromBase58Check('15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3').toOutputScript(), 40000)
+      it('accepts a scriptPubKey', function() {
+        var dest = Address.fromBase58Check('15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3').toOutputScript()
+
+        tx.addOutput(dest, 40000)
         verifyTransactionOut()
       })
 
-      it('supports alternative networks', function() {
-        var address = Address.fromBase58Check('mkHJaNR7uuwRG1JrmTZsV4MszaTKjCBvCR')
-        var script = address.toOutputScript()
-
-        tx.addOutput(address, 40000)
-        verifyTransactionOut()
-
-        assert.deepEqual(tx.outs[0].script, script)
-      })
-
       function verifyTransactionOut() {
         assert.equal(tx.outs.length, 1)
 

From 009fcb9b82f653aa575a064c2db5a1ef9ff52203 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 13 Jun 2014 16:44:02 +1000
Subject: [PATCH 20/29] Transaction: now returns index of added input/output

---
 src/transaction.js  | 14 ++++++++------
 test/transaction.js | 12 ++++++++++++
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 6bbf613..c195da3 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -34,7 +34,7 @@ function Transaction() {
  *
  * Note that this method does not sign the created input.
  */
-Transaction.prototype.addInput = function(tx, outIndex) {
+Transaction.prototype.addInput = function(tx, index) {
   var hash
 
   if (typeof tx === 'string') {
@@ -50,13 +50,15 @@ Transaction.prototype.addInput = function(tx, outIndex) {
 
   }
 
-  this.ins.push(new TransactionIn({
+  assert.equal(typeof index, 'number', 'Expected number index, got ' + index)
+
+  return (this.ins.push(new TransactionIn({
     outpoint: {
       hash: hash,
-      index: outIndex
+      index: index
     },
     script: Script.EMPTY
-  }))
+  })) - 1)
 }
 
 /**
@@ -81,10 +83,10 @@ Transaction.prototype.addOutput = function(scriptPubKey, value) {
     scriptPubKey = address.toOutputScript()
   }
 
-  this.outs.push(new TransactionOut({
+  return (this.outs.push(new TransactionOut({
     script: scriptPubKey,
     value: value,
-  }))
+  })) - 1)
 }
 
 Transaction.prototype.toBuffer = function () {
diff --git a/test/transaction.js b/test/transaction.js
index bcb3179..b2c8b92 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -107,6 +107,11 @@ describe('Transaction', function() {
         verifyTransactionIn()
       })
 
+      it('returns an index', function() {
+        assert.equal(tx.addInput(prevTx, 0), 0)
+        assert.equal(tx.addInput(prevTx, 0), 1)
+      })
+
       function verifyTransactionIn() {
         assert.equal(tx.ins.length, 1)
 
@@ -142,6 +147,13 @@ describe('Transaction', function() {
         verifyTransactionOut()
       })
 
+      it('returns an index', function() {
+        var dest = '15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3'
+
+        assert.equal(tx.addOutput(dest, 40000), 0)
+        assert.equal(tx.addOutput(dest, 40000), 1)
+      })
+
       function verifyTransactionOut() {
         assert.equal(tx.outs.length, 1)
 

From d56746358878acc1c51fb19821941601a15de36e Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Fri, 13 Jun 2014 17:00:40 +1000
Subject: [PATCH 21/29] Transaction: remove estimateFee

This is a wallet abstraction.
---
 src/transaction.js  | 12 ------------
 src/wallet.js       |  7 +++++--
 test/transaction.js | 22 ----------------------
 3 files changed, 5 insertions(+), 36 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index c195da3..8132bd2 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -325,18 +325,6 @@ Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, DER
   return pubKey.verify(hash, signature)
 }
 
-Transaction.feePerKb = 20000
-Transaction.prototype.estimateFee = function(feePerKb){
-  var uncompressedInSize = 180
-  var outSize = 34
-  var fixedPadding = 34
-
-  if(feePerKb == undefined) feePerKb = Transaction.feePerKb;
-  var size = this.ins.length * uncompressedInSize + this.outs.length * outSize + fixedPadding
-
-  return feePerKb * Math.ceil(size / 1000)
-}
-
 function TransactionIn(data) {
   assert(data.outpoint && data.script, 'Invalid TxIn parameters')
   this.outpoint = data.outpoint
diff --git a/src/wallet.js b/src/wallet.js
index 4410b36..4915d68 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -237,10 +237,13 @@ function Wallet(seed, network) {
     return sortByValueDesc
   }
 
-  function estimateFeePadChangeOutput(tx){
+  var feePerKb = 20000
+  function estimateFeePadChangeOutput(tx) {
     var tmpTx = tx.clone()
     tmpTx.addOutput(getChangeAddress(), 0)
-    return tmpTx.estimateFee()
+
+    var byteSize = tmpTx.toBuffer().length
+    return feePerKb * Math.ceil(byteSize / 1000)
   }
 
   function getChangeAddress() {
diff --git a/test/transaction.js b/test/transaction.js
index b2c8b92..8cf2366 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -194,28 +194,6 @@ describe('Transaction', function() {
         assert.equal(validTx.validateInput(0, script, key.pub, sig), true)
       })
     })
-
-    describe('estimateFee', function() {
-      it('works for fixture tx 1', function() {
-        var tx = Transaction.fromHex(fixtureTx1Hex)
-        assert.equal(tx.estimateFee(), 20000)
-      })
-
-      it('works for fixture big tx', function() {
-        var tx = Transaction.fromHex(fixtureTxBigHex)
-        assert.equal(tx.estimateFee(), 60000)
-      })
-
-      it('allow feePerKb to be passed in as an argument', function() {
-        var tx = Transaction.fromHex(fixtureTx2Hex)
-        assert.equal(tx.estimateFee(10000), 10000)
-      })
-
-      it('allow feePerKb to be set to 0', function() {
-        var tx = Transaction.fromHex(fixtureTx2Hex)
-        assert.equal(tx.estimateFee(0), 0)
-      })
-    })
   })
 
   describe('signInput', function() {

From a17208a549f4bfc014b96a5f2bbd83162983cae9 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sun, 15 Jun 2014 01:08:52 +1000
Subject: [PATCH 22/29] Transaction: rename key to privKey and standardize type
 check

---
 src/transaction.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 8132bd2..f780df9 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -287,21 +287,21 @@ Transaction.fromHex = function(hex) {
 /**
  * Signs a pubKeyHash output at some index with the given key
  */
-Transaction.prototype.sign = function(index, key, hashType) {
-  var prevOutScript = key.pub.getAddress().toOutputScript()
-  var signature = this.signInput(index, prevOutScript, key, hashType)
+Transaction.prototype.sign = function(index, privKey, hashType) {
+  var prevOutScript = privKey.pub.getAddress().toOutputScript()
+  var signature = this.signInput(index, prevOutScript, privKey, hashType)
 
   // FIXME: Assumed prior TX was pay-to-pubkey-hash
-  var scriptSig = scripts.pubKeyHashInput(signature, key.pub)
+  var scriptSig = scripts.pubKeyHashInput(signature, privKey.pub)
   this.setInputScript(index, scriptSig)
 }
 
-Transaction.prototype.signInput = function(index, prevOutScript, key, hashType) {
+Transaction.prototype.signInput = function(index, prevOutScript, privKey, hashType) {
   hashType = hashType || SIGHASH_ALL
-  assert(key instanceof ECKey, 'Invalid private key')
+  assert(privKey instanceof ECKey, 'Expected ECKey, got ' + privKey)
 
   var hash = this.hashForSignature(prevOutScript, index, hashType)
-  var signature = key.sign(hash)
+  var signature = privKey.sign(hash)
   var DERencoded = ecdsa.serializeSig(signature)
 
   return Buffer.concat([

From b5268465dbce454a7824ad35d11551d65ed05f18 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sun, 15 Jun 2014 01:39:59 +1000
Subject: [PATCH 23/29] Transaction: remove TxIn/TxOut clone

---
 src/transaction.js | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index f780df9..b55c345 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -332,27 +332,9 @@ function TransactionIn(data) {
   this.sequence = data.sequence == undefined ? DEFAULT_SEQUENCE : data.sequence
 }
 
-TransactionIn.prototype.clone = function () {
-  return new TransactionIn({
-    outpoint: {
-      hash: this.outpoint.hash,
-      index: this.outpoint.index
-    },
-    script: this.script,
-    sequence: this.sequence
-  })
-}
-
 function TransactionOut(data) {
   this.script = data.script
   this.value = data.value
 }
 
-TransactionOut.prototype.clone = function() {
-  return new TransactionOut({
-    script: this.script,
-    value: this.value
-  })
-}
-
 module.exports = Transaction

From 203d6c711662c1b3de953238abb905ee3278ef0c Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sun, 15 Jun 2014 15:28:11 +1000
Subject: [PATCH 24/29] Transaction: add test for clone

---
 test/transaction.js | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/test/transaction.js b/test/transaction.js
index 8cf2366..0233713 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -237,5 +237,22 @@ describe('Transaction', function() {
       assert.equal(tx.getId(), '7c3275f1212fd1a2add614f47a1f1f7b6d9570a97cb88e0e2664ab1752976e9f')
     })
   })
+
+  describe('clone', function() {
+    it('creates a new object', function() {
+      var txA = new Transaction()
+      txA.addInput('d6f72aab8ff86ff6289842a0424319bf2ddba85dc7c52757912297f948286389', 0)
+      txA.addOutput('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r', 1000)
+
+      var txB = txA.clone()
+
+      // Enforce value equality
+      assert.deepEqual(txA, txB)
+
+      // Enforce reference inequality
+      assert.notEqual(txA.ins[0], txB.ins[0])
+      assert.notEqual(txA.outs[0], txB.outs[0])
+    })
+  })
 })
 

From d8fdd50950820a6d479379d0625dbe57c4585957 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Sun, 15 Jun 2014 15:28:20 +1000
Subject: [PATCH 25/29] Transaction: remove TxIn/TxOut

---
 src/transaction.js | 42 +++++++++++++++++++-----------------------
 1 file changed, 19 insertions(+), 23 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index b55c345..d4e9634 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -52,13 +52,14 @@ Transaction.prototype.addInput = function(tx, index) {
 
   assert.equal(typeof index, 'number', 'Expected number index, got ' + index)
 
-  return (this.ins.push(new TransactionIn({
+  return (this.ins.push({
     outpoint: {
       hash: hash,
       index: index
     },
-    script: Script.EMPTY
-  })) - 1)
+    script: Script.EMPTY,
+    sequence: DEFAULT_SEQUENCE
+  }) - 1)
 }
 
 /**
@@ -83,10 +84,10 @@ Transaction.prototype.addOutput = function(scriptPubKey, value) {
     scriptPubKey = address.toOutputScript()
   }
 
-  return (this.outs.push(new TransactionOut({
+  return (this.outs.push({
     script: scriptPubKey,
     value: value,
-  })) - 1)
+  }) - 1)
 }
 
 Transaction.prototype.toBuffer = function () {
@@ -209,11 +210,18 @@ Transaction.prototype.clone = function () {
   newTx.locktime = this.locktime
 
   newTx.ins = this.ins.map(function(txin) {
-    return new TransactionIn(txin)
+    return {
+      outpoint: txin.outpoint,
+      script: txin.script,
+      sequence: txin.sequence
+    }
   })
 
   newTx.outs = this.outs.map(function(txout) {
-    return new TransactionOut(txout)
+    return {
+      script: txout.script,
+      value: txout.value
+    }
   })
 
   return newTx
@@ -252,14 +260,14 @@ Transaction.fromBuffer = function(buffer) {
     var script = readSlice(scriptLen)
     var sequence = readUInt32()
 
-    tx.ins.push(new TransactionIn({
+    tx.ins.push({
       outpoint: {
         hash: hash,
         index: vout
       },
       script: Script.fromBuffer(script),
       sequence: sequence
-    }))
+    })
   }
 
   var voutLen = readVarInt()
@@ -268,10 +276,10 @@ Transaction.fromBuffer = function(buffer) {
     var scriptLen = readVarInt()
     var script = readSlice(scriptLen)
 
-    tx.outs.push(new TransactionOut({
+    tx.outs.push({
       value: value,
       script: Script.fromBuffer(script)
-    }))
+    })
   }
 
   tx.locktime = readUInt32()
@@ -325,16 +333,4 @@ Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, DER
   return pubKey.verify(hash, signature)
 }
 
-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
-}
-
-function TransactionOut(data) {
-  this.script = data.script
-  this.value = data.value
-}
-
 module.exports = Transaction

From 2a267b62e60377010df22c8e0286c1fa100a458d Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 16 Jun 2014 01:27:05 +1000
Subject: [PATCH 26/29] jshint: remove unused variables

---
 src/index.js       | 2 --
 src/transaction.js | 2 +-
 src/wallet.js      | 2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/index.js b/src/index.js
index fc46f9b..2b9ae4b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,5 +1,3 @@
-var T = require('./transaction')
-
 module.exports = {
   Address: require('./address'),
   base58: require('./base58'),
diff --git a/src/transaction.js b/src/transaction.js
index d4e9634..7c85424 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -128,7 +128,7 @@ Transaction.prototype.toBuffer = function () {
   writeUInt32(this.version)
   writeVarInt(this.ins.length)
 
-  this.ins.forEach(function(txin, i) {
+  this.ins.forEach(function(txin) {
     writeSlice(txin.outpoint.hash)
     writeUInt32(txin.outpoint.index)
     writeVarInt(txin.script.buffer.length)
diff --git a/src/wallet.js b/src/wallet.js
index 4915d68..77756f3 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -169,7 +169,7 @@ function Wallet(seed, network) {
       }
     })
 
-    tx.ins.forEach(function(txIn, i) {
+    tx.ins.forEach(function(txIn) {
       var op = txIn.outpoint
 
       // copy and convert to big-endian hex

From 569e0d4ff156e7094141888b5e977c63cba9ce83 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 16 Jun 2014 13:58:16 +1000
Subject: [PATCH 27/29] Wallet: fix processConfirmedTx tests

These tests were still passing despite being incorrect.
---
 test/wallet.js | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/test/wallet.js b/test/wallet.js
index ffd75c7..7d9aa8c 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -313,34 +313,36 @@ describe('Wallet', function() {
       })
 
       describe("when tx ins outpoint contains a known txhash:i", function(){
+        var spendTx
         beforeEach(function(){
           wallet.addresses = [addresses[0]] // the address fixtureTx2 used as input
           wallet.processConfirmedTx(tx)
 
-          tx = Transaction.fromHex(fixtureTx2Hex)
+          spendTx = Transaction.fromHex(fixtureTx2Hex)
         })
 
         it("does not add to wallet.outputs", function(){
-          var outputs = wallet.outputs
-          wallet.processConfirmedTx(tx)
-          assert.deepEqual(wallet.outputs, outputs)
+          wallet.processConfirmedTx(spendTx)
+          assert.deepEqual(wallet.outputs, {})
         })
 
         it("deletes corresponding 'output'", function(){
-          wallet.processConfirmedTx(tx)
+          var txIn = spendTx.ins[0]
+          var txInId = new Buffer(txIn.outpoint.hash)
+          Array.prototype.reverse.call(txInId)
+          txInId = txInId.toString('hex')
 
-          var txIn = tx.ins[0]
-          var key = txIn.outpoint.hash + ":" + txIn.outpoint.index
-          var output = wallet.outputs[key]
+          var expected = txInId + ':' + txIn.outpoint.index
+          assert(expected in wallet.outputs)
 
-          assert.equal(output, undefined)
+          wallet.processConfirmedTx(spendTx)
+          assert(!(expected in wallet.outputs))
         })
       })
 
       it("does nothing when none of the involved addresses belong to the wallet", function(){
-        var outputs = wallet.outputs
         wallet.processConfirmedTx(tx)
-        assert.deepEqual(wallet.outputs, outputs)
+        assert.deepEqual(wallet.outputs, {})
       })
     })
 

From c0e5393595849d096136bd3f4774a34e2ce74e3a Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 16 Jun 2014 14:08:43 +1000
Subject: [PATCH 28/29] Transaction: remove .outpoint object

---
 src/transaction.js   | 21 ++++++++-------------
 src/wallet.js        | 10 ++++------
 test/bitcoin.core.js |  4 ++--
 test/transaction.js  |  8 ++++----
 test/wallet.js       | 20 +++++++++++++-------
 5 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 7c85424..51cfd00 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -1,5 +1,3 @@
-// FIXME: To all ye that enter here, be weary of Buffers, Arrays and Hex interchanging between the outpoints
-
 var assert = require('assert')
 var bufferutils = require('./bufferutils')
 var crypto = require('./crypto')
@@ -53,10 +51,8 @@ Transaction.prototype.addInput = function(tx, index) {
   assert.equal(typeof index, 'number', 'Expected number index, got ' + index)
 
   return (this.ins.push({
-    outpoint: {
-      hash: hash,
-      index: index
-    },
+    hash: hash,
+    index: index,
     script: Script.EMPTY,
     sequence: DEFAULT_SEQUENCE
   }) - 1)
@@ -129,8 +125,8 @@ Transaction.prototype.toBuffer = function () {
   writeVarInt(this.ins.length)
 
   this.ins.forEach(function(txin) {
-    writeSlice(txin.outpoint.hash)
-    writeUInt32(txin.outpoint.index)
+    writeSlice(txin.hash)
+    writeUInt32(txin.index)
     writeVarInt(txin.script.buffer.length)
     writeSlice(txin.script.buffer)
     writeUInt32(txin.sequence)
@@ -211,7 +207,8 @@ Transaction.prototype.clone = function () {
 
   newTx.ins = this.ins.map(function(txin) {
     return {
-      outpoint: txin.outpoint,
+      hash: txin.hash,
+      index: txin.index,
       script: txin.script,
       sequence: txin.sequence
     }
@@ -261,10 +258,8 @@ Transaction.fromBuffer = function(buffer) {
     var sequence = readUInt32()
 
     tx.ins.push({
-      outpoint: {
-        hash: hash,
-        index: vout
-      },
+      hash: hash,
+      index: vout,
       script: Script.fromBuffer(script),
       sequence: sequence
     })
diff --git a/src/wallet.js b/src/wallet.js
index 77756f3..1501456 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -170,14 +170,12 @@ function Wallet(seed, network) {
     })
 
     tx.ins.forEach(function(txIn) {
-      var op = txIn.outpoint
-
       // copy and convert to big-endian hex
-      var txinHash = new Buffer(op.hash)
-      Array.prototype.reverse.call(txinHash)
-      txinHash = txinHash.toString('hex')
+      var txinId = new Buffer(txIn.hash)
+      Array.prototype.reverse.call(txinId)
+      txinId = txinId.toString('hex')
 
-      var output = txinHash + ':' + op.index
+      var output = txinId + ':' + txIn.index
 
       if(me.outputs[output]) delete me.outputs[output]
     })
diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js
index 48f594c..af52885 100644
--- a/test/bitcoin.core.js
+++ b/test/bitcoin.core.js
@@ -147,7 +147,7 @@ describe('Bitcoin-core', function() {
           var prevOutIndex = input[1]
   //          var prevOutScriptPubKey = input[2] // TODO: we don't have a ASM parser
 
-          var actualHash = txin.outpoint.hash
+          var actualHash = txin.hash
 
           // Test data is big-endian
           Array.prototype.reverse.call(actualHash)
@@ -155,7 +155,7 @@ describe('Bitcoin-core', function() {
           assert.equal(actualHash.toString('hex'), prevOutHash)
 
           // we read UInt32, not Int32
-          assert.equal(txin.outpoint.index & 0xffffffff, prevOutIndex)
+          assert.equal(txin.index & 0xffffffff, prevOutIndex)
         })
       })
     })
diff --git a/test/transaction.js b/test/transaction.js
index 0233713..38f031f 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -51,8 +51,8 @@ describe('Transaction', function() {
       var input = tx.ins[0]
       assert.equal(input.sequence, 4294967295)
 
-      assert.equal(input.outpoint.index, 0)
-      assert.equal(input.outpoint.hash.toString('hex'), "344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069")
+      assert.equal(input.index, 0)
+      assert.equal(input.hash.toString('hex'), "344630cbff61fbc362f7e1ff2f11a344c29326e4ee96e787dc0d4e5cc02fd069")
 
       assert.equal(input.script.toHex(), "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
     })
@@ -118,8 +118,8 @@ describe('Transaction', function() {
         var input = tx.ins[0]
         assert.equal(input.sequence, 4294967295)
 
-        assert.equal(input.outpoint.index, 0)
-        assert.equal(input.outpoint.hash.toString('hex'), "576bc3c3285dbdccd8c3cbd8c03e10d7f77a5c839c744f34c3eb00511059b80c")
+        assert.equal(input.index, 0)
+        assert.equal(input.hash.toString('hex'), "576bc3c3285dbdccd8c3cbd8c03e10d7f77a5c839c744f34c3eb00511059b80c")
 
         assert.equal(input.script, Script.EMPTY)
       }
diff --git a/test/wallet.js b/test/wallet.js
index 7d9aa8c..ad94d03 100644
--- a/test/wallet.js
+++ b/test/wallet.js
@@ -328,11 +328,11 @@ describe('Wallet', function() {
 
         it("deletes corresponding 'output'", function(){
           var txIn = spendTx.ins[0]
-          var txInId = new Buffer(txIn.outpoint.hash)
+          var txInId = new Buffer(txIn.hash)
           Array.prototype.reverse.call(txInId)
           txInId = txInId.toString('hex')
 
-          var expected = txInId + ':' + txIn.outpoint.index
+          var expected = txInId + ':' + txIn.index
           assert(expected in wallet.outputs)
 
           wallet.processConfirmedTx(spendTx)
@@ -400,7 +400,8 @@ describe('Wallet', function() {
         var tx = wallet.createTx(to, value)
 
         assert.equal(tx.ins.length, 1)
-        assert.deepEqual(tx.ins[0].outpoint, { hash: fakeTxHash(3), index: 0 })
+        assert.deepEqual(tx.ins[0].hash, fakeTxHash(3))
+        assert.equal(tx.ins[0].index, 0)
       })
 
       it('allows fee to be specified', function(){
@@ -408,8 +409,11 @@ describe('Wallet', function() {
         var tx = wallet.createTx(to, value, fee)
 
         assert.equal(tx.ins.length, 2)
-        assert.deepEqual(tx.ins[0].outpoint, { hash: fakeTxHash(3), index: 0 })
-        assert.deepEqual(tx.ins[1].outpoint, { hash: fakeTxHash(2), index: 1 })
+
+        assert.deepEqual(tx.ins[0].hash, fakeTxHash(3))
+        assert.equal(tx.ins[0].index, 0)
+        assert.deepEqual(tx.ins[1].hash, fakeTxHash(2))
+        assert.equal(tx.ins[1].index, 1)
       })
 
       it('allows fee to be set to zero', function(){
@@ -418,7 +422,8 @@ describe('Wallet', function() {
         var tx = wallet.createTx(to, value, fee)
 
         assert.equal(tx.ins.length, 1)
-        assert.deepEqual(tx.ins[0].outpoint, { hash: fakeTxHash(3), index: 0 })
+        assert.deepEqual(tx.ins[0].hash, fakeTxHash(3))
+        assert.equal(tx.ins[0].index, 0)
       })
 
       it('ignores pending outputs', function(){
@@ -436,7 +441,8 @@ describe('Wallet', function() {
         var tx = wallet.createTx(to, value)
 
         assert.equal(tx.ins.length, 1)
-        assert.deepEqual(tx.ins[0].outpoint, { hash: fakeTxHash(3), index: 0 })
+        assert.deepEqual(tx.ins[0].hash, fakeTxHash(3))
+        assert.equal(tx.ins[0].index, 0)
       })
     })
 

From c5252fc509ac5dfb9e79248a5bbfabced42f8763 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Mon, 16 Jun 2014 15:44:27 +1000
Subject: [PATCH 29/29] Transaction: amend confusing exception message

---
 src/transaction.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 51cfd00..65c0a59 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -37,13 +37,13 @@ Transaction.prototype.addInput = function(tx, index) {
 
   if (typeof tx === 'string') {
     hash = new Buffer(tx, 'hex')
-    assert.equal(hash.length, 32, 'Invalid TX hash')
+    assert.equal(hash.length, 32, 'Expected Transaction or string, got ' + tx)
 
     // TxHash hex is big-endian, we need little-endian
     Array.prototype.reverse.call(hash)
 
   } else {
-    assert(tx instanceof Transaction, 'Expected Transaction, got ' + tx)
+    assert(tx instanceof Transaction, 'Expected Transaction or string, got ' + tx)
     hash = crypto.hash256(tx.toBuffer())
 
   }