From 6016d96202aefbedb198e1b02cf68b9b642b70fa Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 20 Jan 2017 22:24:45 -0800 Subject: [PATCH] pool: move sync method out of peer. --- lib/net/common.js | 8 +++++ lib/net/peer.js | 91 ++++++++++++++++------------------------------ lib/net/pool.js | 92 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 124 insertions(+), 67 deletions(-) diff --git a/lib/net/common.js b/lib/net/common.js index ed850016..5cbfe0a8 100644 --- a/lib/net/common.js +++ b/lib/net/common.js @@ -57,6 +57,14 @@ exports.SENDHEADERS_VERSION = 7012; exports.COMPACT_VERSION = 70014; +/** + * Minimum version for bip152+segwit. + * @const {Number} + * @default + */ + +exports.COMPACT_WITNESS_VERSION = 70015; + /** * Service bits. * @enum {Number} diff --git a/lib/net/peer.js b/lib/net/peer.js index aac7ac8e..bfa16f47 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -118,7 +118,7 @@ function Peer(pool) { this.merkleBlock = null; this.merkleTime = -1; this.merkleMatches = 0; - this.syncSent = false; + this.syncing = false; this.sentAddr = false; this.sentGetAddr = false; this.challenge = null; @@ -1181,7 +1181,7 @@ Peer.prototype.maybeTimeout = function maybeTimeout() { } } - if (!this.pool.syncing || this.chain.synced) + if (!this.syncing || this.chain.synced) return; if (!this.isLoader()) @@ -1337,14 +1337,12 @@ Peer.prototype.blockType = function blockType() { if (this.options.spv) return invTypes.FILTERED_BLOCK; - if (this.outbound && this.chain.synced) { - if (this.options.compact && this.compactMode !== -1) { - if (!this.options.witness || this.compactWitness) - return invTypes.CMPCT_BLOCK; - } + if (this.options.compact && this.outbound) { + if (this.hasCompact()) + return invTypes.CMPCT_BLOCK; } - if (this.hasWitness()) + if (this.options.witness && this.hasWitness()) return invTypes.WITNESS_BLOCK; return invTypes.BLOCK; @@ -1356,7 +1354,7 @@ Peer.prototype.blockType = function blockType() { */ Peer.prototype.txType = function txType() { - if (this.hasWitness()) + if (this.options.witness && this.hasWitness()) return invTypes.WITNESS_TX; return invTypes.TX; @@ -1729,6 +1727,11 @@ Peer.prototype.handleVersion = co(function* handleVersion(packet) { if (!(this.services & services.WITNESS)) throw new Error('Peer does not support segregated witness.'); } + + if (this.options.compact) { + if (!this.hasCompact()) + throw new Error('Peer does not support compact blocks.'); + } } this.send(new packets.VerackPacket()); @@ -2240,58 +2243,6 @@ Peer.prototype.reject = function reject(msg, code, reason, score) { this.increaseBan(score); }; -/** - * Start syncing from peer. - * @returns {Promise} - */ - -Peer.prototype.sync = co(function* sync() { - var locator, tip, watermark; - - if (!this.pool.syncing) - return false; - - if (!this.handshake) - return false; - - if (this.syncSent) - return false; - - if (!(this.services & services.NETWORK)) - return false; - - if (this.options.witness && !this.hasWitness()) - return false; - - if (!this.isLoader()) { - if (!this.chain.synced) - return false; - } - - // Ask for the mempool if we're synced. - if (this.network.requestMempool) { - if (this.isLoader() && this.chain.synced) - this.sendMempool(); - } - - this.syncSent = true; - - this.lastBlock = util.ms(); - - if (this.pool.headersFirst) { - tip = this.chain.tip; - watermark = this.pool.headerTip; - this.sendGetHeaders([tip.hash], watermark.hash); - return true; - } - - locator = yield this.chain.getLocator(); - - this.sendGetBlocks(locator); - - return true; -}); - /** * Test whether required services are available. * @param {Number} services @@ -2311,6 +2262,24 @@ Peer.prototype.hasWitness = function hasWitness() { return (this.services & services.WITNESS) !== 0; }; +/** + * Test whether the peer supports compact blocks. + * @returns {Boolean} + */ + +Peer.prototype.hasCompact = function hasCompact() { + if (this.version < common.COMPACT_VERSION) + return false; + + if (!this.options.witness) + return true; + + if (!(this.services & services.WITNESS)) + return false; + + return this.version >= common.COMPACT_WITNESS_VERSION; +}; + /** * Inspect the peer. * @returns {String} diff --git a/lib/net/pool.js b/lib/net/pool.js index c2b9888f..92995cec 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -505,7 +505,7 @@ Pool.prototype.setLoader = function setLoader(peer) { assert(peer.outbound); this.peers.load = peer; - peer.sync(); + this.sendSync(peer); this.emit('loader', peer); }; @@ -538,7 +538,7 @@ Pool.prototype.sync = function sync() { for (peer = this.peers.head(); peer; peer = peer.next) { if (!peer.outbound) continue; - peer.sync(); + this.sendSync(peer); } }; @@ -556,11 +556,90 @@ Pool.prototype.forceSync = function forceSync() { for (peer = this.peers.head(); peer; peer = peer.next) { if (!peer.outbound) continue; - peer.syncSent = false; - peer.sync(); + peer.syncing = false; + this.sendSync(peer); } }; +/** + * Stop the sync. + * @private + */ + +Pool.prototype.stopSync = function stopSync() { + var peer; + + if (!this.syncing) + return; + + this.syncing = false; + + for (peer = this.peers.head(); peer; peer = peer.next) { + if (!peer.outbound) + continue; + peer.syncing = false; + } +}; + +/** + * Start syncing from peer. + * @param {Peer} peer + * @returns {Promise} + */ + +Pool.prototype.sendSync = co(function* sendSync(peer) { + var locator, tip, watermark; + + if (!this.syncing) + return false; + + if (!peer.handshake) + return false; + + if (peer.syncing) + return false; + + if (!(peer.services & services.NETWORK)) + return false; + + if (this.options.witness && !peer.hasWitness()) + return false; + + if (!peer.isLoader()) { + if (!this.chain.synced) + return false; + } + + // Ask for the mempool if we're synced. + if (this.network.requestMempool) { + if (peer.isLoader() && this.chain.synced) + peer.sendMempool(); + } + + peer.syncing = true; + + peer.lastBlock = util.ms(); + + if (this.pool.headersFirst) { + tip = this.chain.tip; + watermark = this.headerTip; + peer.sendGetHeaders([tip.hash], watermark.hash); + return true; + } + + try { + locator = yield this.chain.getLocator(); + } catch (e) { + this.emit('error', e); + return; + } + + peer.sendGetBlocks(locator); + + return true; +}); + + /** * Send `mempool` to all peers. */ @@ -880,7 +959,7 @@ Pool.prototype.handleOpen = function handleOpen(peer) { // We want compact blocks! if (this.options.compact) { - if (peer.version >= common.COMPACT_VERSION) + if (peer.hasCompact()) peer.sendCompact(this.options.blockMode); } @@ -900,7 +979,8 @@ Pool.prototype.handleOpen = function handleOpen(peer) { peer.sendFeeRate(this.options.feeRate); // Start syncing the chain. - peer.sync(); + if (peer.outbound) + this.sendSync(peer); if (peer.outbound) { this.hosts.markAck(peer.hostname, peer.services);