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