Merge pull request #170 from dcousens/bufferx

BufferExt and Transaction serialization to use Buffers
This commit is contained in:
Wei Lu 2014-05-05 12:40:51 +08:00
commit 5deab5188f
13 changed files with 438 additions and 227 deletions

94
src/buffer.js Normal file
View file

@ -0,0 +1,94 @@
var assert = require('assert')
function readUInt64LE(buffer, offset) {
var a = buffer.readUInt32LE(offset)
var b = buffer.readUInt32LE(offset + 4)
b *= 0x100000000
// Javascript Safe Integer limitation
// assert(Number.isSafeInteger(value), 'value must be < 2^53')
assert(b + a < 0x0020000000000000, 'value must be < 2^53')
return b + a
}
function readVarInt(buffer, offset) {
var t = buffer.readUInt8(offset)
var number, size
// 8-bit
if (t < 253) {
number = t
size = 1
// 16-bit
} else if (t < 254) {
number = buffer.readUInt16LE(offset + 1)
size = 3
// 32-bit
} else if (t < 255) {
number = buffer.readUInt32LE(offset + 1)
size = 5
// 64 bit
} else {
number = readUInt64LE(buffer, offset + 1)
size = 9
}
return {
number: number,
size: size
}
}
function writeUInt64LE(buffer, value, offset) {
// Javascript Safe Integer limitation
// assert(Number.isSafeInteger(value), 'value must be < 2^53')
assert(value < 0x0020000000000000, 'value must be < 2^53')
buffer.writeInt32LE(value & -1, offset)
buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4)
}
function varIntSize(i) {
return i < 253 ? 1
: i < 0x10000 ? 3
: i < 0x100000000 ? 5
: 9
}
function writeVarInt(buffer, number, offset) {
var size = varIntSize(number)
// 8 bit
if (size === 1) {
buffer.writeUInt8(number, offset)
// 16 bit
} else if (size === 3) {
buffer.writeUInt8(253, offset)
buffer.writeUInt16LE(number, offset + 1)
// 32 bit
} else if (size === 5) {
buffer.writeUInt8(254, offset)
buffer.writeUInt32LE(number, offset + 1)
// 64 bit
} else {
buffer.writeUInt8(255, offset)
writeUInt64LE(buffer, number, offset + 1)
}
return size
}
module.exports = {
readUInt64LE: readUInt64LE,
readVarInt: readVarInt,
varIntSize: varIntSize,
writeUInt64LE: writeUInt64LE,
writeVarInt: writeVarInt
}

View file

