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