miner: better stopping and starting.

This commit is contained in:
Christopher Jeffrey 2016-10-06 01:18:08 -07:00
parent 12a5bcc4e2
commit 5b3f6bb042
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 82 additions and 53 deletions

View File

@ -43,7 +43,9 @@ function Miner(options) {
this.logger = options.logger || this.chain.logger; this.logger = options.logger || this.chain.logger;
this.running = false; this.running = false;
this.stopping = false;
this.attempt = null; this.attempt = null;
this.since = 0;
this.version = -1; this.version = -1;
this.address = Address(options.address); this.address = Address(options.address);
@ -62,10 +64,6 @@ utils.inherits(Miner, AsyncObject);
Miner.prototype._init = function _init() { Miner.prototype._init = function _init() {
var self = this; var self = this;
this.chain.on('tip', function(tip) {
self.restart();
});
this.on('block', function(block) { this.on('block', function(block) {
// Emit the block hex as a failsafe (in case we can't send it) // 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); self.logger.info('Found block: %d (%s).', block.height, block.rhash);
@ -105,9 +103,17 @@ Miner.prototype._open = co(function* open() {
* @returns {Promise} * @returns {Promise}
*/ */
Miner.prototype._close = function close() { Miner.prototype._close = co(function* close() {
return Promise.resolve(null); if (!this.running)
}; return;
if (this.stopping) {
yield this._onStop();
return;
}
yield this.stop();
});
/** /**
* Start mining. * Start mining.
@ -115,80 +121,104 @@ Miner.prototype._close = function close() {
*/ */
Miner.prototype.start = co(function* start() { Miner.prototype.start = co(function* start() {
var attempt, block; var block;
assert(!this.running, 'Miner is already running.'); assert(!this.running, 'Miner is already running.');
this.running = true; this.running = true;
this.stopping = false;
while (!block) { for (;;) {
if (!this.running) this.attempt = null;
return;
try { try {
attempt = yield this.createBlock(); this.attempt = yield this.createBlock();
} catch (e) { } catch (e) {
this.running = false; if (this.stopping)
break;
this.emit('error', e); this.emit('error', e);
return; continue;
} }
if (!this.running) if (this.stopping)
return; break;
this.attempt = attempt;
try { try {
block = yield attempt.mineAsync(); block = yield this.attempt.mineAsync();
} catch (e) { } catch (e) {
if (this.stopping)
break;
this.emit('error', e); this.emit('error', e);
this.restart(); continue;
return;
} }
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 { this.emit('done');
yield this.chain.add(block);
} catch (e) {
this.emit('error', e);
this.restart();
return;
}
this.emit('block', block);
}); });
/** /**
* Stop mining. * Stop mining.
*/ */
Miner.prototype.stop = function stop() { Miner.prototype.stop = co(function* stop() {
assert(this.running, 'Miner is not running.'); 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.running = false;
this.stopping = false;
this.attempt = null;
if (this.attempt) { this.emit('stop');
this.attempt.destroy(); });
this.attempt = null;
}
};
/** /**
* Restart miner. * Wait for `done` event.
*/ */
Miner.prototype.restart = function restart() { Miner.prototype._onDone = co(function* _onDone() {
var self = this; var self = this;
return new Promise(function(resolve, reject) {
self.once('done', resolve);
});
});
if (!this.running) /**
return; * Wait for `stop` event.
*/
this.stop(); Miner.prototype._onStop = co(function* _onStop() {
var self = this;
setTimeout(function() { return new Promise(function(resolve, reject) {
self.start(); self.once('stop', resolve);
}, 500); });
}; });
/** /**
* Create a block "attempt". * Create a block "attempt".
@ -268,7 +298,10 @@ Miner.prototype.notifyEntry = function notifyEntry() {
if (!this.attempt) if (!this.attempt)
return; return;
this.attempt.since++; if (++this.since > 20) {
this.since = 0;
this.attempt.destroy();
}
}; };
/** /**

View File

@ -61,7 +61,6 @@ function MinerBlock(options) {
this.address = options.address; this.address = options.address;
this.network = Network.get(options.network); this.network = Network.get(options.network);
this.destroyed = false; this.destroyed = false;
this.since = 0;
this.sigops = 0; this.sigops = 0;
this.weight = 0; this.weight = 0;
@ -366,13 +365,10 @@ MinerBlock.prototype.findNonceAsync = co(function* findNonceAsync() {
data = block.abbr(); data = block.abbr();
nonce = yield workers.pool.mine(data, target, min, max); nonce = yield workers.pool.mine(data, target, min, max);
if (this.destroyed)
throw new Error('Miner was interrupted.');
if (nonce !== -1) if (nonce !== -1)
break; break;
if (this.since > 20) if (this.destroyed)
return nonce; return nonce;
block.nonce = max; block.nonce = max;
@ -434,7 +430,7 @@ MinerBlock.prototype.mineAsync = co(function* mineAsync() {
if (nonce !== -1) if (nonce !== -1)
break; break;
if (this.since > 20) if (this.destroyed)
return; return;
this.iterate(); this.iterate();