rpc: improve mining.
This commit is contained in:
parent
3f5c5cf603
commit
6598245486
125
lib/http/rpc.js
125
lib/http/rpc.js
@ -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
|
||||
*/
|
||||
|
||||
@ -435,7 +435,7 @@ HTTPServer.prototype._init = function _init() {
|
||||
}
|
||||
|
||||
send(200, {
|
||||
result: json,
|
||||
result: json != null ? json : null,
|
||||
error: null,
|
||||
id: req.body.id
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user