Add lib/block/merkleblock.js
This commit is contained in:
parent
a9feb2b869
commit
29c18e22f0
1
index.js
1
index.js
|
@ -30,6 +30,7 @@ bitcore.errors = require('./lib/errors');
|
|||
// main bitcoin library
|
||||
bitcore.Address = require('./lib/address');
|
||||
bitcore.Block = require('./lib/block');
|
||||
bitcore.MerkleBlock = require('./lib/block/merkleblock');
|
||||
bitcore.BlockHeader = require('./lib/blockheader');
|
||||
bitcore.HDPrivateKey = require('./lib/hdprivatekey.js');
|
||||
bitcore.HDPublicKey = require('./lib/hdpublickey.js');
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
'use strict';
|
||||
var _ = require('lodash');
|
||||
var BlockHeader = require('../blockheader');
|
||||
var BufferUtil = require('../util/buffer');
|
||||
var BufferReader = require('../encoding/bufferreader');
|
||||
var BufferWriter = require('../encoding/bufferwriter');
|
||||
var JSUtil = require('../util/js');
|
||||
var $ = require('../util/preconditions');
|
||||
|
||||
/**
|
||||
* Instantiate a MerkleBlock from a Buffer, JSON object, or Object with
|
||||
* the properties of the Block
|
||||
*
|
||||
* @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock
|
||||
* @returns {MerkleBlock}
|
||||
* @constructor
|
||||
*/
|
||||
function MerkleBlock(arg) {
|
||||
if (!(this instanceof MerkleBlock)) {
|
||||
return new MerkleBlock(arg);
|
||||
}
|
||||
|
||||
var info = {};
|
||||
if (BufferUtil.isBuffer(arg)) {
|
||||
info = MerkleBlock._fromBufferReader(BufferReader(arg));
|
||||
} else if (JSUtil.isValidJSON(arg)) {
|
||||
info = MerkleBlock._fromJSON(arg);
|
||||
} else if (_.isObject(arg)) {
|
||||
var header;
|
||||
if(arg.header instanceof BlockHeader) {
|
||||
header = arg.header
|
||||
} else {
|
||||
header = BlockHeader.fromJSON(JSON.stringify(arg.header));
|
||||
}
|
||||
info = {
|
||||
/**
|
||||
* @name MerkleBlock#header
|
||||
* @type {BlockHeader}
|
||||
*/
|
||||
header: header,
|
||||
/**
|
||||
* @name MerkleBlock#numTransactions
|
||||
* @type {Number}
|
||||
*/
|
||||
numTransactions: arg.numTransactions,
|
||||
/**
|
||||
* @name MerkleBlock#hashes
|
||||
* @type {String[]}
|
||||
*/
|
||||
hashes: arg.hashes,
|
||||
/**
|
||||
* @name MerkleBlock#flags
|
||||
* @type {Number[]}
|
||||
*/
|
||||
flags: arg.flags
|
||||
};
|
||||
} else {
|
||||
throw new TypeError('Unrecognized argument for Block');
|
||||
}
|
||||
_.extend(this,info);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Buffer} - MerkleBlock data in a Buffer object
|
||||
* @returns {MerkleBlock} - A MerkleBlock object
|
||||
*/
|
||||
MerkleBlock.fromBuffer = function fromBuffer(buf) {
|
||||
return MerkleBlock.fromBufferReader(BufferReader(buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BufferReader} - MerkleBlock data in a BufferReader object
|
||||
* @returns {MerkleBlock} - A MerkleBlock object
|
||||
*/
|
||||
MerkleBlock.fromBufferReader = function fromBufferReader(br) {
|
||||
return new MerkleBlock(MerkleBlock._fromBufferReader(br));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String|Object} - A JSON String or Object
|
||||
* @returns {MerkleBlock} - A MerkleBlock object
|
||||
*/
|
||||
MerkleBlock.fromJSON = function fromJSON(buf) {
|
||||
return new MerkleBlock(MerkleBlock._fromJSON(buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Buffer} - A buffer of the block
|
||||
*/
|
||||
MerkleBlock.prototype.toBuffer = function toBuffer() {
|
||||
return this.toBufferWriter().concat();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {BufferWriter} - An existing instance of BufferWriter
|
||||
* @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock
|
||||
*/
|
||||
MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) {
|
||||
if (!bw) {
|
||||
bw = new BufferWriter();
|
||||
}
|
||||
bw.write(this.header.toBuffer());
|
||||
bw.writeUInt32LE(this.numTransactions);
|
||||
bw.writeVarintNum(this.hashes.length);
|
||||
for (var i = 0; i < this.hashes.length; i++) {
|
||||
bw.write(new Buffer(this.hashes[i], 'hex'));
|
||||
}
|
||||
bw.writeVarintNum(this.flags.length);
|
||||
for (var i = 0; i < this.flags.length; i++) {
|
||||
bw.writeUInt8(this.flags[i]);
|
||||
}
|
||||
return bw;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Object} - A plain object with the MerkleBlock properties
|
||||
*/
|
||||
MerkleBlock.prototype.toObject = function toObject() {
|
||||
return {
|
||||
header: this.header.toObject(),
|
||||
numTransactions: this.numTransactions,
|
||||
hashes: this.hashes,
|
||||
flags: this.flags
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {String} - A JSON string of a MerkleBlock
|
||||
*/
|
||||
MerkleBlock.prototype.toJSON = function toJSON() {
|
||||
return JSON.stringify(this.toObject());
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Buffer} - MerkleBlock data
|
||||
* @returns {Object} - An Object representing merkleblock data
|
||||
* @private
|
||||
*/
|
||||
MerkleBlock._fromBufferReader = function _fromBufferReader(br) {
|
||||
$.checkState(!br.finished(), 'No merkleblock data received');
|
||||
var info = {};
|
||||
info.header = BlockHeader.fromBufferReader(br);
|
||||
info.numTransactions = br.readUInt32LE();
|
||||
var numHashes = br.readVarintNum();
|
||||
info.hashes = [];
|
||||
for (var i = 0; i < numHashes; i++) {
|
||||
info.hashes.push(br.read(32).toString('hex'));
|
||||
}
|
||||
var numFlags = br.readVarintNum();
|
||||
info.flags = [];
|
||||
for (var i = 0; i < numFlags; i++) {
|
||||
info.flags.push(br.readUInt8());
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String|Object} - A JSON or String Object
|
||||
* @returns {Object} - An Object representing merkleblock data
|
||||
* @private
|
||||
*/
|
||||
MerkleBlock._fromJSON = function _fromJSON(data) {
|
||||
if (JSUtil.isValidJSON(data)) {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
var info = {
|
||||
header: BlockHeader.fromJSON(data.header),
|
||||
numTransactions: data.numTransactions,
|
||||
hashes: data.hashes,
|
||||
flags: data.flags,
|
||||
};
|
||||
return info;
|
||||
};
|
||||
|
||||
module.exports = MerkleBlock;
|
|
@ -0,0 +1,44 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
HEX: [
|
||||
// Mainnet Block 100015
|
||||
"01000000" + // Version
|
||||
"82bb869cf3a793432a66e826e05a6fc37469f8efb7421dc88067010000000000" + // prevHash
|
||||
"7f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d97287" + // MerkleRoot
|
||||
"76381b4d" + // Time
|
||||
"4c86041b" + // Bits
|
||||
"554b8529" + // Nonce
|
||||
"07000000" + // Transaction Count
|
||||
"04" + // Hash Count
|
||||
"3612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2" + // Hash1
|
||||
"019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b65" + // Hash2
|
||||
"41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068" + // Hash3
|
||||
"20d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf" + // Hash4
|
||||
"01" + // Num Flag Bytes
|
||||
"1d" // Flags
|
||||
],
|
||||
JSON: [
|
||||
{ // Mainnet Block 100015
|
||||
header: {
|
||||
version: 1,
|
||||
prevHash: "82bb869cf3a793432a66e826e05a6fc37469f8efb7421dc88067010000000000",
|
||||
merkleRoot: "7f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d97287",
|
||||
time: 1293629558,
|
||||
bits: 453281356,
|
||||
nonce: 151839121
|
||||
},
|
||||
numTransactions: 7,
|
||||
hashes: [
|
||||
"3612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2",
|
||||
"019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b65",
|
||||
"41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068",
|
||||
"20d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf"
|
||||
],
|
||||
flags: [ 29 ]
|
||||
}
|
||||
|
||||
|
||||
|
||||
]
|
||||
};
|
|
@ -0,0 +1,132 @@
|
|||
'use strict';
|
||||
|
||||
var bitcore = require('..'),
|
||||
BufferUtil = bitcore.util.buffer,
|
||||
MerkleBlock = bitcore.MerkleBlock,
|
||||
BlockHeader = bitcore.BlockHeader,
|
||||
BufferReader = bitcore.encoding.BufferReader,
|
||||
BufferWriter = bitcore.encoding.BufferWriter,
|
||||
data = require('./data/merkleblocks.js');
|
||||
|
||||
describe('MerkleBlock', function() {
|
||||
var blockhex = data.HEX[0];
|
||||
var blockbuf = new Buffer(blockhex,'hex');
|
||||
var blockJSON = JSON.stringify(data.JSON[0]);
|
||||
var blockObject = JSON.parse(JSON.stringify(data.JSON[0]));
|
||||
|
||||
describe('#constructor', function() {
|
||||
it('should make a new merkleblock from buffer', function() {
|
||||
var b = MerkleBlock(blockbuf);
|
||||
b.toBuffer().toString('hex').should.equal(blockhex);
|
||||
});
|
||||
|
||||
it('should make a new merkleblock from object', function() {
|
||||
var b = MerkleBlock(blockObject);
|
||||
b.toObject().should.deep.equal(blockObject);
|
||||
});
|
||||
|
||||
it('should make a new merkleblock from JSON', function() {
|
||||
var b = MerkleBlock(blockJSON);
|
||||
b.toJSON().should.equal(blockJSON);
|
||||
});
|
||||
|
||||
it('should not make an empty block', function() {
|
||||
(function() {
|
||||
return new MerkleBlock();
|
||||
}).should.throw('Unrecognized argument for Block');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fromJSON', function() {
|
||||
|
||||
it('should set these known values', function() {
|
||||
var block = MerkleBlock.fromJSON(blockJSON);
|
||||
should.exist(block.header);
|
||||
should.exist(block.numTransactions);
|
||||
should.exist(block.hashes);
|
||||
should.exist(block.flags);
|
||||
});
|
||||
|
||||
it('should set these known values', function() {
|
||||
var block = MerkleBlock(blockJSON);
|
||||
should.exist(block.header);
|
||||
should.exist(block.numTransactions);
|
||||
should.exist(block.hashes);
|
||||
should.exist(block.flags);
|
||||
});
|
||||
|
||||
it('accepts an object as argument', function() {
|
||||
var block = MerkleBlock(blockbuf);
|
||||
MerkleBlock.fromJSON(block.toObject()).should.exist();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#toJSON', function() {
|
||||
|
||||
it('should recover these known values', function() {
|
||||
var block = MerkleBlock.fromJSON(blockJSON);
|
||||
var b = JSON.parse(block.toJSON());
|
||||
should.exist(block.header);
|
||||
should.exist(block.numTransactions);
|
||||
should.exist(block.hashes);
|
||||
should.exist(block.flags);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// TODO
|
||||
//describe('#fromString/#toString', function() {
|
||||
|
||||
//it('should output/input a block hex string', function() {
|
||||
//var b = MerkleBlock.fromString(blockhex);
|
||||
//b.toString().should.equal(blockhex);
|
||||
//});
|
||||
|
||||
//});
|
||||
|
||||
describe('#fromBuffer', function() {
|
||||
|
||||
it('should make a block from this known buffer', function() {
|
||||
var block = MerkleBlock.fromBuffer(blockbuf);
|
||||
block.toBuffer().toString('hex').should.equal(blockhex);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#fromBufferReader', function() {
|
||||
|
||||
it('should make a block from this known buffer', function() {
|
||||
var block = MerkleBlock.fromBufferReader(BufferReader(blockbuf));
|
||||
block.toBuffer().toString('hex').should.equal(blockhex);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#toBuffer', function() {
|
||||
|
||||
it('should recover a block from this known buffer', function() {
|
||||
var block = MerkleBlock.fromBuffer(blockbuf);
|
||||
block.toBuffer().toString('hex').should.equal(blockhex);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#toBufferWriter', function() {
|
||||
|
||||
it('should recover a block from this known buffer', function() {
|
||||
var block = MerkleBlock.fromBuffer(blockbuf);
|
||||
block.toBufferWriter().concat().toString('hex').should.equal(blockhex);
|
||||
});
|
||||
|
||||
it('doesn\'t create a bufferWriter if one provided', function() {
|
||||
var writer = new BufferWriter();
|
||||
var block = MerkleBlock.fromBuffer(blockbuf);
|
||||
block.toBufferWriter(writer).should.equal(writer);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue