diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 6a14e270..3411d112 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -768,7 +768,7 @@ Chain.prototype._findFork = function _findFork(fork, longer, callback) { if (longer.height <= fork.height) return done(); - self.db.get(longer.prevBlock, function(err, entry) { + longer.getPrevious(function(err, entry) { if (err) return callback(err); @@ -785,7 +785,7 @@ Chain.prototype._findFork = function _findFork(fork, longer, callback) { if (fork.hash === longer.hash) return callback(null, fork); - self.db.get(fork.prevBlock, function(err, entry) { + fork.getPrevious(function(err, entry) { if (err) return callback(err); @@ -814,7 +814,7 @@ Chain.prototype._reorganize = function _reorganize(entry, callback) { var entries = []; (function collect(entry) { - self.db.get(entry.prevBlock, function(err, entry) { + entry.getPrevious(function(err, entry) { if (err) return callback(err); @@ -871,7 +871,7 @@ Chain.prototype._reorganize = function _reorganize(entry, callback) { var entries = []; (function collect(entry) { - self.db.get(entry.prevBlock, function(err, entry) { + entry.getPrevious(function(err, entry) { if (err) return callback(err); @@ -1332,8 +1332,6 @@ Chain.prototype.add = function add(initial, peer, callback, force) { if (entry.chainwork.cmp(self.tip.chainwork) <= 0) return done(); - // Add entry if we do not have it. - // Update the block height block.height = entry.height; block.txs.forEach(function(tx) { @@ -1706,7 +1704,7 @@ Chain.prototype.getLocator = function getLocator(start, callback, force) { return callback(null, top); } - getTop(function(err, top) { + return getTop(function(err, top) { if (err) { unlock(); return callback(err); @@ -1808,7 +1806,7 @@ Chain.prototype.getTargetAsync = function getTarget(last, block, callback) { if (last.height > 0 && last.height % network.powDiffInterval !== 0 && last.bits === powLimit) { - return self.db.get(last.prevBlock, next); + return last.getPrevious(next); } return callback(null, last.bits); @@ -1829,7 +1827,7 @@ Chain.prototype.getTargetAsync = function getTarget(last, block, callback) { if (i >= network.powDiffInterval) return callback(null, self.retarget(last, first)); - self.db.get(first.prevBlock, next); + first.getPrevious(next); })(null, last); }; @@ -1928,7 +1926,7 @@ Chain.prototype.getState = function getState(prev, block, id, callback) { var bits = entry.version & constants.versionbits.TOP_MASK; var topBits = constants.versionbits.TOP_BITS; var mask = 1 << deployment.bit; - return (bits === topBits) && (entry.version & mask) !== 0; + return bits === topBits && (entry.version & mask) !== 0; } (function walk(err, entry) { @@ -1999,7 +1997,7 @@ Chain.prototype.getState = function getState(prev, block, id, callback) { if (condition(entry)) count++; - return self.db.get(entry.prevBlock, next); + return entry.getPrevious(next); })(null, entry); function doneCounting(err) { diff --git a/lib/bcoin/chainblock.js b/lib/bcoin/chainblock.js index 1ff5b527..8285adf9 100644 --- a/lib/bcoin/chainblock.js +++ b/lib/bcoin/chainblock.js @@ -82,7 +82,7 @@ ChainBlock.prototype.toRaw = function toRaw() { utils.writeU32(res, this.bits, 72); utils.writeU32(res, this.nonce, 76); utils.writeU32(res, this.height, 80); - utils.copy(new Buffer(this.chainwork.toArray('be', 32)), res, 84); + utils.copy(new Buffer(this.chainwork.toArray('le', 32)), res, 84); return res; }; @@ -97,7 +97,7 @@ ChainBlock.fromRaw = function fromRaw(chain, p) { bits: utils.readU32(p, 72), nonce: utils.readU32(p, 76), height: utils.readU32(p, 80), - chainwork: new bn(p.slice(84, 116), 'be') + chainwork: new bn(p.slice(84, 116), 'le') }); }; @@ -119,7 +119,7 @@ ChainBlock.prototype.getMedianTimeAsync = function getMedianTime(callback) { median[i] = entry.ts; i++; - self.chain.db.get(entry.prevBlock, next); + entry.getPrevious(next); })(null, this); }; @@ -149,7 +149,7 @@ ChainBlock.prototype.isSuperMajorityAsync = function isSuperMajority(version, re i++; - self.chain.db.get(entry.prevBlock, next); + entry.getPrevious(next); })(null, this); }; @@ -225,7 +225,7 @@ ChainBlock.prototype.getAncestors = function getAncestors(max, callback) { if (previous.length >= max) return callback(null, previous); - self.chain.db.get(entry.prevBlock, next); + entry.getPrevious(next); })(null, entry); }; @@ -233,19 +233,65 @@ ChainBlock.prototype.free = function free() { this.previous.length = 0; }; +ChainBlock.prototype.isMainChain = function isMainChain(callback) { + var self = this; + return this.chain.db.getHash(this.height, function(err, hash) { + if (err) + return callback(err); + + if (!hash) + return callback(null, false); + + return callback(null, self.hash === hash); + }); +}; + ChainBlock.prototype.getAncestorByHeight = function getAncestorByHeight(height, callback) { + assert(height >= 0); assert(height <= this.height); - return this.getAncestor(this.height - height, callback); + return this.getAncestor(this.height - height, function(err, entry) { + if (err) + return callback(err); + + if (!entry) + return callback(); + + assert(entry.height === height); + + return callback(null, entry); + }); }; ChainBlock.prototype.getAncestor = function getAncestor(index, callback) { + assert(index >= 0); return this.getAncestors(index + 1, function(err, previous) { if (err) return callback(err); + + if (previous.length !== index + 1) + return callback(); + return callback(null, previous[previous.length - 1]); }); }; +ChainBlock.prototype.getPrevious = function getPrevious(callback) { + return this.chain.db.get(this.prevBlock, callback); +}; + +ChainBlock.prototype.getNext = function getNext(callback) { + var self = this; + return this.chain.db.getNextHash(this.hash, function(err, hash) { + if (err) + return callback(err); + + if (!hash) + return callback(); + + return self.chain.db.get(hash, callback); + }); +}; + ChainBlock.prototype.getMedianTime = function getMedianTime(previous) { var entry = this; var median = []; @@ -300,6 +346,18 @@ ChainBlock.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback) }); }; +ChainBlock.prototype.inspect = function inspect() { + var copy = new ChainBlock(this.chain, this, null); + copy.__proto__ = null; + copy.hash = utils.revHex(copy.hash); + copy.prevBlock = utils.revHex(copy.prevBlock); + copy.merkleRoot = utils.revHex(copy.merkleRoot); + copy.chainwork = copy.chainwork.toString(10); + delete copy.chain; + copy.previous = this.previous.length; + return copy; +}; + /** * Expose */ diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index e43288eb..16342f96 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -1673,8 +1673,8 @@ utils.getMerkleRoot = function getMerkleRoot(leaves) { utils.getMerkleBranch = function getMerkleBranch(index, leaves) { var tree = utils.buildMerkleTree(leaves); + var size = leaves.length; var branch = []; - var size = this.totalTX; var j = 0; var i;