rpc: improve mining.

This commit is contained in:
Christopher Jeffrey 2016-09-17 06:24:58 -07:00
parent 3f5c5cf603
commit 6598245486
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 113 additions and 14 deletions

View File

@ -33,6 +33,7 @@ function RPC(node) {
this.miner = node.miner;
this.wallet = node.wallet;
this.walletdb = node.walletdb;
this.locker = new bcoin.locker(this);
this.feeRate = null;
this.mining = false;
@ -95,6 +96,8 @@ RPC.prototype.execute = function execute(json, callback) {
return this.getmininginfo(json.params, callback);
case 'prioritisetransaction':
return this.prioritisetransaction(json.params, callback);
case 'getwork':
return this.getwork(json.params, callback);
case 'getblocktemplate':
return this.getblocktemplate(json.params, callback);
case 'submitblock':
@ -272,7 +275,7 @@ RPC.prototype.execute = function execute(json, callback) {
return this.getmemory(json.params, callback);
default:
return callback(new Error('Method not found.'));
return callback(new Error('Method not found: ' + json.method + '.'));
}
};
@ -1382,6 +1385,74 @@ RPC.prototype.verifychain = function verifychain(args, callback) {
* Mining
*/
RPC.prototype.getwork = function getwork(args, callback, force) {
var self = this;
var i, data, abbr, field, block, header;
callback = this.locker.lock(getwork, [args, callback], force);
if (!callback)
return;
if (args.length > 1)
return callback(new RPCError('getwork ( "data" )'));
if (args.length === 1 && this.currentBlock) {
if (!utils.isHex(args[0]))
return callback(new RPCError('Invalid parameter.'));
if (args[0].length !== 256)
return callback(new RPCError('Invalid parameter.'));
data = new Buffer(args[0], 'hex').slice(0, 80);
reverseEndian(data);
header = bcoin.headers.fromAbbr(data);
block = this.currentBlock.block;
this._clearBlock();
if (header.prevBlock !== block.prevBlock)
return self.getwork([], callback, true);
block.nonce = header.nonce;
block.ts = header.ts;
block.mutable = false;
block.txs[0].mutable = false;
return this.chain.add(block, function(err) {
if (err) {
if (err.reason)
return callback(new RPCError(err.reason));
return callback(err);
}
return self.getwork([], callback, true);
});
}
this._createBlock(function(err, attempt) {
if (err)
return callback(err);
data = new Buffer(128);
data.fill(0);
abbr = attempt.block.abbr();
abbr.copy(data, 0);
data[80] = 0x80;
data.writeUInt32BE(80 * 8, data.length - 4, true);
reverseEndian(data);
callback(null, {
data: data.toString('hex'),
target: attempt.target.toString('hex'),
height: attempt.height
});
});
};
RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
var self = this;
var txs = [];
@ -1391,6 +1462,11 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
var i, j, tx, deps, input, dep, block;
var opt, lpid, keys, vbavailable, vbrules, mutable, clientRules;
callback = this.locker.lock(getblocktemplate, [args, callback]);
if (!callback)
return;
if (args.help || args.length > 1)
return callback(new RPCError('getblocktemplate ( "jsonrequestobject" )'));
@ -1433,11 +1509,13 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
}
}
if (this.pool.peers.all.length === 0)
return callback(new RPCError('Bitcoin is not connected!'));
if (this.network !== bcoin.network.regtest) {
if (this.pool.peers.all.length === 0)
return callback(new RPCError('Bitcoin is not connected!'));
if (!this.chain.isFull())
return callback(new RPCError('Bitcoin is downloading blocks...'));
if (!this.chain.isFull())
return callback(new RPCError('Bitcoin is downloading blocks...'));
}
this._poll(lpid, function(err) {
if (err)
@ -1528,16 +1606,18 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
flags: new Buffer(attempt.coinbaseFlags, 'utf8').toString('hex')
},
coinbasevalue: attempt.coinbase.outputs[0].value,
longpollid: self.chain.tip.rhash + self.mempool.total,
longpollid: self.chain.tip.rhash + utils.pad32(self.mempool.totalTX),
target: utils.revHex(attempt.target.toString('hex')),
mintime: attempt.ts,
mintime: attempt.block.ts,
mutable: mutable,
noncerange: '00000000ffffffff',
sigoplimit: constants.block.MAX_SIGOPS_WEIGHT,
sigoplimit: attempt.witness
? constants.block.MAX_SIGOPS_WEIGHT
: constants.block.MAX_SIGOPS,
sizelimit: constants.block.MAX_SIZE,
weightlimit: constants.block.MAX_WEIGHT,
curtime: block.ts,
bits: String(block.bits),
bits: utils.hex32(block.bits),
height: attempt.height,
default_witness_commitment: attempt.witness
? attempt.coinbase.outputs[1].script.toJSON()
@ -1569,7 +1649,7 @@ RPC.prototype._poll = function _poll(lpid, callback) {
}
function listener() {
if (self.chain.tip.hash !== watched || self.mempool.total !== lastTX) {
if (self.chain.tip.hash !== watched || self.mempool.totalTX !== lastTX) {
self.chain.removeListener('block', listener);
self.mempool.removeListener('tx', listener);
return callback();
@ -1580,20 +1660,31 @@ RPC.prototype._poll = function _poll(lpid, callback) {
this.mempool.on('tx', listener);
};
RPC.prototype._clearBlock = function _clearBlock() {
this.prevBlock = null;
this.currentBlock = null;
this.lastTX = 0;
this.start = 0;
};
RPC.prototype._createBlock = function _createBlock(callback) {
var self = this;
var diff = utils.now() - this.start;
var total = this.mempool.totalTX;
if (this.prevBlock !== this.chain.tip.hash
|| (this.mempool.total !== this.lastTX && utils.now() - this.start > 5)) {
|| (total !== this.lastTX && diff > 5)) {
return this.miner.createBlock(function(err, attempt) {
if (err)
return callback(err);
self.prevBlock = attempt.block.prevBlock;
self.currentBlock = attempt;
self.lastTX = self.mempool.total;
self.lastTX = self.mempool.totalTX;
self.start = utils.now();
callback(null, attempt);
});
}
callback(null, this.currentBlock);
};
@ -1622,7 +1713,7 @@ RPC.prototype.getmininginfo = function getmininginfo(args, callback) {
errors: '',
genproclimit: self.proclimit,
networkhashps: hashps,
pooledtx: self.mempool.total,
pooledtx: self.mempool.totalTX,
testnet: self.network.type !== bcoin.network.main,
chain: self.network.type,
generate: self.mining
@ -4170,6 +4261,14 @@ function toSatoshi(obj) {
return utils.satoshi(obj + '');
}
function reverseEndian(data) {
var i, field;
for (i = 0; i < data.length; i += 4) {
field = data.readUInt32LE(i, true);
data.writeUInt32BE(field, i, true);
}
}
/*
* Expose
*/

View File

@ -435,7 +435,7 @@ HTTPServer.prototype._init = function _init() {
}
send(200, {
result: json,
result: json != null ? json : null,
error: null,
id: req.body.id
});