From fd2f15816964fb587aedfbce99918072ca15d753 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 14 Jan 2017 06:43:49 -0800 Subject: [PATCH] net: avoid requesting duplicate blocks. avoid reconnecting to banned peers. --- lib/blockchain/chain.js | 25 ++++++++++++++++++++++++- lib/net/pool.js | 28 ++++++++++++++++++---------- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 5652eca8..d3a57f00 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -1583,7 +1583,8 @@ Chain.prototype.removeInvalid = function removeInvalid(hash) { }; /** - * Test the chain to see if it has a block, orphan, or pending block. + * Test the chain to see if it contains + * a block, or has recently seen a block. * @param {Hash} hash * @returns {Promise} - Returns Boolean. */ @@ -1595,9 +1596,31 @@ Chain.prototype.has = co(function* has(hash) { if (this.locker.has(hash)) return true; + if (this.invalid.has(hash)) + return true; + return yield this.hasEntry(hash); }); +/** + * Test the chain to see if it has recently seen a block. + * @param {Hash} hash + * @returns {Boolean} + */ + +Chain.prototype.seen = function seen(hash) { + if (this.hasOrphan(hash)) + return true; + + if (this.locker.has(hash)) + return true; + + if (this.invalid.has(hash)) + return true; + + return this.db.hasCache(hash); +}; + /** * Find a block entry by timestamp. * @param {Number} ts - Timestamp. diff --git a/lib/net/pool.js b/lib/net/pool.js index 70fd2968..359da4d0 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -879,17 +879,15 @@ Pool.prototype.handleOpen = function handleOpen(peer) { */ Pool.prototype.handleClose = co(function* handleClose(peer, connected) { - var loader = peer.isLoader(); + var outbound = peer.outbound; this.removePeer(peer); if (!this.loaded) return; - if (!loader) { - this.refill(); + if (!outbound) return; - } this.refill(); }); @@ -1427,10 +1425,13 @@ Pool.prototype.getHost = function getHost(unique) { if (!addr.hasServices(this.reqServices)) continue; - if (now - entry.lastAttempt < 600 && i < 30) + if (i < 30 && now - entry.lastAttempt < 600) continue; - if (addr.port !== this.network.port && i < 50) + if (i < 50 && addr.port !== this.network.port) + continue; + + if (i < 95 && this.hosts.isBanned(addr.host)) continue; return entry.addr; @@ -1820,22 +1821,29 @@ Pool.prototype.sendBlockRequests = function sendBlockRequests(peer) { for (i = 0; i < queue.length; i++) { hash = queue[i]; + if (hashes.length === size) + break; + assert(this.queueMap.has(hash)); this.queueMap.remove(hash); assert(!this.requestMap.has(hash)); + // Do a second check to make sure + // we don't have this in the chain. + // Avoids a potential race condition + // with the `chain.has()` call. + if (this.chain.seen(hash)) + continue; + this.requestMap.insert(hash); peer.requestMap.insert(hash); hashes.push(hash); - - if (hashes.length === size) - break; } - peer.blockQueue = queue.slice(hashes.length); + peer.blockQueue = queue.slice(i); this.logger.debug( 'Requesting %d/%d blocks from peer with getdata (%s).',