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,
|
subver: peer.agent,
|
||||||
inbound: !peer.outbound,
|
inbound: !peer.outbound,
|
||||||
startingheight: peer.height,
|
startingheight: peer.height,
|
||||||
|
besthash: peer.bestHash,
|
||||||
|
bestheight: peer.bestHeight,
|
||||||
banscore: peer.banScore,
|
banscore: peer.banScore,
|
||||||
inflight: peer.requestMap.keys().map(util.revHex),
|
inflight: peer.requestMap.keys().map(util.revHex),
|
||||||
whitelisted: false
|
whitelisted: false
|
||||||
|
|||||||
@ -125,6 +125,9 @@ function Peer(options) {
|
|||||||
this.minPing = -1;
|
this.minPing = -1;
|
||||||
this.blockTime = -1;
|
this.blockTime = -1;
|
||||||
|
|
||||||
|
this.bestHash = null;
|
||||||
|
this.bestHeight = -1;
|
||||||
|
|
||||||
this.connectTimeout = null;
|
this.connectTimeout = null;
|
||||||
this.pingTimer = null;
|
this.pingTimer = null;
|
||||||
this.invTimer = null;
|
this.invTimer = null;
|
||||||
|
|||||||
@ -699,6 +699,30 @@ Pool.prototype.resolveHeaders = function resolveHeaders(peer) {
|
|||||||
this.getBlock(peer, items);
|
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.
|
* Find the next checkpoint.
|
||||||
* @private
|
* @private
|
||||||
@ -1427,13 +1451,19 @@ Pool.prototype._handleInv = co(function* handleInv(peer, packet) {
|
|||||||
|
|
||||||
Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
|
Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
|
||||||
var items = [];
|
var items = [];
|
||||||
var i, hash;
|
var i, hash, exists, height;
|
||||||
|
|
||||||
assert(hashes.length > 0);
|
assert(hashes.length > 0);
|
||||||
|
|
||||||
if (!this.syncing)
|
if (!this.syncing)
|
||||||
return;
|
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
|
// Ignore for now if we're still syncing
|
||||||
if (!this.chain.synced && !peer.loader)
|
if (!this.chain.synced && !peer.loader)
|
||||||
return;
|
return;
|
||||||
@ -1466,6 +1496,8 @@ Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exists = hash;
|
||||||
|
|
||||||
// Normally we request the hashContinue.
|
// Normally we request the hashContinue.
|
||||||
// In the odd case where we already have
|
// In the odd case where we already have
|
||||||
// it, we can do one of two things: either
|
// 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);
|
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) {
|
Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
|
||||||
var hash = block.hash('hex');
|
var hash = block.hash('hex');
|
||||||
var entry;
|
var entry, height;
|
||||||
|
|
||||||
if (!this.syncing)
|
if (!this.syncing)
|
||||||
return;
|
return;
|
||||||
@ -2008,6 +2048,17 @@ Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
|
|||||||
return;
|
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.');
|
this.logger.debug('Peer sent an orphan block. Resolving.');
|
||||||
|
|
||||||
yield this.resolveOrphan(peer, hash);
|
yield this.resolveOrphan(peer, hash);
|
||||||
@ -2015,6 +2066,12 @@ Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.chain.synced) {
|
||||||
|
peer.bestHash = entry.hash;
|
||||||
|
peer.bestHeight = entry.height;
|
||||||
|
this.resolveHeight(entry.hash, entry.height);
|
||||||
|
}
|
||||||
|
|
||||||
this.logStatus(block);
|
this.logStatus(block);
|
||||||
|
|
||||||
yield this.resolveChain(peer, hash);
|
yield this.resolveChain(peer, hash);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user