From dd53e43958129331f72eff6866dda30aa2138cd5 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 27 Aug 2016 15:53:04 -0700 Subject: [PATCH] pool: repurpose regular peers if no loader is available. --- lib/net/peer.js | 12 ++--- lib/net/pool.js | 114 ++++++++++++++++++++++++++++++------------------ 2 files changed, 78 insertions(+), 48 deletions(-) diff --git a/lib/net/peer.js b/lib/net/peer.js index b8017d2e..7f9aeedb 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -417,12 +417,6 @@ Peer.prototype._onAck = function _onAck(err) { // Start syncing the chain. this.sync(); - // Ask for the mempool if we're synced. - if (this.network.requestMempool) { - if (this.isLoader() && this.chain.synced) - this.sendMempool(); - } - this.logger.debug('Received verack (%s).', this.hostname); // Finally we can let the pool know @@ -2397,6 +2391,12 @@ Peer.prototype.sync = function sync(callback) { return; } + // Ask for the mempool if we're synced. + if (this.network.requestMempool) { + if (this.isLoader() && this.chain.synced) + this.sendMempool(); + } + this.syncSent = true; if (this.options.headers) { diff --git a/lib/net/pool.js b/lib/net/pool.js index 7bfc28d0..0405c385 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -275,20 +275,8 @@ Pool.prototype._init = function _init() { this.chain.on('full', function() { self.stopTimeout(); self.stopInterval(); - - if (!self.chain.synced) { - // Ask loader for a mempool snapshot. - if (self.network.requestMempool) { - if (self.peers.load) - self.peers.load.sendMempool(); - } - - // Ask all peers for their latest blocks. - self.sync(); - } - + self.sync(); self.emit('full'); - self.logger.info('Chain is fully synced (height=%d).', self.chain.height); }); }; @@ -626,21 +614,16 @@ Pool.prototype.addLoader = function addLoader() { addr = this.getLoaderHost(); peer = this.peers.get(addr); + if (peer) { + this.setLoader(peer); + return; + } + if (this.syncing) { this.startTimeout(); this.startInterval(); } - if (peer) { - this.logger.info('Repurposing peer for loader (%s).', peer.hostname); - this.peers.repurpose(peer); - this.fillPeers(); - utils.nextTick(function() { - self.emit('loader', peer); - }); - return; - } - peer = this.createPeer(addr); this.logger.info('Added loader peer (%s).', peer.hostname); @@ -653,6 +636,33 @@ Pool.prototype.addLoader = function addLoader() { }); }; +/** + * Add a loader peer. Necessary for + * a sync to even begin. + * @private + */ + +Pool.prototype.setLoader = function setLoader(peer) { + var self = this; + + if (!this.loaded) + return; + + if (this.syncing) { + this.startTimeout(); + this.startInterval(); + } + + this.logger.info('Repurposing peer for loader (%s).', peer.hostname); + this.peers.repurpose(peer); + this.fillPeers(); + peer.sync(); + + utils.nextTick(function() { + self.emit('loader', peer); + }); +}; + /** * Start the blockchain sync. */ @@ -1029,6 +1039,18 @@ Pool.prototype.createPeer = function createPeer(addr, socket) { var self = this; var peer = new bcoin.peer(this, addr, socket); + peer.once('ack', function() { + if (!peer.outbound) + return; + + // Attempt to promote from pending->regular + self.peers.promote(peer); + + // If we don't have an ack'd loader yet, use this peer. + if (!self.peers.load || !self.peers.load.ack) + self.setLoader(peer); + }); + peer.once('close', function() { if (!self.loaded) { self.removePeer(peer); @@ -1400,10 +1422,6 @@ Pool.prototype.addPeer = function addPeer() { this.peers.addPending(peer); - peer.once('ack', function() { - self.peers.promote(peer); - }); - utils.nextTick(function() { self.emit('peer', peer); }); @@ -1944,6 +1962,13 @@ function PeerList(pool) { this.map = {}; } +PeerList.prototype.addLoader = function addLoader(peer) { + this.load = peer; + this.all.push(peer); + assert(!this.map[peer.hostname]); + this.map[peer.hostname] = peer; +}; + PeerList.prototype.addPending = function addPending(peer) { this.pending.push(peer); this.all.push(peer); @@ -1951,6 +1976,13 @@ PeerList.prototype.addPending = function addPending(peer) { this.map[peer.hostname] = peer; }; +PeerList.prototype.addLeech = function addLeech(peer) { + this.leeches.push(peer); + this.all.push(peer); + assert(!this.map[peer.hostname]); + this.map[peer.hostname] = peer; +}; + PeerList.prototype.promote = function promote(peer) { if (utils.binaryRemove(this.pending, peer, compare)) utils.binaryInsert(this.regular, peer, compare); @@ -1971,11 +2003,23 @@ PeerList.prototype.remove = function remove(peer) { } }; +PeerList.prototype.demoteLoader = function demoteLoader() { + var peer = this.load; + assert(peer); + this.load = null; + if (peer.ack) + utils.binaryInsert(this.regular, peer, compare); + else + utils.binaryInsert(this.pending, peer, compare); +}; + PeerList.prototype.repurpose = function repurpose(peer) { var r1, r2; assert(peer.outbound); - assert(!this.load); + + if (this.load) + this.demoteLoader(); r1 = utils.binaryRemove(this.pending, peer, compare); r2 = utils.binaryRemove(this.regular, peer, compare); @@ -1993,20 +2037,6 @@ PeerList.prototype.size = function size() { return this.regular.length + this.pending.length; }; -PeerList.prototype.addLeech = function addLeech(peer) { - this.leeches.push(peer); - this.all.push(peer); - assert(!this.map[peer.hostname]); - this.map[peer.hostname] = peer; -}; - -PeerList.prototype.addLoader = function addLoader(peer) { - this.load = peer; - this.all.push(peer); - assert(!this.map[peer.hostname]); - this.map[peer.hostname] = peer; -}; - PeerList.prototype.get = function get(addr) { return this.map[addr.hostname]; };