refactor: even more restructuring.
This commit is contained in:
parent
a3c24938b9
commit
10bb8d1e18
@ -132,7 +132,7 @@ function Environment() {
|
|||||||
this.network = require('./protocol/network');
|
this.network = require('./protocol/network');
|
||||||
this.errors = require('./utils/errors');
|
this.errors = require('./utils/errors');
|
||||||
this.ldb = require('./db/ldb');
|
this.ldb = require('./db/ldb');
|
||||||
this.timedata = require('./timedata');
|
this.timedata = require('./net/timedata');
|
||||||
this.script = require('./primitives/script');
|
this.script = require('./primitives/script');
|
||||||
this.opcode = this.script.Opcode;
|
this.opcode = this.script.Opcode;
|
||||||
this.stack = this.script.Stack;
|
this.stack = this.script.Stack;
|
||||||
@ -172,7 +172,7 @@ function Environment() {
|
|||||||
this.path = this.walletdb.Path;
|
this.path = this.walletdb.Path;
|
||||||
this.peer = require('./net/peer');
|
this.peer = require('./net/peer');
|
||||||
this.pool = require('./net/pool');
|
this.pool = require('./net/pool');
|
||||||
this.miner = require('./miner');
|
this.miner = require('./miner/miner');
|
||||||
this.minerblock = this.miner.MinerBlock;
|
this.minerblock = this.miner.MinerBlock;
|
||||||
this.http = require('./http');
|
this.http = require('./http');
|
||||||
this.workers = require('./workers');
|
this.workers = require('./workers');
|
||||||
|
|||||||
@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var bcoin = require('./env');
|
var bcoin = require('../env');
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var constants = bcoin.protocol.constants;
|
var constants = bcoin.protocol.constants;
|
||||||
var BufferReader = require('./utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var BufferWriter = require('./utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var global = bcoin.utils.global;
|
var global = bcoin.utils.global;
|
||||||
var Float64Array = global.Float64Array || Array;
|
var Float64Array = global.Float64Array || Array;
|
||||||
var Int32Array = global.Int32Array || Array;
|
var Int32Array = global.Int32Array || Array;
|
||||||
|
|||||||
@ -12,13 +12,13 @@
|
|||||||
* (inherits all from txdb)
|
* (inherits all from txdb)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var bcoin = require('./env');
|
var bcoin = require('../env');
|
||||||
var AsyncObject = require('./utils/async');
|
var AsyncObject = require('../utils/async');
|
||||||
var constants = bcoin.protocol.constants;
|
var constants = bcoin.protocol.constants;
|
||||||
var utils = require('./utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var BufferWriter = require('./utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('./utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var VerifyError = bcoin.errors.VerifyError;
|
var VerifyError = bcoin.errors.VerifyError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
336
lib/bcoin/miner/miner.js
Normal file
336
lib/bcoin/miner/miner.js
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
/*!
|
||||||
|
* miner.js - inefficient miner for bcoin (because we can)
|
||||||
|
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||||
|
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bcoin = require('../env');
|
||||||
|
var utils = require('../utils/utils');
|
||||||
|
var assert = utils.assert;
|
||||||
|
var AsyncObject = require('../utils/async');
|
||||||
|
var MinerBlock = require('./minerblock');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitcoin miner (supports mining witness blocks).
|
||||||
|
* @exports Miner
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Base58Address} options.address - Payout address.
|
||||||
|
* @param {String?} [options.coinbaseFlags="mined by bcoin"]
|
||||||
|
* @property {Boolean} running
|
||||||
|
* @property {Boolean} loaded
|
||||||
|
* @emits Miner#block
|
||||||
|
* @emits Miner#status
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Miner(options) {
|
||||||
|
if (!(this instanceof Miner))
|
||||||
|
return new Miner(options);
|
||||||
|
|
||||||
|
AsyncObject.call(this);
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
options = {};
|
||||||
|
|
||||||
|
this.options = options;
|
||||||
|
this.address = bcoin.address(this.options.address);
|
||||||
|
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
||||||
|
this.version = null;
|
||||||
|
|
||||||
|
this.pool = options.pool;
|
||||||
|
this.chain = options.chain;
|
||||||
|
this.logger = options.logger || this.chain.logger;
|
||||||
|
this.mempool = options.mempool;
|
||||||
|
this.fees = this.mempool ? this.mempool.fees : options.fees;
|
||||||
|
|
||||||
|
assert(this.chain, 'Miner requires a blockchain.');
|
||||||
|
|
||||||
|
this.network = this.chain.network;
|
||||||
|
this.running = false;
|
||||||
|
this.timeout = null;
|
||||||
|
this.attempt = null;
|
||||||
|
this.workerPool = null;
|
||||||
|
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.inherits(Miner, AsyncObject);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the miner.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype._init = function _init() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (this.mempool) {
|
||||||
|
this.mempool.on('tx', function(tx) {
|
||||||
|
if (!self.running)
|
||||||
|
return;
|
||||||
|
if (self.attempt)
|
||||||
|
self.attempt.addTX(tx.clone());
|
||||||
|
});
|
||||||
|
} else if (this.pool) {
|
||||||
|
this.pool.on('tx', function(tx) {
|
||||||
|
if (!self.running)
|
||||||
|
return;
|
||||||
|
if (self.attempt)
|
||||||
|
self.attempt.addTX(tx.clone());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.chain.on('tip', function(tip) {
|
||||||
|
if (!self.running)
|
||||||
|
return;
|
||||||
|
self.stop();
|
||||||
|
setTimeout(function() {
|
||||||
|
self.start();
|
||||||
|
}, self.network.type === 'regtest' ? 100 : 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
self.logger.debug('Raw: %s', block.toRaw().toString('hex'));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('status', function(stat) {
|
||||||
|
self.logger.info(
|
||||||
|
'Miner: hashrate=%dkhs hashes=%d target=%d height=%d best=%s',
|
||||||
|
stat.hashrate / 1000 | 0,
|
||||||
|
stat.hashes,
|
||||||
|
stat.target,
|
||||||
|
stat.height,
|
||||||
|
stat.best);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (bcoin.useWorkers) {
|
||||||
|
this.workerPool = new bcoin.workers({
|
||||||
|
size: this.options.parallel ? 2 : 1,
|
||||||
|
timeout: -1
|
||||||
|
});
|
||||||
|
|
||||||
|
this.workerPool.on('error', function(err) {
|
||||||
|
self.emit('error', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.workerPool.on('status', function(stat) {
|
||||||
|
self.emit('status', stat);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the miner, wait for the chain and mempool to load.
|
||||||
|
* @alias Miner#open
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype._open = function open(callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
function open(callback) {
|
||||||
|
if (self.mempool)
|
||||||
|
self.mempool.open(callback);
|
||||||
|
else
|
||||||
|
self.chain.open(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
open(function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
self.logger.info('Miner loaded (flags=%s).', self.coinbaseFlags);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the miner.
|
||||||
|
* @alias Miner#close
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype._close = function close(callback) {
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start mining.
|
||||||
|
* @param {Number?} version - Custom block version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype.start = function start() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.stop();
|
||||||
|
|
||||||
|
this.running = true;
|
||||||
|
|
||||||
|
// Create a new block and start hashing
|
||||||
|
this.createBlock(function(err, attempt) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
|
||||||
|
if (!self.running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.attempt = attempt;
|
||||||
|
|
||||||
|
attempt.on('status', function(status) {
|
||||||
|
self.emit('status', status);
|
||||||
|
});
|
||||||
|
|
||||||
|
attempt.mineAsync(function(err, block) {
|
||||||
|
if (err) {
|
||||||
|
if (!self.running)
|
||||||
|
return;
|
||||||
|
self.emit('error', err);
|
||||||
|
return self.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add our block to the chain
|
||||||
|
self.chain.add(block, function(err) {
|
||||||
|
if (err) {
|
||||||
|
if (err.type === 'VerifyError')
|
||||||
|
self.logger.warning('%s could not be added to chain.', block.rhash);
|
||||||
|
self.emit('error', err);
|
||||||
|
return self.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit our newly found block
|
||||||
|
self.emit('block', block);
|
||||||
|
|
||||||
|
// `tip` will now be emitted by chain
|
||||||
|
// and the whole process starts over.
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop mining.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype.stop = function stop() {
|
||||||
|
if (!this.running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.running = false;
|
||||||
|
|
||||||
|
if (this.attempt) {
|
||||||
|
this.attempt.destroy();
|
||||||
|
this.attempt = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.workerPool)
|
||||||
|
this.workerPool.destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a block "attempt".
|
||||||
|
* @param {Number?} version - Custom block version.
|
||||||
|
* @param {Function} callback - Returns [Error, {@link MinerBlock}].
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype.createBlock = function createBlock(tip, callback) {
|
||||||
|
var self = this;
|
||||||
|
var i, ts, attempt, txs, tx;
|
||||||
|
|
||||||
|
if (typeof tip === 'function') {
|
||||||
|
callback = tip;
|
||||||
|
tip = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tip)
|
||||||
|
tip = this.chain.tip;
|
||||||
|
|
||||||
|
ts = Math.max(bcoin.now(), tip.ts + 1);
|
||||||
|
|
||||||
|
function computeVersion(callback) {
|
||||||
|
if (self.version != null)
|
||||||
|
return callback(null, self.version);
|
||||||
|
self.chain.computeBlockVersion(tip, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.loaded) {
|
||||||
|
this.open(function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
self.createBlock(tip, callback);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(tip);
|
||||||
|
|
||||||
|
// Find target
|
||||||
|
this.chain.getTargetAsync(ts, tip, function(err, target) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
// Calculate version with versionbits
|
||||||
|
computeVersion(function(err, version) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
attempt = new MinerBlock({
|
||||||
|
workerPool: self.workerPool,
|
||||||
|
tip: tip,
|
||||||
|
version: version,
|
||||||
|
target: target,
|
||||||
|
address: self.address,
|
||||||
|
coinbaseFlags: self.coinbaseFlags,
|
||||||
|
witness: self.chain.segwitActive,
|
||||||
|
parallel: self.options.parallel,
|
||||||
|
network: self.network
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!self.mempool)
|
||||||
|
return callback(null, attempt);
|
||||||
|
|
||||||
|
txs = self.mempool.getHistory();
|
||||||
|
|
||||||
|
for (i = 0; i < txs.length; i++) {
|
||||||
|
tx = txs[i];
|
||||||
|
attempt.addTX(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, attempt);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mine a single block.
|
||||||
|
* @param {Number?} version - Custom block version.
|
||||||
|
* @param {Function} callback - Returns [Error, [{@link Block}]].
|
||||||
|
*/
|
||||||
|
|
||||||
|
Miner.prototype.mineBlock = function mineBlock(tip, callback) {
|
||||||
|
if (typeof tip === 'function') {
|
||||||
|
callback = tip;
|
||||||
|
tip = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new block and start hashing
|
||||||
|
this.createBlock(tip, function(err, attempt) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
attempt.mineAsync(callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Miner.MinerBlock = MinerBlock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = Miner;
|
||||||
@ -7,329 +7,14 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var bcoin = require('./env');
|
var bcoin = require('../env');
|
||||||
var utils = require('./utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.protocol.constants;
|
var constants = bcoin.protocol.constants;
|
||||||
var bn = require('bn.js');
|
var bn = require('bn.js');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var AsyncObject = require('./utils/async');
|
var BufferReader = require('../utils/reader');
|
||||||
var BufferReader = require('./utils/reader');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferWriter = require('./utils/writer');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A bitcoin miner (supports mining witness blocks).
|
|
||||||
* @exports Miner
|
|
||||||
* @constructor
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {Base58Address} options.address - Payout address.
|
|
||||||
* @param {String?} [options.coinbaseFlags="mined by bcoin"]
|
|
||||||
* @property {Boolean} running
|
|
||||||
* @property {Boolean} loaded
|
|
||||||
* @emits Miner#block
|
|
||||||
* @emits Miner#status
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Miner(options) {
|
|
||||||
if (!(this instanceof Miner))
|
|
||||||
return new Miner(options);
|
|
||||||
|
|
||||||
AsyncObject.call(this);
|
|
||||||
|
|
||||||
if (!options)
|
|
||||||
options = {};
|
|
||||||
|
|
||||||
this.options = options;
|
|
||||||
this.address = bcoin.address(this.options.address);
|
|
||||||
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
|
||||||
this.version = null;
|
|
||||||
|
|
||||||
this.pool = options.pool;
|
|
||||||
this.chain = options.chain;
|
|
||||||
this.logger = options.logger || this.chain.logger;
|
|
||||||
this.mempool = options.mempool;
|
|
||||||
this.fees = this.mempool ? this.mempool.fees : options.fees;
|
|
||||||
|
|
||||||
assert(this.chain, 'Miner requires a blockchain.');
|
|
||||||
|
|
||||||
this.network = this.chain.network;
|
|
||||||
this.running = false;
|
|
||||||
this.timeout = null;
|
|
||||||
this.attempt = null;
|
|
||||||
this.workerPool = null;
|
|
||||||
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.inherits(Miner, AsyncObject);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the miner.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype._init = function _init() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (this.mempool) {
|
|
||||||
this.mempool.on('tx', function(tx) {
|
|
||||||
if (!self.running)
|
|
||||||
return;
|
|
||||||
if (self.attempt)
|
|
||||||
self.attempt.addTX(tx.clone());
|
|
||||||
});
|
|
||||||
} else if (this.pool) {
|
|
||||||
this.pool.on('tx', function(tx) {
|
|
||||||
if (!self.running)
|
|
||||||
return;
|
|
||||||
if (self.attempt)
|
|
||||||
self.attempt.addTX(tx.clone());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chain.on('tip', function(tip) {
|
|
||||||
if (!self.running)
|
|
||||||
return;
|
|
||||||
self.stop();
|
|
||||||
setTimeout(function() {
|
|
||||||
self.start();
|
|
||||||
}, self.network.type === 'regtest' ? 100 : 5000);
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
self.logger.debug('Raw: %s', block.toRaw().toString('hex'));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on('status', function(stat) {
|
|
||||||
self.logger.info(
|
|
||||||
'Miner: hashrate=%dkhs hashes=%d target=%d height=%d best=%s',
|
|
||||||
stat.hashrate / 1000 | 0,
|
|
||||||
stat.hashes,
|
|
||||||
stat.target,
|
|
||||||
stat.height,
|
|
||||||
stat.best);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (bcoin.useWorkers) {
|
|
||||||
this.workerPool = new bcoin.workers({
|
|
||||||
size: this.options.parallel ? 2 : 1,
|
|
||||||
timeout: -1
|
|
||||||
});
|
|
||||||
|
|
||||||
this.workerPool.on('error', function(err) {
|
|
||||||
self.emit('error', err);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.workerPool.on('status', function(stat) {
|
|
||||||
self.emit('status', stat);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the miner, wait for the chain and mempool to load.
|
|
||||||
* @alias Miner#open
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype._open = function open(callback) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
function open(callback) {
|
|
||||||
if (self.mempool)
|
|
||||||
self.mempool.open(callback);
|
|
||||||
else
|
|
||||||
self.chain.open(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
open(function(err) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
self.logger.info('Miner loaded (flags=%s).', self.coinbaseFlags);
|
|
||||||
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the miner.
|
|
||||||
* @alias Miner#close
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype._close = function close(callback) {
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start mining.
|
|
||||||
* @param {Number?} version - Custom block version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype.start = function start() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.stop();
|
|
||||||
|
|
||||||
this.running = true;
|
|
||||||
|
|
||||||
// Create a new block and start hashing
|
|
||||||
this.createBlock(function(err, attempt) {
|
|
||||||
if (err)
|
|
||||||
return self.emit('error', err);
|
|
||||||
|
|
||||||
if (!self.running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.attempt = attempt;
|
|
||||||
|
|
||||||
attempt.on('status', function(status) {
|
|
||||||
self.emit('status', status);
|
|
||||||
});
|
|
||||||
|
|
||||||
attempt.mineAsync(function(err, block) {
|
|
||||||
if (err) {
|
|
||||||
if (!self.running)
|
|
||||||
return;
|
|
||||||
self.emit('error', err);
|
|
||||||
return self.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add our block to the chain
|
|
||||||
self.chain.add(block, function(err) {
|
|
||||||
if (err) {
|
|
||||||
if (err.type === 'VerifyError')
|
|
||||||
self.logger.warning('%s could not be added to chain.', block.rhash);
|
|
||||||
self.emit('error', err);
|
|
||||||
return self.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit our newly found block
|
|
||||||
self.emit('block', block);
|
|
||||||
|
|
||||||
// `tip` will now be emitted by chain
|
|
||||||
// and the whole process starts over.
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop mining.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype.stop = function stop() {
|
|
||||||
if (!this.running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.running = false;
|
|
||||||
|
|
||||||
if (this.attempt) {
|
|
||||||
this.attempt.destroy();
|
|
||||||
this.attempt = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.workerPool)
|
|
||||||
this.workerPool.destroy();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a block "attempt".
|
|
||||||
* @param {Number?} version - Custom block version.
|
|
||||||
* @param {Function} callback - Returns [Error, {@link MinerBlock}].
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype.createBlock = function createBlock(tip, callback) {
|
|
||||||
var self = this;
|
|
||||||
var i, ts, attempt, txs, tx;
|
|
||||||
|
|
||||||
if (typeof tip === 'function') {
|
|
||||||
callback = tip;
|
|
||||||
tip = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tip)
|
|
||||||
tip = this.chain.tip;
|
|
||||||
|
|
||||||
ts = Math.max(bcoin.now(), tip.ts + 1);
|
|
||||||
|
|
||||||
function computeVersion(callback) {
|
|
||||||
if (self.version != null)
|
|
||||||
return callback(null, self.version);
|
|
||||||
self.chain.computeBlockVersion(tip, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.loaded) {
|
|
||||||
this.open(function(err) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
self.createBlock(tip, callback);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(tip);
|
|
||||||
|
|
||||||
// Find target
|
|
||||||
this.chain.getTargetAsync(ts, tip, function(err, target) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
// Calculate version with versionbits
|
|
||||||
computeVersion(function(err, version) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
attempt = new MinerBlock({
|
|
||||||
workerPool: self.workerPool,
|
|
||||||
tip: tip,
|
|
||||||
version: version,
|
|
||||||
target: target,
|
|
||||||
address: self.address,
|
|
||||||
coinbaseFlags: self.coinbaseFlags,
|
|
||||||
witness: self.chain.segwitActive,
|
|
||||||
parallel: self.options.parallel,
|
|
||||||
network: self.network
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!self.mempool)
|
|
||||||
return callback(null, attempt);
|
|
||||||
|
|
||||||
txs = self.mempool.getHistory();
|
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++) {
|
|
||||||
tx = txs[i];
|
|
||||||
attempt.addTX(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null, attempt);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mine a single block.
|
|
||||||
* @param {Number?} version - Custom block version.
|
|
||||||
* @param {Function} callback - Returns [Error, [{@link Block}]].
|
|
||||||
*/
|
|
||||||
|
|
||||||
Miner.prototype.mineBlock = function mineBlock(tip, callback) {
|
|
||||||
if (typeof tip === 'function') {
|
|
||||||
callback = tip;
|
|
||||||
tip = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new block and start hashing
|
|
||||||
this.createBlock(tip, function(err, attempt) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
attempt.mineAsync(callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MinerBlock
|
* MinerBlock
|
||||||
@ -354,6 +39,8 @@ function MinerBlock(options) {
|
|||||||
if (!(this instanceof MinerBlock))
|
if (!(this instanceof MinerBlock))
|
||||||
return new MinerBlock(options);
|
return new MinerBlock(options);
|
||||||
|
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.workerPool = options.workerPool;
|
this.workerPool = options.workerPool;
|
||||||
this.tip = options.tip;
|
this.tip = options.tip;
|
||||||
@ -802,10 +489,8 @@ function rcmp(a, b) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Miner.MinerBlock = MinerBlock;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = Miner;
|
module.exports = MinerBlock;
|
||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var utils = require('./utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
80
lib/bcoin/workers/jobs.js
Normal file
80
lib/bcoin/workers/jobs.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*!
|
||||||
|
* jobs.js - worker jobs for bcoin
|
||||||
|
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bcoin = require('./env');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jobs to execute within the worker.
|
||||||
|
* @memberof Workers
|
||||||
|
* @const {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var jobs = exports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute tx.verify() on worker.
|
||||||
|
* @see TX#verify
|
||||||
|
* @param {TX} tx
|
||||||
|
* @param {VerifyFlags} flags
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
jobs.verify = function verify(tx, flags) {
|
||||||
|
return tx.verify(flags);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute Wallet.sign() on worker.
|
||||||
|
* @see Wallet.sign
|
||||||
|
* @param {KeyRing[]} rings
|
||||||
|
* @param {HDPrivateKey} master
|
||||||
|
* @param {MTX} tx
|
||||||
|
*/
|
||||||
|
|
||||||
|
jobs.sign = function sign(tx, ring, type) {
|
||||||
|
var total = tx.sign(ring, type);
|
||||||
|
var sigs = [];
|
||||||
|
var i, input;
|
||||||
|
|
||||||
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
|
input = tx.inputs[i];
|
||||||
|
sigs.push([input.script, input.witness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [sigs, total];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mine a block on worker.
|
||||||
|
* @param {Object} attempt - Naked {@link MinerBlock}.
|
||||||
|
* @returns {Block}
|
||||||
|
*/
|
||||||
|
|
||||||
|
jobs.mine = function mine(attempt) {
|
||||||
|
attempt.on('status', function(stat) {
|
||||||
|
bcoin.master.sendEvent('status', stat);
|
||||||
|
});
|
||||||
|
return attempt.mineSync();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute scrypt() on worker.
|
||||||
|
* @see scrypt
|
||||||
|
* @param {Buffer} passwd
|
||||||
|
* @param {Buffer} salt
|
||||||
|
* @param {Number} N
|
||||||
|
* @param {Number} r
|
||||||
|
* @param {Number} p
|
||||||
|
* @param {Number} len
|
||||||
|
* @returns {Buffer}
|
||||||
|
*/
|
||||||
|
|
||||||
|
jobs.scrypt = function scrypt(passwd, salt, N, r, p, len) {
|
||||||
|
var scrypt = require('./scrypt');
|
||||||
|
return scrypt(passwd, salt, N >>> 0, r >>> 0, p >>> 0, len);
|
||||||
|
};
|
||||||
@ -15,7 +15,7 @@ var global = utils.global;
|
|||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var BufferWriter = require('./utils/writer');
|
var BufferWriter = require('./utils/writer');
|
||||||
var BufferReader = require('./utils/reader');
|
var BufferReader = require('./utils/reader');
|
||||||
var jobs;
|
var jobs = require('./jobs');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A worker pool.
|
* A worker pool.
|
||||||
@ -354,7 +354,7 @@ Worker.prototype._init = function _init() {
|
|||||||
} else {
|
} else {
|
||||||
cp = require('child_process');
|
cp = require('child_process');
|
||||||
|
|
||||||
this.child = cp.spawn(process.argv[0], [__dirname + '/worker.js'], {
|
this.child = cp.spawn(process.argv[0], [__dirname + '/../../worker.js'], {
|
||||||
stdio: 'pipe',
|
stdio: 'pipe',
|
||||||
env: utils.merge({}, process.env, penv)
|
env: utils.merge({}, process.env, penv)
|
||||||
});
|
});
|
||||||
@ -746,77 +746,6 @@ Master.listen = function listen(options) {
|
|||||||
return master;
|
return master;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Jobs to execute within the worker.
|
|
||||||
* @memberof Workers
|
|
||||||
* @const {Object}
|
|
||||||
*/
|
|
||||||
|
|
||||||
jobs = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute tx.verify() on worker.
|
|
||||||
* @see TX#verify
|
|
||||||
* @param {TX} tx
|
|
||||||
* @param {VerifyFlags} flags
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
jobs.verify = function verify(tx, flags) {
|
|
||||||
return tx.verify(flags);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute Wallet.sign() on worker.
|
|
||||||
* @see Wallet.sign
|
|
||||||
* @param {KeyRing[]} rings
|
|
||||||
* @param {HDPrivateKey} master
|
|
||||||
* @param {MTX} tx
|
|
||||||
*/
|
|
||||||
|
|
||||||
jobs.sign = function sign(tx, ring, type) {
|
|
||||||
var total = tx.sign(ring, type);
|
|
||||||
var sigs = [];
|
|
||||||
var i, input;
|
|
||||||
|
|
||||||
for (i = 0; i < tx.inputs.length; i++) {
|
|
||||||
input = tx.inputs[i];
|
|
||||||
sigs.push([input.script, input.witness]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [sigs, total];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mine a block on worker.
|
|
||||||
* @param {Object} attempt - Naked {@link MinerBlock}.
|
|
||||||
* @returns {Block}
|
|
||||||
*/
|
|
||||||
|
|
||||||
jobs.mine = function mine(attempt) {
|
|
||||||
attempt.on('status', function(stat) {
|
|
||||||
bcoin.master.sendEvent('status', stat);
|
|
||||||
});
|
|
||||||
return attempt.mineSync();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute scrypt() on worker.
|
|
||||||
* @see scrypt
|
|
||||||
* @param {Buffer} passwd
|
|
||||||
* @param {Buffer} salt
|
|
||||||
* @param {Number} N
|
|
||||||
* @param {Number} r
|
|
||||||
* @param {Number} p
|
|
||||||
* @param {Number} len
|
|
||||||
* @returns {Buffer}
|
|
||||||
*/
|
|
||||||
|
|
||||||
jobs.scrypt = function scrypt(passwd, salt, N, r, p, len) {
|
|
||||||
var scrypt = require('./scrypt');
|
|
||||||
return scrypt(passwd, salt, N >>> 0, r >>> 0, p >>> 0, len);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Framer
|
* Framer
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -24,7 +24,7 @@ if (typeof importScripts !== 'undefined') {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
env = process.env;
|
env = process.env;
|
||||||
bcoin = require('./env');
|
bcoin = require('./bcoin/env');
|
||||||
bcoin.set(env.BCOIN_WORKER_NETWORK);
|
bcoin.set(env.BCOIN_WORKER_NETWORK);
|
||||||
bcoin.workers.listen();
|
bcoin.workers.listen();
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user