fix orphan resolution.

This commit is contained in:
Christopher Jeffrey 2016-02-22 14:32:18 -08:00
parent 9ddc23227c
commit 0dc1b1cc5f
2 changed files with 58 additions and 53 deletions

View File

@ -1759,7 +1759,7 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
else if (hash.hash) else if (hash.hash)
hash = hash.hash('hex'); hash = hash.hash('hex');
root = hash; assert(hash);
while (this.orphan.bmap[hash]) { while (this.orphan.bmap[hash]) {
root = hash; root = hash;
@ -1769,23 +1769,6 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
return root; 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) { Chain.prototype.getHeight = function getHeight(hash) {
return this.db.getHeight(hash); return this.db.getHeight(hash);
}; };

View File

@ -66,7 +66,7 @@ function Pool(options) {
options.multiplePeers = true; options.multiplePeers = true;
} else { } else {
if (options.headers == null) if (options.headers == null)
options.headers = true; options.headers = false;
if (options.multiplePeers == null) if (options.multiplePeers == null)
options.multiplePeers = false; options.multiplePeers = false;
} }
@ -262,13 +262,35 @@ Pool.prototype.resolveOrphan = function resolveOrphan(peer, top, orphan) {
assert(orphan); assert(orphan);
this.chain.onFlush(function() { this.chain.onFlush(function() {
self.chain.getLocatorAsync(top, function(err, locator) { self.chain.getLocatorAsync(top, function(err, locator) {
var root, soil;
if (err) if (err)
throw err; throw err;
peer.getBlocks( root = self.chain.getOrphanRoot(orphan);
locator,
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) { Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
var self = this;
var i, header, last, block, blockPeer; var i, header, last, block, blockPeer;
assert(this.options.headers); assert(this.options.headers);
@ -524,39 +547,41 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
this.emit('headers', headers); this.emit('headers', headers);
for (i = 0; i < headers.length; i++) { this.chain.onFlush(function() {
block = bcoin.block(headers[i], 'header'); for (i = 0; i < headers.length; i++) {
blockPeer = peer; block = bcoin.block(headers[i], 'header');
blockPeer = peer;
// if (this.options.multiplePeers) { // if (self.options.multiplePeers) {
// if (this.peers.regular.length) { // if (self.peers.regular.length) {
// blockPeer = this.peers.regular[i % (this.peers.regular.length + 1)]; // blockPeer = self.peers.regular[i % (self.peers.regular.length + 1)];
// if (!blockPeer) // if (!blockPeer)
// blockPeer = this.peers.load; // blockPeer = self.peers.load;
// } // }
// } // }
if (last && block.prevBlock !== last.hash('hex')) if (last && block.prevBlock !== last.hash('hex'))
break; break;
if (!block.verify()) if (!block.verify())
break; break;
if (!this.chain.has(block)) if (!self.chain.has(block))
this.getData(blockPeer, this.block.type, block.hash('hex')); self.getData(blockPeer, self.block.type, block.hash('hex'));
last = block; last = block;
} }
// Restart the getheaders process // Restart the getheaders process
// Technically `last` is not indexed yet so // Technically `last` is not indexed yet so
// the locator hashes will not be entirely // the locator hashes will not be entirely
// accurate. However, it shouldn't matter // accurate. However, it shouldn't matter
// that much since FindForkInGlobalIndex // that much since FindForkInGlobalIndex
// simply tries to find the latest block in // simply tries to find the latest block in
// the peer's chain. // the peer's chain.
if (last && headers.length === 2000) if (last && headers.length === 2000)
this.getHeaders(peer, last, null); self.getHeaders(peer, last, null);
});
// Reset interval to avoid calling getheaders unnecessarily // Reset interval to avoid calling getheaders unnecessarily
this._startInterval(); this._startInterval();
@ -590,9 +615,6 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
// Resolve orphan chain. // Resolve orphan chain.
if (self.chain.hasOrphan(hash)) { if (self.chain.hasOrphan(hash)) {
utils.debug('Peer sent a hash that is already a known orphan.'); 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); self.resolveOrphan(peer, null, hash);
continue; continue;
} }