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.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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user