From b41665522287caa066012243128dba5e4932a33e Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Fri, 16 Jan 2015 16:54:32 -0300 Subject: [PATCH] block serialization: Add option skip magic numbers --- lib/block.js | 68 +++++++++++++++++---------------- lib/blockheader.js | 15 ++++---- test/block.js | 28 ++++++-------- test/data/blk86756-testnet.json | 3 +- 4 files changed, 54 insertions(+), 60 deletions(-) diff --git a/lib/block.js b/lib/block.js index e69fd8a..015d2b0 100644 --- a/lib/block.js +++ b/lib/block.js @@ -59,12 +59,11 @@ Block._from = function _from(arg) { * @type {BlockHeader} */ header: arg.header, - txsvi: arg.txsvi, /** - * @name Block#txs + * @name Block#transactions * @type {Transaction[]} */ - txs: arg.txs + transactions: arg.transactions }; } else { throw new TypeError('Unrecognized argument for Block'); @@ -81,16 +80,15 @@ Block._fromJSON = function _fromJSON(data) { if (JSUtil.isValidJSON(data)) { data = JSON.parse(data); } - var txs = []; - data.txs.forEach(function(tx) { - txs.push(Transaction().fromJSON(tx)); + var transactions = []; + data.transactions.forEach(function(data) { + transactions.push(Transaction().fromJSON(data)); }); var info = { magicnum: data.magicnum, size: data.size, header: BlockHeader.fromJSON(data.header), - txsvi: Varint().fromString(data.txsvi), - txs: txs + transactions: transactions }; return info; }; @@ -109,16 +107,22 @@ Block.fromJSON = function fromJSON(json) { * @returns {Object} - An object representing the block data * @private */ -Block._fromBufferReader = function _fromBufferReader(br) { +Block._fromBufferReader = function _fromBufferReader(br, options) { + options = options || {}; var info = {}; - info.magicnum = br.readUInt32LE(); - info.size = br.readUInt32LE(); + if (!options.skipMagic) { + info.magicnum = br.readUInt32LE(); + info.size = br.readUInt32LE(); + } info.header = BlockHeader.fromBufferReader(br); - info.txsvi = Varint(br.readVarintBuf()); - var txslen = info.txsvi.toNumber(); - info.txs = []; - for (var i = 0; i < txslen; i++) { - info.txs.push(Transaction().fromBufferReader(br)); + if (options.skipMagic) { + info.magicnum = 0; + info.size = info.header.bits; + } + var transactions = br.readVarintNum(); + info.transactions = []; + for (var i = 0; i < transactions; i++) { + info.transactions.push(Transaction().fromBufferReader(br)); } return info; }; @@ -127,8 +131,8 @@ Block._fromBufferReader = function _fromBufferReader(br) { * @param {BufferReader} - A buffer reader of the block * @returns {Block} - An instance of block */ -Block.fromBufferReader = function fromBufferReader(br) { - var info = Block._fromBufferReader(br); +Block.fromBufferReader = function fromBufferReader(br, opts) { + var info = Block._fromBufferReader(br, opts); return new Block(info); }; @@ -136,8 +140,8 @@ Block.fromBufferReader = function fromBufferReader(br) { * @param {Buffer} - A buffer of the block * @returns {Block} - An instance of block */ -Block.fromBuffer = function fromBuffer(buf) { - return Block.fromBufferReader(BufferReader(buf)); +Block.fromBuffer = function fromBuffer(buf, opts) { + return Block.fromBufferReader(BufferReader(buf), opts); }; /** @@ -166,16 +170,15 @@ Block.fromRawBlock = function fromRawBlock(data) { * @returns {Object} - A plain object with the block properties */ Block.prototype.toObject = function toObject() { - var txs = []; - this.txs.forEach(function(tx) { - txs.push(tx.toObject()); + var transactions = []; + this.transactions.forEach(function(tx) { + transactions.push(tx.toObject()); }); return { magicnum: this.magicnum, size: this.size, header: this.header.toObject(), - txsvi: this.txsvi.toString(), - txs: txs + transactions: transactions }; }; @@ -211,10 +214,9 @@ Block.prototype.toBufferWriter = function toBufferWriter(bw) { bw.writeUInt32LE(this.magicnum); bw.writeUInt32LE(this.size); bw.write(this.header.toBuffer()); - bw.write(this.txsvi.buf); - var txslen = this.txsvi.toNumber(); - for (var i = 0; i < txslen; i++) { - this.txs[i].toBufferWriter(bw); + bw.writeVarintNum(this.transactions.length); + for (var i = 0; i < this.transactions.length; i++) { + this.transactions[i].toBufferWriter(bw); } return bw; }; @@ -225,11 +227,11 @@ Block.prototype.toBufferWriter = function toBufferWriter(bw) { */ Block.prototype.getTransactionHashes = function getTransactionHashes() { var hashes = []; - if (this.txs.length === 0) { + if (this.transactions.length === 0) { return [Block.Values.NULL_HASH]; } - for (var t = 0; t < this.txs.length; t++) { - hashes.push(this.txs[t]._getHash()); + for (var t = 0; t < this.transactions.length; t++) { + hashes.push(this.transactions[t]._getHash()); } return hashes; }; @@ -245,7 +247,7 @@ Block.prototype.getMerkleTree = function getMerkleTree() { var tree = this.getTransactionHashes(); var j = 0; - for (var size = this.txs.length; size > 1; size = Math.floor((size + 1) / 2)) { + for (var size = this.transactions.length; size > 1; size = Math.floor((size + 1) / 2)) { for (var i = 0; i < size; i += 2) { var i2 = Math.min(i + 1, size - 1); var buf = Buffer.concat([tree[j + i], tree[j + i2]]); diff --git a/lib/blockheader.js b/lib/blockheader.js index 80ad727..7c18c1b 100644 --- a/lib/blockheader.js +++ b/lib/blockheader.js @@ -119,14 +119,13 @@ BlockHeader.fromString = function fromString(str) { * @private */ BlockHeader._fromBufferReader = function _fromBufferReader(br) { - var info = { - version: br.readUInt32LE(), - prevHash: br.read(32), - merkleRoot: br.read(32), - time: br.readUInt32LE(), - bits: br.readUInt32LE(), - nonce: br.readUInt32LE() - }; + var info = {}; + info.version = br.readUInt32LE(); + info.prevHash = br.read(32); + info.merkleRoot = br.read(32); + info.time = br.readUInt32LE(); + info.bits = br.readUInt32LE(); + info.nonce = br.readUInt32LE(); return info; }; diff --git a/test/block.js b/test/block.js index 8df1360..d3b9771 100644 --- a/test/block.js +++ b/test/block.js @@ -27,9 +27,8 @@ describe('Block', function() { var blockbuf = new Buffer(blockhex, 'hex'); var size = data.blocksize; var bh = BlockHeader.fromBuffer(new Buffer(data.blockheaderhex, 'hex')); - var txsvi = Varint().fromNumber(data.txsvi); var txs = []; - JSON.parse(dataJson).txs.forEach(function(tx){ + JSON.parse(dataJson).transactions.forEach(function(tx){ txs.push(new Transaction().fromJSON(tx)); }); var json = dataJson; @@ -45,7 +44,7 @@ describe('Block', function() { it('should not make an empty block', function() { (function() { - var b = new Block(); + return new Block(); }).should.throw('Unrecognized argument for Block'); }); @@ -56,20 +55,18 @@ describe('Block', function() { magicnum: magicnum, size: size, header: bh, - txsvi: txsvi, - txs: txs + transactions: txs }); should.exist(b.magicnum); should.exist(b.size); - should.exist(b.txsvi); should.exist(b.header); - should.exist(b.txs); + should.exist(b.transactions); }); it('should properly deserialize blocks', function() { dataBlocks.forEach(function(block){ - var b = Block.fromBuffer(new Buffer(block.data, 'hex')); - b.txs.length.should.equal(block.transactions); + var b = Block.fromBuffer(new Buffer(block.data, 'hex'), {skipMagic: true}); + b.transactions.length.should.equal(block.transactions); }); }); @@ -98,8 +95,7 @@ describe('Block', function() { should.exist(block.magicnum); should.exist(block.size); should.exist(block.header); - should.exist(block.txsvi); - should.exist(block.txs); + should.exist(block.transactions); }); it('should set these known values', function() { @@ -108,8 +104,7 @@ describe('Block', function() { should.exist(block.magicnum); should.exist(block.size); should.exist(block.header); - should.exist(block.txsvi); - should.exist(block.txs); + should.exist(block.transactions); }); it('accepts an object as argument', function() { @@ -127,8 +122,7 @@ describe('Block', function() { should.exist(b.magicnum); should.exist(b.size); should.exist(b.header); - should.exist(b.txsvi); - should.exist(b.txs); + should.exist(b.transactions); }); }); @@ -225,14 +219,14 @@ describe('Block', function() { it('should describe as invalid merkle root', function() { var x = Block.fromRawBlock(dataRawBlockBinary); - x.txs.push(new Transaction()); + x.transactions.push(new Transaction()); var valid = x.validMerkleRoot(); valid.should.equal(false); }); it('should get a null hash merkle root', function() { var x = Block.fromRawBlock(dataRawBlockBinary); - x.txs = []; // empty the txs + x.transactions = []; // empty the txs var mr = x.getMerkleRoot(); mr.should.deep.equal(Block.Values.NULL_HASH); }); diff --git a/test/data/blk86756-testnet.json b/test/data/blk86756-testnet.json index 0e0799f..0450b7c 100644 --- a/test/data/blk86756-testnet.json +++ b/test/data/blk86756-testnet.json @@ -9,8 +9,7 @@ "bits": 473956288, "nonce": 3594009557 }, - "txsvi": "16", - "txs": [{ + "transactions": [{ "version": 1, "txinsvi": "01", "txins": [{