various fixes for our miner.
This commit is contained in:
parent
8d120a4fd6
commit
c56640a433
@ -25,6 +25,7 @@ bcoin.wallet = require('./bcoin/wallet');
|
||||
bcoin.peer = require('./bcoin/peer');
|
||||
bcoin.pool = require('./bcoin/pool');
|
||||
bcoin.hd = require('./bcoin/hd');
|
||||
bcoin.miner = require('./bcoin/miner');
|
||||
|
||||
bcoin.protocol.network.set(process.env.BCOIN_NETWORK || 'main');
|
||||
|
||||
|
||||
@ -110,15 +110,20 @@ Chain.prototype._init = function _init() {
|
||||
var self = this;
|
||||
var s;
|
||||
|
||||
if (!this.storage)
|
||||
this.loading = true;
|
||||
|
||||
if (!this.storage) {
|
||||
utils.nextTick(function() {
|
||||
self.loading = false;
|
||||
self.emit('load');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
utils.nextTick(function() {
|
||||
self.emit('debug', 'Chain is loading.');
|
||||
});
|
||||
|
||||
this.loading = true;
|
||||
|
||||
s = this.storage.createReadStream({
|
||||
start: this.prefix,
|
||||
end: this.prefix + 'z'
|
||||
@ -681,7 +686,7 @@ Chain.prototype._compact = function _compact(keep) {
|
||||
var entries = this._filter(this.index.entries);
|
||||
|
||||
if (!keep)
|
||||
keep = 1000;
|
||||
keep = network.powDiffInterval + 10;
|
||||
|
||||
// Keep only last 1000 consequent blocks, dilate others at:
|
||||
// 7 day range for blocks before 2013
|
||||
|
||||
@ -13,6 +13,8 @@ var bn = require('bn.js');
|
||||
var inherits = require('inherits');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
var crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* Miner
|
||||
*/
|
||||
@ -30,8 +32,8 @@ function Miner(options) {
|
||||
this.address = this.options.address;
|
||||
this.msg = this.options.msg || 'mined by bcoin';
|
||||
|
||||
this.chain = options.chain || bcoin.chain.global;
|
||||
this.pool = options.pool || bcoin.pool.global;
|
||||
this.chain = options.chain || this.pool.chain || bcoin.chain.global;
|
||||
|
||||
this.running = false;
|
||||
this.timeout = null;
|
||||
@ -40,7 +42,9 @@ function Miner(options) {
|
||||
this.fee = new bn(0);
|
||||
this.last = this.chain.getTip();
|
||||
this.block = null;
|
||||
this.rate = 0;
|
||||
this._begin = utils.now();
|
||||
|
||||
this._init();
|
||||
}
|
||||
|
||||
inherits(Miner, EventEmitter);
|
||||
@ -61,15 +65,23 @@ Miner.prototype._init = function _init() {
|
||||
// });
|
||||
|
||||
this.on('block', function(block) {
|
||||
self.emit('debug',
|
||||
self.chain.emit('debug',
|
||||
'Found block: %d (%s)',
|
||||
self.last.height + 1,
|
||||
block.height,
|
||||
block.hash('hex'));
|
||||
// Emit the block hex as a failsafe (in case we can't send it)
|
||||
self.chain.emit('debug', 'Block: %s', utils.toHex(block.render()));
|
||||
self.pool.sendBlock(block);
|
||||
});
|
||||
|
||||
this.on('status', function(stat) {
|
||||
self.emit('debug', 'Hashes per second: %s', stat.hashrate);
|
||||
self.chain.emit('debug',
|
||||
'hashrate=%dkhs hashes=%d target=%d height=%d best=%s',
|
||||
stat.hashrate / 1000 | 0,
|
||||
stat.hashes,
|
||||
stat.target,
|
||||
stat.height,
|
||||
stat.best);
|
||||
});
|
||||
};
|
||||
|
||||
@ -154,7 +166,7 @@ Miner.prototype.addTX = function addTX(tx) {
|
||||
// Add the tx to our block
|
||||
this.block.txs.push(tx);
|
||||
|
||||
// Calulcate our new reward fee
|
||||
// Calculate our new reward fee
|
||||
if (full)
|
||||
this.fee.iadd(tx.getFee());
|
||||
|
||||
@ -202,7 +214,7 @@ Miner.prototype.createBlock = function createBlock(tx) {
|
||||
: this.last.hash,
|
||||
merkleRoot: utils.toHex(constants.zeroHash.slice()),
|
||||
ts: ts,
|
||||
bits: utils.toCompact(target),
|
||||
bits: target,
|
||||
nonce: 0
|
||||
};
|
||||
|
||||
@ -212,20 +224,21 @@ Miner.prototype.createBlock = function createBlock(tx) {
|
||||
|
||||
block.txs.push(coinbase);
|
||||
|
||||
block.target = utils.fromCompact(target);
|
||||
block.extraNonce = new bn(0);
|
||||
|
||||
// Update coinbase since our coinbase was added.
|
||||
this.updateCoinbase(block);
|
||||
|
||||
// Create our merkle root.
|
||||
this.updateMerkle(block);
|
||||
|
||||
block.target = target;
|
||||
block.extraNonce = new bn(0);
|
||||
|
||||
return block;
|
||||
};
|
||||
|
||||
Miner.prototype.updateCoinbase = function updateCoinbase(block) {
|
||||
var coinbase = block.coinbase;
|
||||
var reward = bcoin.block.reward(this.last.height + 1);
|
||||
|
||||
assert(coinbase);
|
||||
|
||||
@ -233,7 +246,7 @@ Miner.prototype.updateCoinbase = function updateCoinbase(block) {
|
||||
block = this.block;
|
||||
|
||||
coinbase.inputs[0].script[1] = block.extraNonce.toArray();
|
||||
coinbase.outputs[0].value = bcoin.block.reward(this.last.height + 1).add(fee);
|
||||
coinbase.outputs[0].value = reward.add(this.fee);
|
||||
};
|
||||
|
||||
Miner.prototype.updateMerkle = function updateMerkle(block) {
|
||||
@ -277,19 +290,62 @@ Miner.prototype.iterate = function iterate() {
|
||||
}, 10);
|
||||
};
|
||||
|
||||
Miner.prototype.__defineGetter__('hashes', function() {
|
||||
return this.block.extraNonce.muln(0xffffffff).addn(this.block.nonce);
|
||||
});
|
||||
|
||||
Miner.prototype.__defineGetter__('rate', function() {
|
||||
if (!this.block.nonce)
|
||||
return 0;
|
||||
// Calculate our terrible hashrate
|
||||
return (this.block.nonce / (utils.now() - this._begin)) * 2 | 0;
|
||||
});
|
||||
|
||||
Miner.prototype.sendStatus = function sendStatus() {
|
||||
this.emit('status', {
|
||||
block: this.block,
|
||||
target: this.block.bits,
|
||||
hashes: this.hashes.toString(10),
|
||||
hashrate: this.rate,
|
||||
height: this.last.height + 1,
|
||||
best: utils.revHex(this.last.hash)
|
||||
});
|
||||
};
|
||||
|
||||
Miner.prototype.findNonce = function findNonce() {
|
||||
var begin = utils.now();
|
||||
var data = new Buffer(this.block.render());
|
||||
var now;
|
||||
|
||||
this._begin = utils.now();
|
||||
|
||||
// The heart and soul of the miner: match the target.
|
||||
while (this.block.nonce <= 0xffffffff) {
|
||||
if (utils.testTarget(this.block.target, this.block.hash()))
|
||||
// Hash and test against the next target
|
||||
if (utils.testTarget(this.block.target, dsha256(data)))
|
||||
return true;
|
||||
|
||||
// Increment the nonce to get a different hash
|
||||
this.block.nonce++;
|
||||
utils.writeU32(data, this.block.nonce, 76);
|
||||
|
||||
// Send progress report every so often
|
||||
if (this.block.nonce % 100000 === 0)
|
||||
this.sendStatus();
|
||||
}
|
||||
|
||||
// Calculate our terrible hashrate
|
||||
this.rate = (0xffffffff / (utils.now() - begin)) * 2;
|
||||
// Send progress report
|
||||
this.sendStatus();
|
||||
|
||||
// If we took more a second or more (likely),
|
||||
// skip incrementing the extra nonce and just
|
||||
// update the timestamp. This improves
|
||||
// performance because we do not have to
|
||||
// recalculate the merkle root.
|
||||
now = utils.now();
|
||||
if (now > this.block.ts) {
|
||||
this.block.ts = now;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Overflow the nonce and increment the extraNonce.
|
||||
this.block.nonce = 0;
|
||||
@ -301,17 +357,21 @@ Miner.prototype.findNonce = function findNonce() {
|
||||
// We changed the coinbase, need to update merkleRoot.
|
||||
this.updateMerkle();
|
||||
|
||||
// Send progress report
|
||||
this.emit('status', {
|
||||
block: this.block,
|
||||
target: this.block.target,
|
||||
hashes: this.block.extraNonce.mul(0xffffffff).toString(10),
|
||||
hashrate: this.rate
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
|
||||
function sha256(data, enc) {
|
||||
return crypto.createHash('sha256').update(data).digest();
|
||||
}
|
||||
|
||||
function dsha256(data, enc) {
|
||||
return Array.prototype.slice.call(sha256(sha256(data, enc)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -149,13 +149,13 @@ function Pool(options) {
|
||||
|
||||
Pool.global = this;
|
||||
|
||||
if (!this.chain.loading) {
|
||||
this._init();
|
||||
} else {
|
||||
this.chain.once('load', function() {
|
||||
self._init();
|
||||
});
|
||||
}
|
||||
this.loading = true;
|
||||
|
||||
this.chain.once('load', function() {
|
||||
self.loading = false;
|
||||
self.emit('load');
|
||||
self._init();
|
||||
});
|
||||
}
|
||||
|
||||
inherits(Pool, EventEmitter);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user