miner. improve workers.
This commit is contained in:
parent
71934a22f1
commit
a1cabfb8bd
@ -217,8 +217,7 @@ Block.prototype.addTX = function addTX(tx) {
|
||||
|
||||
index = this.txs.push(tx) - 1;
|
||||
|
||||
if (!this.mutable)
|
||||
tx.setBlock(this, index);
|
||||
tx.setBlock(this, index);
|
||||
|
||||
return tx;
|
||||
};
|
||||
|
||||
@ -11,6 +11,8 @@ var assert = utils.assert;
|
||||
var constants = bcoin.protocol.constants;
|
||||
var bn = require('bn.js');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var BufferReader = require('./reader');
|
||||
var BufferWriter = require('./writer');
|
||||
|
||||
/**
|
||||
* A bitcoin miner (supports mining witness blocks).
|
||||
@ -19,8 +21,6 @@ var EventEmitter = require('events').EventEmitter;
|
||||
* @param {Object} options
|
||||
* @param {Base58Address} options.address - Payout address.
|
||||
* @param {String?} [options.coinbaseFlags="mined by bcoin"]
|
||||
* @param {Function?} dsha256 - Optional sha256 substitute
|
||||
* for faster linked code.
|
||||
* @property {Boolean} running
|
||||
* @property {Boolean} loaded
|
||||
* @emits Miner#block
|
||||
@ -40,10 +40,6 @@ function Miner(options) {
|
||||
this.address = this.options.address;
|
||||
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
||||
|
||||
// Allow a dsha256 option in case someone
|
||||
// wants to pass in a faster linked in function.
|
||||
this.dsha256 = this.options.dsha256 || utils.dsha256;
|
||||
|
||||
this.pool = options.pool;
|
||||
this.chain = options.chain;
|
||||
this.mempool = options.mempool;
|
||||
@ -101,14 +97,14 @@ Miner.prototype._init = function _init() {
|
||||
if (!self.running)
|
||||
return;
|
||||
if (self.attempt)
|
||||
self.attempt.addTX(tx);
|
||||
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);
|
||||
self.attempt.addTX(tx.clone());
|
||||
});
|
||||
}
|
||||
|
||||
@ -272,7 +268,6 @@ Miner.prototype.createBlock = function createBlock(version, callback) {
|
||||
coinbaseFlags: self.coinbaseFlags,
|
||||
witness: self.chain.segwitActive,
|
||||
parallel: self.options.parallel,
|
||||
dsha256: self.dsha256,
|
||||
network: self.network
|
||||
});
|
||||
|
||||
@ -337,7 +332,6 @@ Miner.prototype.mineBlock = function mineBlock(version, callback) {
|
||||
* @param {ChainEntry} options.tip
|
||||
* @param {Number} options.height
|
||||
* @param {Number} options.target - Compact form.
|
||||
* @param {Function} options.dsha256
|
||||
* @param {Base58Address} options.address - Payout address.
|
||||
* @param {Boolean} options.witness - Allow witness
|
||||
* transactions, mine a witness block.
|
||||
@ -350,6 +344,8 @@ Miner.prototype.mineBlock = function mineBlock(version, callback) {
|
||||
*/
|
||||
|
||||
function MinerBlock(options) {
|
||||
var i;
|
||||
|
||||
if (!(this instanceof MinerBlock))
|
||||
return new MinerBlock(options);
|
||||
|
||||
@ -360,7 +356,6 @@ function MinerBlock(options) {
|
||||
this.target = utils.fromCompact(options.target).toBuffer('le', 32);
|
||||
this.extraNonce = new bn(0);
|
||||
this.iterations = 0;
|
||||
this.dsha256 = options.dsha256;
|
||||
this.coinbaseFlags = options.coinbaseFlags;
|
||||
this.witness = options.witness;
|
||||
this.address = options.address;
|
||||
@ -415,6 +410,11 @@ function MinerBlock(options) {
|
||||
|
||||
this.block.addTX(this.coinbase);
|
||||
|
||||
if (options.txs) {
|
||||
for (i = 0; i < options.txs.length; i++)
|
||||
this.block.addTX(options.txs[i]);
|
||||
}
|
||||
|
||||
if (this.witness) {
|
||||
// Set up the witness nonce and
|
||||
// commitment output for segwit.
|
||||
@ -526,7 +526,7 @@ MinerBlock.prototype.findNonce = function findNonce() {
|
||||
// The heart and soul of the miner: match the target.
|
||||
while (block.nonce <= 0xffffffff) {
|
||||
// Hash and test against the next target
|
||||
if (rcmp(this.dsha256(data), target) < 0)
|
||||
if (rcmp(utils.dsha256(data), target) < 0)
|
||||
return true;
|
||||
|
||||
// Increment the nonce to get a different hash
|
||||
@ -665,6 +665,64 @@ MinerBlock.prototype.destroy = function destroy() {
|
||||
this.block = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the miner block.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
MinerBlock.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
var i;
|
||||
|
||||
p.writeBytes(this.tip.toRaw());
|
||||
p.writeU32(this.block.version);
|
||||
p.writeU32(this.block.bits);
|
||||
p.writeVarString(this.address, 'ascii');
|
||||
p.writeVarString(this.coinbaseFlags, 'utf8');
|
||||
p.writeU8(this.witness ? 1 : 0);
|
||||
p.writeVarint(this.block.txs.length - 1);
|
||||
|
||||
for (i = 1; i < this.block.txs.length; i++)
|
||||
p.writeBytes(this.block.txs[i].render());
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a miner block from serialized data.
|
||||
* @params {Buffer} data
|
||||
* @returns {MinerBlock}
|
||||
*/
|
||||
|
||||
MinerBlock.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
var tip = bcoin.chainentry.fromRaw(null, p);
|
||||
var version = p.readU32();
|
||||
var bits = p.readU32();
|
||||
var address = p.readVarString('ascii');
|
||||
var coinbaseFlags = p.readVarString('utf8');
|
||||
var witness = p.readU8() === 1;
|
||||
var count = p.readVarint();
|
||||
var txs = [];
|
||||
var i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
txs.push(bcoin.tx.fromRaw(p));
|
||||
|
||||
return new MinerBlock({
|
||||
tip: tip,
|
||||
version: version,
|
||||
target: bits,
|
||||
address: address,
|
||||
coinbaseFlags: coinbaseFlags,
|
||||
witness: witness,
|
||||
txs: txs
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* "Reverse" comparison so we don't have
|
||||
* to waste time reversing the block hash.
|
||||
|
||||
@ -1274,11 +1274,6 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (tx.isCoinbase()) {
|
||||
notfound.push({ type: constants.inv.TX, hash: hash });
|
||||
return next();
|
||||
}
|
||||
|
||||
data = witness
|
||||
? self.framer.witnessTX(tx)
|
||||
: self.framer.tx(tx);
|
||||
|
||||
@ -2413,7 +2413,7 @@ BroadcastItem.prototype.finish = function finish(err) {
|
||||
assert(this.timeout, 'Already finished.');
|
||||
assert(this.pool.inv.map[this.hash], 'Already finished.');
|
||||
|
||||
clearInterval(this.timeout);
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = null;
|
||||
|
||||
delete this.pool.inv.map[this.hash];
|
||||
@ -2443,6 +2443,8 @@ BroadcastItem.prototype.send = function send(peer, witness) {
|
||||
if (this.type === constants.inv.TX) {
|
||||
if (this.msg.isCoinbase()) {
|
||||
peer.write(peer.framer.notFound([this]));
|
||||
bcoin.debug('Failsafe: tried to relay a coinbase.');
|
||||
this.finish(new Error('Coinbase.'));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -68,6 +68,52 @@ Workers.cleanup = function cleanup() {
|
||||
|
||||
Workers._exitBound = false;
|
||||
|
||||
/**
|
||||
* Bind to process events in order to cleanup listeners.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Workers._bindExit = function _bindExit() {
|
||||
if (utils.isBrowser)
|
||||
return;
|
||||
|
||||
if (Workers._exitBound)
|
||||
return;
|
||||
|
||||
Workers._exitBound = true;
|
||||
|
||||
function onExit(err) {
|
||||
Workers.cleanup();
|
||||
if (err) {
|
||||
console.error(err.stack + '');
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.once('exit', function() {
|
||||
Workers.cleanup();
|
||||
});
|
||||
|
||||
if (process.listeners('SIGINT').length === 0)
|
||||
process.once('SIGINT', onExit);
|
||||
|
||||
if (process.listeners('SIGTERM').length === 0)
|
||||
process.once('SIGTERM', onExit);
|
||||
|
||||
if (process.listeners('uncaughtException').length === 0)
|
||||
process.once('uncaughtException', onExit);
|
||||
|
||||
process.on('newListener', function(name) {
|
||||
if (name === 'SIGINT'
|
||||
|| name === 'SIGTERM'
|
||||
|| name === 'uncaughtException') {
|
||||
process.removeListener(name, onExit);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Spawn a new worker.
|
||||
* @param {Number} id - Worker ID.
|
||||
@ -110,10 +156,7 @@ Workers.prototype.spawn = function spawn(id) {
|
||||
|
||||
Workers.children.push(child);
|
||||
|
||||
if (!Workers._exitBound) {
|
||||
process.once('exit', Workers.cleanup);
|
||||
Workers._exitBound = true;
|
||||
}
|
||||
Workers._bindExit();
|
||||
|
||||
return child;
|
||||
};
|
||||
@ -221,15 +264,7 @@ Workers.prototype.verify = function verify(tx, index, force, flags, callback) {
|
||||
*/
|
||||
|
||||
Workers.prototype.mine = function mine(attempt, callback) {
|
||||
var data = {
|
||||
tip: attempt.tip,
|
||||
version: attempt.block.version,
|
||||
target: attempt.block.bits,
|
||||
address: attempt.address,
|
||||
coinbaseFlags: attempt.coinbaseFlags,
|
||||
witness: attempt.witness
|
||||
};
|
||||
return this.execute('mine', [data], -1, callback);
|
||||
return this.execute('mine', [attempt], -1, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -679,16 +714,7 @@ jobs.verify = function verify(tx, index, force, flags) {
|
||||
* @returns {Block}
|
||||
*/
|
||||
|
||||
jobs.mine = function mine(data) {
|
||||
var attempt = new bcoin.minerblock({
|
||||
tip: data.tip,
|
||||
version: data.version,
|
||||
target: data.target,
|
||||
address: data.address,
|
||||
coinbaseFlags: data.coinbaseFlags,
|
||||
witness: data.witness,
|
||||
dsha256: utils.dsha256
|
||||
});
|
||||
jobs.mine = function mine(attempt) {
|
||||
attempt.on('status', function(stat) {
|
||||
bcoin.debug(
|
||||
'Miner: hashrate=%dkhs hashes=%d target=%d height=%d best=%s',
|
||||
@ -793,6 +819,9 @@ Framer.item = function _item(item, p) {
|
||||
} else if (item instanceof bcoin.mempoolentry) {
|
||||
p.writeU8(44);
|
||||
item.toRaw(p);
|
||||
} else if (item instanceof bcoin.minerblock) {
|
||||
p.writeU8(45);
|
||||
item.toRaw(p);
|
||||
} else if (bn.isBN(item)) {
|
||||
p.writeU8(50);
|
||||
p.writeVarBytes(item.toBuffer());
|
||||
@ -951,8 +980,10 @@ Parser.parseItem = function parseItem(p) {
|
||||
return bcoin.coin.fromExtended(p);
|
||||
case 43:
|
||||
return bcoin.chainentry.fromRaw(null, p);
|
||||
case 43:
|
||||
case 44:
|
||||
return bcoin.mempoolentry.fromRaw(p);
|
||||
case 45:
|
||||
return bcoin.minerblock.fromRaw(p);
|
||||
case 50:
|
||||
return new bn(p.readVarBytes());
|
||||
default:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user