various fixes for our miner.

This commit is contained in:
Christopher Jeffrey 2016-01-06 19:57:35 -08:00
parent 8d120a4fd6
commit c56640a433
4 changed files with 100 additions and 34 deletions

View File

@ -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');

View File

@ -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

View File

@ -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
*/

View File

@ -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);