diff --git a/lib/net/pool.js b/lib/net/pool.js index 98533155..ccb20536 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -173,7 +173,7 @@ Pool.prototype._init = function _init() { }); this.chain.on('full', function() { - self.sync(); + self.resync(); self.emit('full'); self.logger.info('Chain is fully synced (height=%d).', self.chain.height); }); @@ -686,44 +686,20 @@ Pool.prototype.startSync = function startSync() { assert(this.connected, 'Pool is not connected!'); this.syncing = true; - this.sync(); + this.resync(false); }; /** - * Send a sync to each peer. - * @private - */ - -Pool.prototype.sync = function sync() { - var peer; - - if (!this.syncing) - return; - - for (peer = this.peers.head(); peer; peer = peer.next) { - if (!peer.outbound) - continue; - this.sendSync(peer); - } -}; - -/** - * Force sending a sync to each peer. - * @private + * Force sending of a sync to each peer. */ Pool.prototype.forceSync = function forceSync() { - var peer; - - if (!this.syncing) + if (!this.loaded) return; - for (peer = this.peers.head(); peer; peer = peer.next) { - if (!peer.outbound) - continue; - peer.syncing = false; - this.sendSync(peer); - } + assert(this.connected, 'Pool is not connected!'); + + this.resync(true); }; /** @@ -747,15 +723,43 @@ Pool.prototype.stopSync = function stopSync() { }; /** - * Start syncing from peer. - * @method - * @param {Peer} peer + * Send a sync to each peer. + * @private + * @param {Boolean?} force * @returns {Promise} */ -Pool.prototype.sendSync = co(function* sendSync(peer) { - var locator; +Pool.prototype.resync = co(function* resync(force) { + var peer, locator; + if (!this.syncing) + return; + + try { + locator = yield this.chain.getLocator(); + } catch (e) { + this.emit('error', e); + return; + } + + for (peer = this.peers.head(); peer; peer = peer.next) { + if (!peer.outbound) + continue; + + if (!force && peer.syncing) + continue; + + this.sendLocator(locator, peer); + } +}); + +/** + * Test whether a peer is sync-worthy. + * @param {Peer} peer + * @returns {Boolean} + */ + +Pool.prototype.isSyncable = function isSyncable(peer) { if (!this.syncing) return false; @@ -765,9 +769,6 @@ Pool.prototype.sendSync = co(function* sendSync(peer) { if (!peer.handshake) return false; - if (peer.syncing) - return false; - if (!(peer.services & services.NETWORK)) return false; @@ -779,6 +780,54 @@ Pool.prototype.sendSync = co(function* sendSync(peer) { return false; } + return true; +}; + +/** + * Start syncing from peer. + * @method + * @param {Peer} peer + * @returns {Promise} + */ + +Pool.prototype.sendSync = co(function* sendSync(peer) { + var locator; + + if (peer.syncing) + return false; + + if (!this.isSyncable(peer)) + return false; + + peer.syncing = true; + peer.blockTime = util.ms(); + + try { + locator = yield this.chain.getLocator(); + } catch (e) { + peer.syncing = false; + peer.blockTime = -1; + this.emit('error', e); + return false; + } + + return this.sendLocator(locator, peer); +}); + +/** + * Send a chain locator and start syncing from peer. + * @method + * @param {Hash[]} locator + * @param {Peer} peer + * @returns {Boolean} + */ + +Pool.prototype.sendLocator = function sendLocator(locator, peer) { + var locator; + + if (!this.isSyncable(peer)) + return false; + // Ask for the mempool if we're synced. if (this.network.requestMempool) { if (peer.loader && this.chain.synced) @@ -788,16 +837,6 @@ Pool.prototype.sendSync = co(function* sendSync(peer) { peer.syncing = true; peer.blockTime = util.ms(); - try { - locator = yield this.chain.getLocator(); - } catch (e) { - this.emit('error', e); - return false; - } - - if (peer.destroyed) - return false; - if (this.checkpoints) { peer.sendGetHeaders(locator, this.headerTip.hash); return true; @@ -806,7 +845,7 @@ Pool.prototype.sendSync = co(function* sendSync(peer) { peer.sendGetBlocks(locator); return true; -}); +}; /** * Send `mempool` to all peers. @@ -1336,6 +1375,7 @@ Pool.prototype.handleOpen = co(function* handleOpen(peer) { Pool.prototype.handleClose = co(function* handleClose(peer, connected) { var outbound = peer.outbound; var loader = peer.loader; + var size = peer.requestMap.size; this.removePeer(peer); @@ -1352,10 +1392,16 @@ Pool.prototype.handleClose = co(function* handleClose(peer, connected) { if (!this.loaded) return; - if (!outbound) + if (this.disconnecting) return; - if (this.disconnecting) + if (this.chain.synced && !loader && size > 0) { + this.logger.debug('Peer with requested blocks disconnected.'); + this.logger.debug('Resending sync...'); + this.forceSync(); + } + + if (!outbound) return; this.refill();