pool: track peer heights.
This commit is contained in:
parent
beefcfba67
commit
a96868ff8e
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user