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