@ -24,15 +24,6 @@ function hexToBytes(hex) {
})
}
/**
* Create a byte array representing a number with the given length
*/
function numToBytes(num, bytes) {
if (bytes === undefined) bytes = 8
if (bytes === 0) return []
return [num % 256].concat(numToBytes(Math.floor(num / 256), bytes - 1))
}
/**
* Convert a byte array to the number that it represents
*/
@ -41,42 +32,6 @@ function bytesToNum(bytes) {
return bytes[0] + 256 * bytesToNum(bytes.slice(1))
}
/**
* Turn an integer into a "var_int".
*
* "var_int" is a variable length integer used by Bitcoin's binary format.
*
* Returns a byte array.
*/
function numToVarInt(num) {
if (num < 253) return [num]
if (num < 65536) return [253].concat(numToBytes(num, 2))
if (num < 4294967296) return [254].concat(numToBytes(num, 4))
return [255].concat(numToBytes(num, 8))
}
/**
* Turn an VarInt into an integer
*
* "var_int" is a variable length integer used by Bitcoin's binary format.
*
* Returns { bytes: bytesUsed, number: theNumber }
*/
function varIntToNum(bytes) {
var prefix = bytes[0]
var viBytes =
prefix < 253 ? bytes.slice(0, 1)
: prefix === 253 ? bytes.slice(1, 3)
: prefix === 254 ? bytes.slice(1, 5)
: bytes.slice(1, 9)
return {
bytes: prefix < 253 ? viBytes : bytes.slice(0, viBytes.length + 1),
number: bytesToNum(viBytes)
}
}
function bytesToWords(bytes) {
assert(Array.isArray(bytes) || Buffer.isBuffer(bytes), 'Input must be a byte array')
var words = []
@ -110,10 +65,7 @@ module.exports = {
lpad: lpad,
bytesToHex: bytesToHex,
hexToBytes: hexToBytes,
numToBytes: numToBytes,
bytesToNum: bytesToNum,
numToVarInt: numToVarInt,
varIntToNum: varIntToNum,
bytesToWords: bytesToWords,
wordsToBytes: wordsToBytes,
bytesToWordArray: bytesToWordArray,

View file

@ -179,10 +179,11 @@ HDWallet.prototype.toBase58 = function(priv) {
}
HDWallet.prototype.derive = function(i) {
var iBytes = convert.numToBytes(i, 4).reverse()
, cPar = this.chaincode
, usePriv = i >= HDWallet.HIGHEST_BIT
, SHA512 = CJS.algo.SHA512
var iBuffer = new Buffer(4)
iBuffer.writeUInt32BE(i, 0)
var cPar = this.chaincode
var usePriv = i >= HDWallet.HIGHEST_BIT
var I
if (usePriv) {
@ -191,21 +192,20 @@ HDWallet.prototype.derive = function(i) {
// If 1, private derivation is used:
// let I = HMAC-SHA512(Key = cpar, Data = 0x00 || kpar || i) [Note:]
var kPar = this.priv.toBuffer().slice(0, 32)
kPar = Array.prototype.slice.call(kPar)
iBuffer = Buffer.concat([new Buffer([0]), kPar, iBuffer], 37)
// FIXME: Dislikes buffers
I = HmacFromBytesToBytes(SHA512, [0].concat(kPar, iBytes), cPar)
I = HmacFromBytesToBytes(CJS.algo.SHA512, Array.prototype.slice.call(iBuffer), cPar)
} else {
// If 0, public derivation is used:
// let I = HMAC-SHA512(Key = cpar, Data = χ(kpar*G) || i)
var KPar = this.pub.toBuffer()
KPar = Array.prototype.slice.call(KPar)
iBuffer = Buffer.concat([KPar, iBuffer])
// FIXME: Dislikes buffers
I = HmacFromBytesToBytes(SHA512, KPar.concat(iBytes), cPar)
I = HmacFromBytesToBytes(CJS.algo.SHA512, Array.prototype.slice.call(iBuffer), cPar)
}
// FIXME: Boo, CSJ.algo.SHA512 uses byte arrays
I = new Buffer(I)

View file

@ -6,6 +6,7 @@ module.exports = {
Address: require('./address'),
base58: require('./base58'),
base58check: require('./base58check'),
BufferExt: require('./buffer'),
convert: require('./convert'),
crypto: require('./crypto'),
ec: ec,

View file

@ -1,24 +1,22 @@
/// Implements Bitcoin's feature for signing arbitrary messages.
var Address = require('./address')
var convert = require('./convert')
var BufferExt = require('./buffer')
var crypto = require('./crypto')
var ecdsa = require('./ecdsa')
var ECPubKey = require('./eckey').ECPubKey
// FIXME: magicHash is incompatible with other magic messages
var magicBytes = new Buffer('Bitcoin Signed Message:\n')
// FIXME: incompatible with other networks (Litecoin etc)
var MAGIC_PREFIX = new Buffer('\x18Bitcoin Signed Message:\n')
function magicHash(message) {
var messageBytes = new Buffer(message)
var messageBuffer = new Buffer(message)
var lengthBuffer = new Buffer(BufferExt.varIntSize(messageBuffer.length))
BufferExt.writeVarInt(lengthBuffer, messageBuffer.length, 0)
var buffer = Buffer.concat([
new Buffer(convert.numToVarInt(magicBytes.length)),
magicBytes,
new Buffer(convert.numToVarInt(messageBytes.length)),
messageBytes
MAGIC_PREFIX, lengthBuffer, messageBuffer
])
return crypto.hash256(buffer)
}

View file

@ -13,8 +13,14 @@ function Script(data) {
this.parse()
}
Script.fromHex = function(data) {
return new Script(convert.hexToBytes(data))
Script.fromBuffer = function(buffer) {
assert(Buffer.isBuffer(buffer)) // FIXME: transitionary
return new Script(Array.prototype.slice.call(buffer))
}
Script.fromHex = function(hex) {
return Script.fromBuffer(new Buffer(hex, 'hex'))
}
Script.fromPubKey = function(str) {

View file

@ -3,6 +3,7 @@
var assert = require('assert')
var Address = require('./address')
var BigInteger = require('bigi')
var BufferExt = require('./buffer')
var Script = require('./script')
var convert = require('./convert')
var crypto = require('./crypto')
@ -16,7 +17,7 @@ var Transaction = function (doc) {
this.locktime = 0
this.ins = []
this.outs = []
this.defaultSequence = [255, 255, 255, 255] // 0xFFFFFFFF
this.defaultSequence = 0xffffffff
if (doc) {
if (typeof doc == "string" || Array.isArray(doc)) {
@ -118,45 +119,76 @@ Transaction.prototype.addOutput = function (address, value, network) {
/**
* Serialize this transaction.
*
* Returns the transaction as a byte array in the standard Bitcoin binary
* format. This method is byte-perfect, i.e. the resulting byte array can
* be hashed to get the transaction's standard Bitcoin hash.
* Returns the transaction as a binary buffer in
* accordance with the Bitcoin protocol.
*/
Transaction.prototype.serialize = function () {
var buffer = []
buffer = buffer.concat(convert.numToBytes(parseInt(this.version), 4))
buffer = buffer.concat(convert.numToVarInt(this.ins.length))
var txInSize = this.ins.reduce(function(a, x) {
return a + (40 + BufferExt.varIntSize(x.script.buffer.length) + x.script.buffer.length)
}, 0)
this.ins.forEach(function(txin) {
// Why do blockchain.info, blockexplorer.com, sx and just about everybody
// else use little-endian hashes? No idea...
buffer = buffer.concat(convert.hexToBytes(txin.outpoint.hash).reverse())
var txOutSize = this.outs.reduce(function(a, x) {
return a + (8 + BufferExt.varIntSize(x.script.buffer.length) + x.script.buffer.length)
}, 0)
buffer = buffer.concat(convert.numToBytes(parseInt(txin.outpoint.index), 4))
var buffer = new Buffer(
8 +
BufferExt.varIntSize(this.ins.length) +
BufferExt.varIntSize(this.outs.length) +
txInSize +
txOutSize
)
var scriptBytes = txin.script.buffer
buffer = buffer.concat(convert.numToVarInt(scriptBytes.length))
buffer = buffer.concat(scriptBytes)
buffer = buffer.concat(txin.sequence)
var offset = 0
function writeSlice(slice) {
if (Array.isArray(slice)) slice = new Buffer(slice) // FIXME: Performance: transitionary only
slice.copy(buffer, offset)
offset += slice.length
}
function writeUInt32(i) {
buffer.writeUInt32LE(i, offset)
offset += 4
}
function writeUInt64(i) {
BufferExt.writeUInt64LE(buffer, i, offset)
offset += 8
}
function writeVarInt(i) {
var n = BufferExt.writeVarInt(buffer, i, offset)
offset += n
}
writeUInt32(this.version)
writeVarInt(this.ins.length)
this.ins.forEach(function(txin, i) {
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)
writeUInt32(txin.outpoint.index)
writeVarInt(txin.script.buffer.length)
writeSlice(txin.script.buffer)
writeUInt32(txin.sequence)
})
buffer = buffer.concat(convert.numToVarInt(this.outs.length))
writeVarInt(this.outs.length)
this.outs.forEach(function(txout) {
buffer = buffer.concat(convert.numToBytes(txout.value,8))
var scriptBytes = txout.script.buffer
buffer = buffer.concat(convert.numToVarInt(scriptBytes.length))
buffer = buffer.concat(scriptBytes)
writeUInt64(txout.value)
writeVarInt(txout.script.buffer.length)
writeSlice(txout.script.buffer)
})
buffer = buffer.concat(convert.numToBytes(parseInt(this.locktime), 4))
writeUInt32(this.locktime)
assert.equal(offset, buffer.length, 'Invalid transaction object')
return buffer
}
Transaction.prototype.serializeHex = function() {
return convert.bytesToHex(this.serialize())
return this.serialize().toString('hex')
}
//var OP_CODESEPARATOR = 171
@ -213,23 +245,20 @@ Transaction.prototype.hashTransactionForSignature =
txTmp.ins = [txTmp.ins[inIndex]]
}
var buffer = txTmp.serialize()
buffer = buffer.concat(convert.numToBytes(parseInt(hashType), 4))
var htB = new Buffer(4)
htB.writeUInt32LE(hashType, 0)
var buffer = Buffer.concat([txTmp.serialize(), htB])
return crypto.hash256(buffer)
}
/**
* Calculate and return the transaction's hash.
* Reverses hash since blockchain.info, blockexplorer.com and others
* use little-endian hashes for some stupid reason
*/
Transaction.prototype.getHash = function ()
{
var buffer = this.serialize()
var hash = crypto.hash256(buffer)
Transaction.prototype.getHash = function () {
var buffer = crypto.hash256(this.serialize())
return Array.prototype.slice.call(hash).reverse()
// Big-endian is used for TxHash
Array.prototype.reverse.call(buffer)
return buffer.toString('hex')
}
Transaction.prototype.clone = function ()
@ -250,60 +279,82 @@ Transaction.prototype.clone = function ()
}
Transaction.deserialize = function(buffer) {
if (typeof buffer == "string") {
buffer = convert.hexToBytes(buffer)
}
var pos = 0
var readAsInt = function(bytes) {
if (bytes === 0) return 0;
pos++;
return buffer[pos-1] + readAsInt(bytes-1) * 256
}
var readVarInt = function() {
var bytes = buffer.slice(pos, pos + 9) // maximum possible number of bytes to read
var result = convert.varIntToNum(bytes)
if (typeof buffer == "string") buffer = new Buffer(buffer, 'hex')
else if (Array.isArray(buffer)) buffer = new Buffer(buffer)
pos += result.bytes.length
return result.number
}
var readBytes = function(bytes) {
pos += bytes
return buffer.slice(pos - bytes, pos)
}
var readVarString = function() {
var size = readVarInt()
return readBytes(size)
}
var obj = {
ins: [],
outs: []
}
obj.version = readAsInt(4)
var ins = readVarInt()
var i
// Copy because we mutate (reverse TxOutHashs)
buffer = new Buffer(buffer)
for (i = 0; i < ins; i++) {
obj.ins.push({
var offset = 0
function readSlice(n) {
offset += n
return buffer.slice(offset - n, offset)
}
function readUInt32() {
var i = buffer.readUInt32LE(offset)
offset += 4
return i
}
function readUInt64() {
var i = BufferExt.readUInt64LE(buffer, offset)
offset += 8
return i
}
function readVarInt() {
var vi = BufferExt.readVarInt(buffer, offset)
offset += vi.size
return vi.number
}
var ins = []
var outs = []
var version = readUInt32()
var vinLen = readVarInt()
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)
var sequence = readUInt32()
ins.push({
outpoint: {
hash: convert.bytesToHex(readBytes(32).reverse()),
index: readAsInt(4)
hash: hash.toString('hex'),
index: vout,
},
script: new Script(readVarString()),
sequence: readBytes(4)
})
}
var outs = readVarInt()
for (i = 0; i < outs; i++) {
obj.outs.push({
value: convert.bytesToNum(readBytes(8)),
script: new Script(readVarString())
script: Script.fromBuffer(script),
sequence: sequence
})
}
obj.locktime = readAsInt(4)
var voutLen = readVarInt()
return new Transaction(obj)
for (i = 0; i < voutLen; ++i) {
var value = readUInt64()
var scriptLen = readVarInt()
var script = readSlice(scriptLen)
outs.push({
value: value,
script: Script.fromBuffer(script)
})
}
var locktime = readUInt32()
assert.equal(offset, buffer.length, 'Invalid transaction')
return new Transaction({
version: version,
ins: ins,
outs: outs,
locktime: locktime
})
}
/**

View file

@ -146,7 +146,7 @@ function Wallet(seed, options) {
}
this.processTx = function(tx) {
var txhash = convert.bytesToHex(tx.getHash())
var txhash = tx.getHash()
tx.outs.forEach(function(txOut, i){
var address = txOut.address.toString()

86
test/buffer.js Normal file
View file

@ -0,0 +1,86 @@
var assert = require('assert')
var BufferExt = require('../').BufferExt
var fixtures = require('./fixtures/buffer.js')
describe('Buffer Extensions', function() {
describe('readUInt64LE', function() {
it('matches test vectors', function() {
fixtures.valid.forEach(function(f) {
var buffer = new Buffer(f.hex64, 'hex')
var number = BufferExt.readUInt64LE(buffer, 0)
assert.equal(number, f.dec)
})
})
})
describe('readVarInt', function() {
it('matches test vectors', function() {
fixtures.valid.forEach(function(f) {
var buffer = new Buffer(f.hexVI, 'hex')
var d = BufferExt.readVarInt(buffer, 0)
assert.equal(d.number, f.dec)
assert.equal(d.size, buffer.length)
})
})
})
describe('varIntSize', function() {
it('matches test vectors', function() {
fixtures.valid.forEach(function(f) {
var number = parseInt(f.dec)
var size = BufferExt.varIntSize(number)
assert.equal(size, f.hexVI.length / 2)
})
})
})
describe('writeUInt64LE', function() {
it('matches test vectors', function() {
fixtures.valid.forEach(function(f) {
var buffer = new Buffer(8)
buffer.fill(0)
BufferExt.writeUInt64LE(buffer, f.dec, 0)
assert.equal(buffer.toString('hex'), f.hex64)
})
})
fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
assert.throws(function() {
var buffer = new Buffer(8)
buffer.fill(0)
BufferExt.writeUInt64LE(buffer, f.dec, 0)
})
})
})
})
describe('writeVarInt', function() {
it('matches test vectors', function() {
fixtures.valid.forEach(function(f) {
var buffer = new Buffer(9)
buffer.fill(0)
var n = BufferExt.writeVarInt(buffer, f.dec, 0)
assert.equal(buffer.slice(0, n).toString('hex'), f.hexVI)
})
})
fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
assert.throws(function() {
var buffer = new Buffer(9)
buffer.fill(0)
BufferExt.writeVarInt(buffer, f.dec, 0)
})
})
})
})
})

View file

@ -52,67 +52,6 @@ describe('convert', function() {
})
})
describe('numToVarInt', function() {
describe('works', function() {
var data = [
0, 128, 252, // 8-bit
256, 512, 1024, // 16-bit
65541, // 32-bit
4294967299, // 64-bit
]
var expected = [
[0], [128], [252], // 8-bit
[253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit
[254, 5, 0, 1, 0], // 32-bit
[255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit
]
for (var i = 0; i < data.length; ++i) {
var actual = convert.numToVarInt(data[i])
assert.deepEqual(actual, expected[i])
}
})
})
describe('varIntToNum', function() {
it('works on valid input', function() {
var data = [
[0], [128], [252], // 8-bit
[253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit
[254, 5, 0, 1, 0], // 32-bit
[255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit
]
var expected = [
0, 128, 252, // 8-bit
256, 512, 1024, // 16-bit
65541, // 32-bit
4294967299, // 64-bit
]
for (var i = 0; i < data.length; ++i) {
var actual = convert.varIntToNum(data[i])
assert.equal(actual.number, expected[i])
assert.deepEqual(actual.bytes, data[i])
}
})
it('uses only what is necessary', function() {
var data = [
[0, 99],
[253, 0, 1, 99],
[254, 5, 0, 1, 0, 99],
[255, 3, 0, 0, 0, 1, 0, 0, 0, 99]
]
var expected = [0, 256, 65541, 4294967299]
for (var i = 0; i < data.length; ++i) {
var actual = convert.varIntToNum(data[i])
assert.equal(actual.number, expected[i])
assert.deepEqual(actual.bytes, data[i].slice(0, -1))
}
})
})
describe('reverseEndian', function() {
it('works', function() {
var bigEndian = "6a4062273ac4f9ea4ffca52d9fd102b08f6c32faa0a4d1318e3a7b2e437bb9c7"

74
test/fixtures/buffer.js vendored Normal file
View file

@ -0,0 +1,74 @@
module.exports = {
"valid": [
{
"dec": 0,
"hex64": "0000000000000000",
"hexVI": "00"
},
{
"dec": 1,
"hex64": "0100000000000000",
"hexVI": "01"
},
{
"dec": 252,
"hex64": "fc00000000000000",
"hexVI": "fc"
},
{
"dec": 253,
"hex64": "fd00000000000000",
"hexVI": "fdfd00"
},
{
"dec": 254,
"hex64": "fe00000000000000",
"hexVI": "fdfe00"
},
{
"dec": 65535,
"hex64": "ffff000000000000",
"hexVI": "fdffff"
},
{
"dec": 65536,
"hex64": "0000010000000000",
"hexVI": "fe00000100"
},
{
"dec": 65537,
"hex64": "0100010000000000",
"hexVI": "fe01000100"
},
{
"dec": 4294967295,
"hex64": "ffffffff00000000",
"hexVI": "feffffffff"
},
{
"dec": 4294967296,
"hex64": "0000000001000000",
"hexVI": "ff0000000001000000"
},
{
"dec": 4294967297,
"hex64": "0100000001000000",
"hexVI": "ff0100000001000000"
},
{
"dec": 9007199254740991,
"hex64": "ffffffffffff1f00",
"hexVI": "ffffffffffffff1f00"
}
],
"invalid": [
{
"description": "n === 2^53",
"value": 9007199254740992
},
{
"description": "n > 2^53",
"value": 18374686479671624000
}
]
}

View file

@ -38,6 +38,13 @@ describe('Transaction', function() {
assert.equal(b2h(actual), expected)
})
it('does not mutate the input buffer', function() {
var buffer = new Buffer(serializedTx, 'hex')
Transaction.deserialize(buffer)
assert.equal(buffer.toString('hex'), serializedTx)
})
it('decodes version correctly', function(){
assert.equal(tx.version, 1)
})
@ -50,7 +57,7 @@ describe('Transaction', function() {
assert.equal(tx.ins.length, 1)
var input = tx.ins[0]
assert.deepEqual(input.sequence, [255, 255, 255, 255])
assert.equal(input.sequence, 4294967295)
assert.equal(input.outpoint.index, 0)
assert.equal(input.outpoint.hash, "69d02fc05c4e0ddc87e796eee42693c244a3112fffe1f762c3fb61ffcb304634")
@ -72,7 +79,7 @@ describe('Transaction', function() {
it('assigns hash to deserialized object', function(){
var hashHex = "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c"
assert.equal(b2h(tx.hash), hashHex)
assert.equal(tx.hash, hashHex)
})
it('decodes large inputs correctly', function() {
@ -81,14 +88,18 @@ describe('Transaction', function() {
tx.addInput("0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57", 0)
tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3", 100)
// but we're going to replace the tx.ins.length VarInt with a 32-bit equivalent
// however the same resultant number of inputs (1)
var bytes = tx.serialize()
var mutated = bytes.slice(0, 4).concat([254, 1, 0, 0, 0], bytes.slice(5))
var buffer = tx.serialize()
// the deserialized-serialized transaction should return to its original state (== tx)
var bytes2 = Transaction.deserialize(mutated).serialize()
assert.deepEqual(bytes, bytes2)
// we're going to replace the 8bit VarInt for tx.ins.length with a stretched 32bit equivalent
var mutated = Buffer.concat([
buffer.slice(0, 4),
new Buffer([254, 1, 0, 0, 0]),
buffer.slice(5)
])
// the deserialized-serialized transaction should return to its non-mutated state (== tx)
var buffer2 = Transaction.deserialize(mutated).serialize()
assert.deepEqual(buffer, buffer2)
})
})
@ -128,7 +139,7 @@ describe('Transaction', function() {
assert.equal(tx.ins.length, 1)
var input = tx.ins[0]
assert.deepEqual(input.sequence, [255, 255, 255, 255])
assert.equal(input.sequence, 4294967295)
assert.equal(input.outpoint.index, 0)
assert.equal(input.outpoint.hash, "0cb859105100ebc3344f749c835c7af7d7103ec0d8cbc3d8ccbd5d28c3c36b57")

View file

@ -4,7 +4,6 @@ var T = require('../src/transaction.js')
var Transaction = T.Transaction
var TransactionOut = T.TransactionOut
var Script = require('../src/script.js')
var convert = require('../src/convert.js')
var assert = require('assert')
var sinon = require('sinon')
var crypto = require('../').crypto
@ -338,7 +337,7 @@ describe('Wallet', function() {
function verifyOutputAdded(index) {
var txOut = tx.outs[index]
var key = convert.bytesToHex(tx.getHash()) + ":" + index
var key = tx.getHash() + ":" + index
var output = wallet.outputs[key]
assert.equal(output.receive, key)
assert.equal(output.value, txOut.value)
@ -367,7 +366,7 @@ describe('Wallet', function() {
var key = txIn.outpoint.hash + ":" + txIn.outpoint.index
var output = wallet.outputs[key]
assert.equal(output.spend, convert.bytesToHex(tx.getHash()) + ':' + 0)
assert.equal(output.spend, tx.getHash() + ':' + 0)
})
})
@ -539,7 +538,7 @@ describe('Wallet', function() {
})
function fakeTxHash(i) {
return "txtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtxtx" + i
return "efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe" + i
}
})