From 5b3f6bb042da52413c53749d28dcf7311b0c0f49 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 6 Oct 2016 01:18:08 -0700 Subject: [PATCH] miner: better stopping and starting. --- lib/miner/miner.js | 127 +++++++++++++++++++++++++--------------- lib/miner/minerblock.js | 8 +-- 2 files changed, 82 insertions(+), 53 deletions(-) diff --git a/lib/miner/miner.js b/lib/miner/miner.js index e6aaf4f1..c66cd884 100644 --- a/lib/miner/miner.js +++ b/lib/miner/miner.js @@ -43,7 +43,9 @@ function Miner(options) { this.logger = options.logger || this.chain.logger; this.running = false; + this.stopping = false; this.attempt = null; + this.since = 0; this.version = -1; this.address = Address(options.address); @@ -62,10 +64,6 @@ utils.inherits(Miner, AsyncObject); Miner.prototype._init = function _init() { var self = this; - this.chain.on('tip', function(tip) { - self.restart(); - }); - this.on('block', function(block) { // Emit the block hex as a failsafe (in case we can't send it) self.logger.info('Found block: %d (%s).', block.height, block.rhash); @@ -105,9 +103,17 @@ Miner.prototype._open = co(function* open() { * @returns {Promise} */ -Miner.prototype._close = function close() { - return Promise.resolve(null); -}; +Miner.prototype._close = co(function* close() { + if (!this.running) + return; + + if (this.stopping) { + yield this._onStop(); + return; + } + + yield this.stop(); +}); /** * Start mining. @@ -115,80 +121,104 @@ Miner.prototype._close = function close() { */ Miner.prototype.start = co(function* start() { - var attempt, block; + var block; assert(!this.running, 'Miner is already running.'); this.running = true; + this.stopping = false; - while (!block) { - if (!this.running) - return; + for (;;) { + this.attempt = null; try { - attempt = yield this.createBlock(); + this.attempt = yield this.createBlock(); } catch (e) { - this.running = false; + if (this.stopping) + break; this.emit('error', e); - return; + continue; } - if (!this.running) - return; - - this.attempt = attempt; + if (this.stopping) + break; try { - block = yield attempt.mineAsync(); + block = yield this.attempt.mineAsync(); } catch (e) { + if (this.stopping) + break; this.emit('error', e); - this.restart(); - return; + continue; } + + if (this.stopping) + break; + + if (!block) + continue; + + try { + yield this.chain.add(block); + } catch (e) { + if (this.stopping) + break; + this.emit('error', e); + continue; + } + + if (this.stopping) + break; + + this.emit('block', block); } - try { - yield this.chain.add(block); - } catch (e) { - this.emit('error', e); - this.restart(); - return; - } - - this.emit('block', block); + this.emit('done'); }); /** * Stop mining. */ -Miner.prototype.stop = function stop() { +Miner.prototype.stop = co(function* stop() { assert(this.running, 'Miner is not running.'); + assert(!this.stopping, 'Miner is already stopping.'); + + this.stopping = true; + + if (this.attempt) + this.attempt.destroy(); + + yield this._onDone(); this.running = false; + this.stopping = false; + this.attempt = null; - if (this.attempt) { - this.attempt.destroy(); - this.attempt = null; - } -}; + this.emit('stop'); +}); /** - * Restart miner. + * Wait for `done` event. */ -Miner.prototype.restart = function restart() { +Miner.prototype._onDone = co(function* _onDone() { var self = this; + return new Promise(function(resolve, reject) { + self.once('done', resolve); + }); +}); - if (!this.running) - return; +/** + * Wait for `stop` event. + */ - this.stop(); - - setTimeout(function() { - self.start(); - }, 500); -}; +Miner.prototype._onStop = co(function* _onStop() { + var self = this; + return new Promise(function(resolve, reject) { + self.once('stop', resolve); + }); +}); /** * Create a block "attempt". @@ -268,7 +298,10 @@ Miner.prototype.notifyEntry = function notifyEntry() { if (!this.attempt) return; - this.attempt.since++; + if (++this.since > 20) { + this.since = 0; + this.attempt.destroy(); + } }; /** diff --git a/lib/miner/minerblock.js b/lib/miner/minerblock.js index 3464344e..6c399828 100644 --- a/lib/miner/minerblock.js +++ b/lib/miner/minerblock.js @@ -61,7 +61,6 @@ function MinerBlock(options) { this.address = options.address; this.network = Network.get(options.network); this.destroyed = false; - this.since = 0; this.sigops = 0; this.weight = 0; @@ -366,13 +365,10 @@ MinerBlock.prototype.findNonceAsync = co(function* findNonceAsync() { data = block.abbr(); nonce = yield workers.pool.mine(data, target, min, max); - if (this.destroyed) - throw new Error('Miner was interrupted.'); - if (nonce !== -1) break; - if (this.since > 20) + if (this.destroyed) return nonce; block.nonce = max; @@ -434,7 +430,7 @@ MinerBlock.prototype.mineAsync = co(function* mineAsync() { if (nonce !== -1) break; - if (this.since > 20) + if (this.destroyed) return; this.iterate();