pool: track peer heights.

This commit is contained in:
Christopher Jeffrey 2017-03-04 15:40:59 -08:00
parent beefcfba67
commit a96868ff8e
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 64 additions and 2 deletions

View File

@ -538,6 +538,8 @@ RPC.prototype.getpeerinfo = co(function* getpeerinfo(args, help) {
subver: peer.agent,
inbound: !peer.outbound,
startingheight: peer.height,
besthash: peer.bestHash,
bestheight: peer.bestHeight,
banscore: peer.banScore,
inflight: peer.requestMap.keys().map(util.revHex),
whitelisted: false

View File

@ -125,6 +125,9 @@ function Peer(options) {
this.minPing = -1;
this.blockTime = -1;
this.bestHash = null;
this.bestHeight = -1;
this.connectTimeout = null;
this.pingTimer = null;
this.invTimer = null;

View File

@ -699,6 +699,30 @@ Pool.prototype.resolveHeaders = function resolveHeaders(peer) {
this.getBlock(peer, items);
};
/**
* Update all peer heights by their best hash.
* @param {Hash} hash
* @param {Number} height
*/
Pool.prototype.resolveHeight = function resolveHeight(hash, height) {
var total = 0;
var peer;
for (peer = this.peers.head(); peer; peer = peer.next) {
if (peer.bestHash !== hash)
continue;
if (peer.bestHeight !== height) {
peer.bestHeight = height;
total++;
}
}
if (total > 0)
this.logger.debug('Resolved height for %d peers.', total);
};
/**
* Find the next checkpoint.
* @private
@ -1427,13 +1451,19 @@ Pool.prototype._handleInv = co(function* handleInv(peer, packet) {
Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
var items = [];
var i, hash;
var i, hash, exists, height;
assert(hashes.length > 0);
if (!this.syncing)
return;
// Always keep track of the peer's best hash.
if (!peer.loader || this.chain.synced) {
hash = hashes[hashes.length - 1];
peer.bestHash = hash;
}
// Ignore for now if we're still syncing
if (!this.chain.synced && !peer.loader)
return;
@ -1466,6 +1496,8 @@ Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
continue;
}
exists = hash;
// Normally we request the hashContinue.
// In the odd case where we already have
// it, we can do one of two things: either
@ -1479,6 +1511,14 @@ Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
}
}
// Attempt to update the peer's best height
// with the last existing hash we know of.
if (exists && this.chain.synced) {
height = yield this.chain.db.getHeight(exists);
if (height !== -1)
peer.bestHeight = height;
}
this.getBlock(peer, items);
});
@ -1973,7 +2013,7 @@ Pool.prototype.addBlock = co(function* addBlock(peer, block, flags) {
Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
var hash = block.hash('hex');
var entry;
var entry, height;
if (!this.syncing)
return;
@ -2008,6 +2048,17 @@ Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
return;
}
// During a getblocks sync, peers send
// their best tip frequently. We can grab
// the height commitment from the coinbase.
height = block.getCoinbaseHeight();
if (height !== -1) {
peer.bestHash = hash;
peer.bestHeight = height;
this.resolveHeight(hash, height);
}
this.logger.debug('Peer sent an orphan block. Resolving.');
yield this.resolveOrphan(peer, hash);
@ -2015,6 +2066,12 @@ Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
return;
}
if (this.chain.synced) {
peer.bestHash = entry.hash;
peer.bestHeight = entry.height;
this.resolveHeight(entry.hash, entry.height);
}
this.logStatus(block);
yield this.resolveChain(peer, hash);