diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index e799e8d5..1f3d1f68 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1759,7 +1759,7 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) { else if (hash.hash) hash = hash.hash('hex'); - root = hash; + assert(hash); while (this.orphan.bmap[hash]) { root = hash; @@ -1769,23 +1769,6 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) { return root; }; -Chain.prototype.getOrphanSoil = function getOrphanSoil(hash) { - var root; - - if (utils.isBuffer(hash)) - hash = utils.toHex(hash); - else if (hash.hash) - hash = hash.hash('hex'); - - while (this.orphan.bmap[hash]) { - root = this.orphan.bmap[hash]; - hash = this.orphan.bmap[hash].prevBlock; - } - - if (root) - return root.prevBlock; -}; - Chain.prototype.getHeight = function getHeight(hash) { return this.db.getHeight(hash); }; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 08a2eccb..496a7df2 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -66,7 +66,7 @@ function Pool(options) { options.multiplePeers = true; } else { if (options.headers == null) - options.headers = true; + options.headers = false; if (options.multiplePeers == null) options.multiplePeers = false; } @@ -262,13 +262,35 @@ Pool.prototype.resolveOrphan = function resolveOrphan(peer, top, orphan) { assert(orphan); this.chain.onFlush(function() { self.chain.getLocatorAsync(top, function(err, locator) { + var root, soil; + if (err) throw err; - peer.getBlocks( - locator, - self.chain.getOrphanRoot(orphan) - ); + root = self.chain.getOrphanRoot(orphan); + + // Was probably resolved. + if (!root) { + utils.debug('Orphan root was already resolved.'); + return; + } + + // Get the block that would resolve the chain. + soil = self.chain.getOrphan(root).prevBlock; + + // If we're already processing the block + // that would resolve this, ignore. + if (self.request.map[soil] || self.chain.hasPending(soil)) { + utils.debug('Already processing orphan "soil".'); + return; + } + + if (self.chain.has(soil)) { + utils.debug('Already have orphan "soil". Race condition?'); + return; + } + + peer.getBlocks(locator, root); }); }); }; @@ -505,6 +527,7 @@ Pool.prototype.stopSync = function stopSync() { }; Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) { + var self = this; var i, header, last, block, blockPeer; assert(this.options.headers); @@ -524,39 +547,41 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) { this.emit('headers', headers); - for (i = 0; i < headers.length; i++) { - block = bcoin.block(headers[i], 'header'); - blockPeer = peer; + this.chain.onFlush(function() { + for (i = 0; i < headers.length; i++) { + block = bcoin.block(headers[i], 'header'); + blockPeer = peer; - // if (this.options.multiplePeers) { - // if (this.peers.regular.length) { - // blockPeer = this.peers.regular[i % (this.peers.regular.length + 1)]; - // if (!blockPeer) - // blockPeer = this.peers.load; - // } - // } + // if (self.options.multiplePeers) { + // if (self.peers.regular.length) { + // blockPeer = self.peers.regular[i % (self.peers.regular.length + 1)]; + // if (!blockPeer) + // blockPeer = self.peers.load; + // } + // } - if (last && block.prevBlock !== last.hash('hex')) - break; + if (last && block.prevBlock !== last.hash('hex')) + break; - if (!block.verify()) - break; + if (!block.verify()) + break; - if (!this.chain.has(block)) - this.getData(blockPeer, this.block.type, block.hash('hex')); + if (!self.chain.has(block)) + self.getData(blockPeer, self.block.type, block.hash('hex')); - last = block; - } + last = block; + } - // Restart the getheaders process - // Technically `last` is not indexed yet so - // the locator hashes will not be entirely - // accurate. However, it shouldn't matter - // that much since FindForkInGlobalIndex - // simply tries to find the latest block in - // the peer's chain. - if (last && headers.length === 2000) - this.getHeaders(peer, last, null); + // Restart the getheaders process + // Technically `last` is not indexed yet so + // the locator hashes will not be entirely + // accurate. However, it shouldn't matter + // that much since FindForkInGlobalIndex + // simply tries to find the latest block in + // the peer's chain. + if (last && headers.length === 2000) + self.getHeaders(peer, last, null); + }); // Reset interval to avoid calling getheaders unnecessarily this._startInterval(); @@ -590,9 +615,6 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) { // Resolve orphan chain. if (self.chain.hasOrphan(hash)) { utils.debug('Peer sent a hash that is already a known orphan.'); - // var soil = self.chain.getOrphanSoil(hash); - // if (self.request.map[soil] || self.chain.hasPending(soil)) - // break; self.resolveOrphan(peer, null, hash); continue; }