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.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();
}
};
/**

View File

@ -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();