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.miner = node.miner;
this.wallet = node.wallet; this.wallet = node.wallet;
this.walletdb = node.walletdb; this.walletdb = node.walletdb;
this.locker = new bcoin.locker(this);
this.feeRate = null; this.feeRate = null;
this.mining = false; this.mining = false;
@ -95,6 +96,8 @@ RPC.prototype.execute = function execute(json, callback) {
return this.getmininginfo(json.params, callback); return this.getmininginfo(json.params, callback);
case 'prioritisetransaction': case 'prioritisetransaction':
return this.prioritisetransaction(json.params, callback); return this.prioritisetransaction(json.params, callback);
case 'getwork':
return this.getwork(json.params, callback);
case 'getblocktemplate': case 'getblocktemplate':
return this.getblocktemplate(json.params, callback); return this.getblocktemplate(json.params, callback);
case 'submitblock': case 'submitblock':
@ -272,7 +275,7 @@ RPC.prototype.execute = function execute(json, callback) {
return this.getmemory(json.params, callback); return this.getmemory(json.params, callback);
default: 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 * 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) { RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
var self = this; var self = this;
var txs = []; var txs = [];
@ -1391,6 +1462,11 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
var i, j, tx, deps, input, dep, block; var i, j, tx, deps, input, dep, block;
var opt, lpid, keys, vbavailable, vbrules, mutable, clientRules; var opt, lpid, keys, vbavailable, vbrules, mutable, clientRules;
callback = this.locker.lock(getblocktemplate, [args, callback]);
if (!callback)
return;
if (args.help || args.length > 1) if (args.help || args.length > 1)
return callback(new RPCError('getblocktemplate ( "jsonrequestobject" )')); return callback(new RPCError('getblocktemplate ( "jsonrequestobject" )'));
@ -1433,11 +1509,13 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
} }
} }
if (this.pool.peers.all.length === 0) if (this.network !== bcoin.network.regtest) {
return callback(new RPCError('Bitcoin is not connected!')); if (this.pool.peers.all.length === 0)
return callback(new RPCError('Bitcoin is not connected!'));
if (!this.chain.isFull()) if (!this.chain.isFull())
return callback(new RPCError('Bitcoin is downloading blocks...')); return callback(new RPCError('Bitcoin is downloading blocks...'));
}
this._poll(lpid, function(err) { this._poll(lpid, function(err) {
if (err) if (err)
@ -1528,16 +1606,18 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
flags: new Buffer(attempt.coinbaseFlags, 'utf8').toString('hex') flags: new Buffer(attempt.coinbaseFlags, 'utf8').toString('hex')
}, },
coinbasevalue: attempt.coinbase.outputs[0].value, 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')), target: utils.revHex(attempt.target.toString('hex')),
mintime: attempt.ts, mintime: attempt.block.ts,
mutable: mutable, mutable: mutable,
noncerange: '00000000ffffffff', 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, sizelimit: constants.block.MAX_SIZE,
weightlimit: constants.block.MAX_WEIGHT, weightlimit: constants.block.MAX_WEIGHT,
curtime: block.ts, curtime: block.ts,
bits: String(block.bits), bits: utils.hex32(block.bits),
height: attempt.height, height: attempt.height,
default_witness_commitment: attempt.witness default_witness_commitment: attempt.witness
? attempt.coinbase.outputs[1].script.toJSON() ? attempt.coinbase.outputs[1].script.toJSON()
@ -1569,7 +1649,7 @@ RPC.prototype._poll = function _poll(lpid, callback) {
} }
function listener() { 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.chain.removeListener('block', listener);
self.mempool.removeListener('tx', listener); self.mempool.removeListener('tx', listener);
return callback(); return callback();
@ -1580,20 +1660,31 @@ RPC.prototype._poll = function _poll(lpid, callback) {
this.mempool.on('tx', listener); 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) { RPC.prototype._createBlock = function _createBlock(callback) {
var self = this; var self = this;
var diff = utils.now() - this.start;
var total = this.mempool.totalTX;
if (this.prevBlock !== this.chain.tip.hash 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) { return this.miner.createBlock(function(err, attempt) {
if (err) if (err)
return callback(err); return callback(err);
self.prevBlock = attempt.block.prevBlock; self.prevBlock = attempt.block.prevBlock;
self.currentBlock = attempt; self.currentBlock = attempt;
self.lastTX = self.mempool.total; self.lastTX = self.mempool.totalTX;
self.start = utils.now(); self.start = utils.now();
callback(null, attempt); callback(null, attempt);
}); });
} }
callback(null, this.currentBlock); callback(null, this.currentBlock);
}; };
@ -1622,7 +1713,7 @@ RPC.prototype.getmininginfo = function getmininginfo(args, callback) {
errors: '', errors: '',
genproclimit: self.proclimit, genproclimit: self.proclimit,
networkhashps: hashps, networkhashps: hashps,
pooledtx: self.mempool.total, pooledtx: self.mempool.totalTX,
testnet: self.network.type !== bcoin.network.main, testnet: self.network.type !== bcoin.network.main,
chain: self.network.type, chain: self.network.type,
generate: self.mining generate: self.mining
@ -4170,6 +4261,14 @@ function toSatoshi(obj) {
return utils.satoshi(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 * Expose
*/ */

View File

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