block serialization: Add option skip magic numbers
This commit is contained in:
parent
b6ba5dbc5a
commit
b416655222
68
lib/block.js
68
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]]);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -9,8 +9,7 @@
|
||||
"bits": 473956288,
|
||||
"nonce": 3594009557
|
||||
},
|
||||
"txsvi": "16",
|
||||
"txs": [{
|
||||
"transactions": [{
|
||||
"version": 1,
|
||||
"txinsvi": "01",
|
||||
"txins": [{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user