miner: better stopping and starting.
This commit is contained in:
parent
12a5bcc4e2
commit
5b3f6bb042
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user