chainentry refactor.

This commit is contained in:
Christopher Jeffrey 2016-06-28 23:21:14 -07:00
parent 634290687b
commit 1aa70f8ff0
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -25,7 +25,7 @@ var InvItem = bcoin.packets.InvItem;
* @exports ChainEntry
* @constructor
* @param {Chain} chain
* @param {Object} data
* @param {Object} options
* @param {ChainEntry} prev
* @property {Hash} hash
* @property {Number} version - Transaction version. Note that BCoin reads
@ -41,27 +41,73 @@ var InvItem = bcoin.packets.InvItem;
* @property {ReversedHash} rhash - Reversed block hash (uint256le).
*/
function ChainEntry(chain, data, prev) {
function ChainEntry(chain, options, prev) {
if (!(this instanceof ChainEntry))
return new ChainEntry(chain, data);
return new ChainEntry(chain, options, prev);
this.chain = chain;
this.network = chain ? chain.network : bcoin.network.get();
this.network = this.chain
? this.chain.network
: bcoin.network.get();
this.hash = constants.NULL_HASH;
this.version = 1;
this.prevBlock = constants.NULL_HASH;
this.merkleRoot = constants.NULL_HASH;
this.ts = 0;
this.bits = 0;
this.nonce = 0;
this.height = -1;
this.chainwork = null;
this.hash = data.hash;
this.version = data.version;
this.prevBlock = data.prevBlock;
this.merkleRoot = data.merkleRoot;
this.ts = data.ts;
this.bits = data.bits;
this.nonce = data.nonce;
this.height = data.height;
this.chainwork = data.chainwork || this.getChainwork(prev);
if (options)
this.fromOptions(options, prev);
}
/**
* Inject properties from options.
* @private
* @param {Object} options
* @param {ChainEntry} prev - Previous entry.
*/
ChainEntry.prototype.fromOptions = function fromOptions(options, prev) {
assert(options, 'Block data is required.');
assert(typeof options.hash === 'string');
assert(utils.isNumber(options.version));
assert(typeof options.prevBlock === 'string');
assert(typeof options.merkleRoot === 'string');
assert(utils.isNumber(options.ts));
assert(utils.isNumber(options.bits));
assert(utils.isNumber(options.nonce));
assert(!options.chainwork || bn.isBN(options.chainwork));
this.hash = options.hash;
this.version = options.version;
this.prevBlock = options.prevBlock;
this.merkleRoot = options.merkleRoot;
this.ts = options.ts;
this.bits = options.bits;
this.nonce = options.nonce;
this.height = options.height;
this.chainwork = options.chainwork;
if (!this.chainwork)
this.chainwork = this.getChainwork(prev);
return this;
};
/**
* Instantiate chainentry from options.
* @param {Chain} chain
* @param {Object} options
* @param {ChainEntry} prev - Previous entry.
* @returns {ChainEntry}
*/
ChainEntry.fromOptions = function fromOptions(chain, options, prev) {
return new ChainEntry(chain).fromOptions(options, prev);
};
/**
* The max chainwork (1 << 256).
* @const {BN}
@ -401,6 +447,41 @@ ChainEntry.prototype.__defineGetter__('rhash', function() {
return utils.revHex(this.hash);
});
/**
* Inject properties from block.
* @private
* @param {Block|MerkleBlock} block
* @param {ChainEntry} prev - Previous entry.
*/
ChainEntry.prototype.fromBlock = function fromBlock(block, prev) {
assert(block.height !== -1);
this.hash = block.hash('hex');
this.version = block.version;
this.prevBlock = block.prevBlock;
this.merkleRoot = block.merkleRoot;
this.ts = block.ts;
this.bits = block.bits;
this.nonce = block.nonce;
this.height = block.height;
this.chainwork = this.getChainwork(prev);
return this;
};
/**
* Instantiate chainentry from block.
* @param {Chain} chain
* @param {Block|MerkleBlock} block
* @param {ChainEntry} prev - Previous entry.
* @returns {ChainEntry}
*/
ChainEntry.fromBlock = function fromBlock(chain, block, prev) {
return new ChainEntry(chain).fromBlock(block, prev);
};
/**
* Serialize the entry to internal database format.
* @returns {Buffer}
@ -425,29 +506,39 @@ ChainEntry.prototype.toRaw = function toRaw(writer) {
};
/**
* Deserialize the entry.
* @param {Chain} chain
* @param {Buffer} buf
* @returns {ChainEntry}
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
ChainEntry.fromRaw = function fromRaw(chain, buf) {
var p = new BufferReader(buf, true);
ChainEntry.prototype.fromRaw = function fromRaw(data) {
var p = new BufferReader(data, true);
var hash = utils.hash256(p.readBytes(80));
p.seek(-80);
return new ChainEntry(chain, {
hash: hash.toString('hex'),
version: p.readU32(), // Technically signed
prevBlock: p.readHash('hex'),
merkleRoot: p.readHash('hex'),
ts: p.readU32(),
bits: p.readU32(),
nonce: p.readU32(),
height: p.readU32(),
chainwork: new bn(p.readBytes(32), 'le')
});
this.hash = hash.toString('hex');
this.version = p.readU32(); // Technically signed
this.prevBlock = p.readHash('hex');
this.merkleRoot = p.readHash('hex');
this.ts = p.readU32();
this.bits = p.readU32();
this.nonce = p.readU32();
this.height = p.readU32();
this.chainwork = new bn(p.readBytes(32), 'le');
return this;
};
/**
* Deserialize the entry.
* @param {Chain} chain
* @param {Buffer} data
* @returns {ChainEntry}
*/
ChainEntry.fromRaw = function fromRaw(chain, data) {
return new ChainEntry(chain).fromRaw(data);
};
/**
@ -470,6 +561,36 @@ ChainEntry.prototype.toJSON = function toJSON() {
};
};
/**
* Inject properties from json object.
* @private
* @param {Object} json
*/
ChainEntry.prototype.fromJSON = function fromJSON(json) {
assert(json, 'Block data is required.');
assert(typeof json.hash === 'string');
assert(utils.isNumber(json.version));
assert(typeof json.prevBlock === 'string');
assert(typeof json.merkleRoot === 'string');
assert(utils.isNumber(json.ts));
assert(utils.isNumber(json.bits));
assert(utils.isNumber(json.nonce));
assert(typeof json.chainwork === 'string');
this.hash = utils.revHex(json.hash);
this.version = json.version;
this.prevBlock = utils.revHex(json.prevBlock);
this.merkleRoot = utils.revHex(json.merkleRoot);
this.ts = json.ts;
this.bits = json.bits;
this.nonce = json.nonce;
this.height = json.height;
this.chainwork = new bn(json.chainwork, 10);
return this;
};
/**
* Instantiate block from jsonified object.
* @param {Chain} chain
@ -478,17 +599,7 @@ ChainEntry.prototype.toJSON = function toJSON() {
*/
ChainEntry.fromJSON = function fromJSON(chain, json) {
return new ChainEntry(chain, {
hash: utils.revHex(json.hash),
version: json.version,
prevBlock: utils.revHex(json.prevBlock),
merkleRoot: utils.revHex(json.merkleRoot),
ts: json.ts,
bits: json.bits,
nonce: json.nonce,
height: json.height,
chainwork: new bn(json.chainwork, 10)
});
return new ChainEntry(chain).fromJSON(json);
};
/**
@ -526,7 +637,7 @@ ChainEntry.prototype.inspect = function inspect() {
ChainEntry.isChainEntry = function isChainEntry(obj) {
return obj
&& bn.isBN(obj.chainwork)
&& obj.chainwork !== undefined
&& typeof obj.getMedianTime === 'function';
};