Browse Source

Transaction: use hash Buffer instead of hex string

hk-custom-address
Daniel Cousens 11 years ago
parent
commit
5551c38812
  1. 29
      src/transaction.js
  2. 10
      src/wallet.js
  3. 9
      test/bitcoin.core.js
  4. 4
      test/transaction.js
  5. 25
      test/wallet.js

29
src/transaction.js

@ -55,11 +55,16 @@ Transaction.prototype.addInput = function(tx, outIndex) {
var hash var hash
if (typeof tx === 'string') { 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 { } else {
assert(tx instanceof Transaction, 'Unexpected input: ' + tx) assert(tx instanceof Transaction, 'Expected Transaction, got ' + tx)
hash = tx.getId() hash = crypto.hash256(tx.toBuffer())
} }
this.ins.push(new TransactionIn({ this.ins.push(new TransactionIn({
@ -142,13 +147,8 @@ Transaction.prototype.toBuffer = function () {
writeUInt32(this.version) writeUInt32(this.version)
writeVarInt(this.ins.length) writeVarInt(this.ins.length)
this.ins.forEach(function(txin) { this.ins.forEach(function(txin, i) {
var hash = new Buffer(txin.outpoint.hash, 'hex') // FIXME: Performance: convert on tx.addInput instead writeSlice(txin.outpoint.hash)
// TxHash hex is big-endian, we need little-endian
Array.prototype.reverse.call(hash)
writeSlice(hash)
writeUInt32(txin.outpoint.index) writeUInt32(txin.outpoint.index)
writeVarInt(txin.script.buffer.length) writeVarInt(txin.script.buffer.length)
writeSlice(txin.script.buffer) writeSlice(txin.script.buffer)
@ -240,9 +240,6 @@ Transaction.prototype.clone = function () {
} }
Transaction.fromBuffer = function(buffer) { Transaction.fromBuffer = function(buffer) {
// Copy because we mutate (reverse TxOutHashs)
buffer = new Buffer(buffer)
var offset = 0 var offset = 0
function readSlice(n) { function readSlice(n) {
offset += n offset += n
@ -272,10 +269,6 @@ Transaction.fromBuffer = function(buffer) {
for (var i = 0; i < vinLen; ++i) { for (var i = 0; i < vinLen; ++i) {
var hash = readSlice(32) var hash = readSlice(32)
// TxHash is little-endian, we want big-endian hex
Array.prototype.reverse.call(hash)
var vout = readUInt32() var vout = readUInt32()
var scriptLen = readVarInt() var scriptLen = readVarInt()
var script = readSlice(scriptLen) var script = readSlice(scriptLen)
@ -283,7 +276,7 @@ Transaction.fromBuffer = function(buffer) {
ins.push(new TransactionIn({ ins.push(new TransactionIn({
outpoint: { outpoint: {
hash: hash.toString('hex'), hash: hash,
index: vout index: vout
}, },
script: Script.fromBuffer(script), script: Script.fromBuffer(script),

10
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 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] if(me.outputs[output]) delete me.outputs[output]
}) })

9
test/bitcoin.core.js

@ -147,7 +147,12 @@ describe('Bitcoin-core', function() {
var prevOutIndex = input[1] var prevOutIndex = input[1]
// var prevOutScriptPubKey = input[2] // TODO: we don't have a ASM parser // 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 // we read UInt32, not Int32
assert.equal(txin.outpoint.index & 0xffffffff, prevOutIndex) assert.equal(txin.outpoint.index & 0xffffffff, prevOutIndex)
@ -184,7 +189,7 @@ describe('Bitcoin-core', function() {
} }
if (actualHash != undefined) { if (actualHash != undefined) {
// BigEndian test data // Test data is big-endian
Array.prototype.reverse.call(actualHash) Array.prototype.reverse.call(actualHash)
assert.equal(actualHash.toString('hex'), expectedHash) assert.equal(actualHash.toString('hex'), expectedHash)

4
test/transaction.js

@ -59,7 +59,7 @@ describe('Transaction', function() {
assert.equal(input.sequence, 4294967295) assert.equal(input.sequence, 4294967295)
assert.equal(input.outpoint.index, 0) 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), assert.equal(b2h(input.script.buffer),
"493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901") "493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
@ -120,7 +120,7 @@ describe('Transaction', function() {
assert.equal(input.sequence, 4294967295) assert.equal(input.sequence, 4294967295)
assert.equal(input.outpoint.index, 0) 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) assert.equal(input.script, Script.EMPTY)
} }

25
test/wallet.js

@ -14,7 +14,15 @@ var fixtureTx1Hex = fixtureTxes.prevTx
var fixtureTx2Hex = fixtureTxes.tx var fixtureTx2Hex = fixtureTxes.tx
function fakeTxHash(i) { 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() { describe('Wallet', function() {
@ -263,12 +271,11 @@ describe('Wallet', function() {
}) })
describe('processConfirmedTx', function(){ describe('processConfirmedTx', function(){
it('does not fail on scripts with no corresponding Address', function() { it('does not fail on scripts with no corresponding Address', function() {
var pubKey = wallet.getPrivateKey(0).pub var pubKey = wallet.getPrivateKey(0).pub
var script = scripts.pubKeyOutput(pubKey) var script = scripts.pubKeyOutput(pubKey)
var tx2 = new Transaction() var tx2 = new Transaction()
tx2.addInput(fakeTxHash(1), 0) tx2.addInput(fakeTxId(1), 0)
// FIXME: Transaction doesn't support custom ScriptPubKeys... yet // FIXME: Transaction doesn't support custom ScriptPubKeys... yet
// So for now, we hijack the script with our own, and undefine the cached address // 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 // set up 3 utxo
utxo = [ utxo = [
{ {
"hash": fakeTxHash(1), "hash": fakeTxId(1),
"outputIndex": 0, "outputIndex": 0,
"address" : address1, "address" : address1,
"value": 400000 // not enough for value "value": 400000 // not enough for value
}, },
{ {
"hash": fakeTxHash(2), "hash": fakeTxId(2),
"outputIndex": 1, "outputIndex": 1,
"address" : address1, "address" : address1,
"value": 500000 // enough for only value "value": 500000 // enough for only value
}, },
{ {
"hash": fakeTxHash(3), "hash": fakeTxId(3),
"outputIndex": 0, "outputIndex": 0,
"address" : address2, "address" : address2,
"value": 520000 // enough for value and fee "value": 520000 // enough for value and fee
@ -415,7 +422,7 @@ describe('Wallet', function() {
it('ignores pending outputs', function(){ it('ignores pending outputs', function(){
utxo.push( utxo.push(
{ {
"hash": fakeTxHash(4), "hash": fakeTxId(4),
"outputIndex": 0, "outputIndex": 0,
"address" : address2, "address" : address2,
"value": 530000, "value": 530000,
@ -437,7 +444,7 @@ describe('Wallet', function() {
var address = wallet.generateAddress() var address = wallet.generateAddress()
wallet.setUnspentOutputs([{ wallet.setUnspentOutputs([{
hash: fakeTxHash(0), hash: fakeTxId(0),
outputIndex: 0, outputIndex: 0,
address: address, address: address,
value: value value: value
@ -459,7 +466,7 @@ describe('Wallet', function() {
var address = wallet.generateAddress() var address = wallet.generateAddress()
wallet.setUnspentOutputs([{ wallet.setUnspentOutputs([{
hash: fakeTxHash(0), hash: fakeTxId(0),
outputIndex: 0, outputIndex: 0,
address: address, address: address,
value: value value: value

Loading…
Cancel
Save