rpc: more mining nonsense.
This commit is contained in:
parent
6598245486
commit
061548f2ac
513
lib/http/rpc.js
513
lib/http/rpc.js
@ -12,6 +12,7 @@ var crypto = require('../crypto/crypto');
|
|||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var NetworkAddress = require('../primitives/netaddress');
|
var NetworkAddress = require('../primitives/netaddress');
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var fs;
|
var fs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -24,6 +25,8 @@ function RPC(node) {
|
|||||||
if (!(this instanceof RPC))
|
if (!(this instanceof RPC))
|
||||||
return new RPC(node);
|
return new RPC(node);
|
||||||
|
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.network = node.network;
|
this.network = node.network;
|
||||||
this.chain = node.chain;
|
this.chain = node.chain;
|
||||||
@ -39,12 +42,13 @@ function RPC(node) {
|
|||||||
this.mining = false;
|
this.mining = false;
|
||||||
this.proclimit = 0;
|
this.proclimit = 0;
|
||||||
|
|
||||||
this.prevBlock = null;
|
|
||||||
this.currentBlock = null;
|
this.currentBlock = null;
|
||||||
this.lastTX = 0;
|
this.blockStart = 0;
|
||||||
this.start = 0;
|
this._boundChain = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils.inherits(RPC, EventEmitter);
|
||||||
|
|
||||||
RPC.prototype.execute = function execute(json, callback) {
|
RPC.prototype.execute = function execute(json, callback) {
|
||||||
switch (json.method) {
|
switch (json.method) {
|
||||||
case 'stop':
|
case 'stop':
|
||||||
@ -1385,51 +1389,46 @@ RPC.prototype.verifychain = function verifychain(args, callback) {
|
|||||||
* Mining
|
* Mining
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RPC.prototype.getwork = function getwork(args, callback, force) {
|
RPC.prototype._submitwork = function getwork(data, callback) {
|
||||||
var self = this;
|
var data, block, header;
|
||||||
var i, data, abbr, field, block, header;
|
|
||||||
|
|
||||||
callback = this.locker.lock(getwork, [args, callback], force);
|
if (data.length !== 128)
|
||||||
|
return callback(new RPCError('Invalid parameter.'));
|
||||||
|
|
||||||
if (!callback)
|
if (!this.currentBlock)
|
||||||
return;
|
return this._getwork(callback);
|
||||||
|
|
||||||
if (args.length > 1)
|
data = data.slice(0, 80);
|
||||||
return callback(new RPCError('getwork ( "data" )'));
|
|
||||||
|
|
||||||
if (args.length === 1 && this.currentBlock) {
|
reverseEndian(data);
|
||||||
if (!utils.isHex(args[0]))
|
|
||||||
return callback(new RPCError('Invalid parameter.'));
|
|
||||||
|
|
||||||
if (args[0].length !== 256)
|
header = bcoin.headers.fromAbbr(data);
|
||||||
return callback(new RPCError('Invalid parameter.'));
|
block = this.currentBlock.block;
|
||||||
|
|
||||||
data = new Buffer(args[0], 'hex').slice(0, 80);
|
if (header.prevBlock !== block.prevBlock
|
||||||
reverseEndian(data);
|
|| header.merkleRoot !== block.merkleRoot
|
||||||
|
|| header.bits !== block.bits) {
|
||||||
header = bcoin.headers.fromAbbr(data);
|
return callback(null, false);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.type === 'VerifyError')
|
||||||
|
return callback(null, false);
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null, true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
RPC.prototype._getwork = function getwork(callback) {
|
||||||
|
var i, data, abbr;
|
||||||
|
|
||||||
this._createBlock(function(err, attempt) {
|
this._createBlock(function(err, attempt) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -1453,20 +1452,70 @@ RPC.prototype.getwork = function getwork(args, callback, force) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
|
RPC.prototype.getwork = function getwork(args, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var txs = [];
|
var data;
|
||||||
var txIndex = {};
|
|
||||||
var mode = 'template';
|
|
||||||
var maxVersion = -1;
|
|
||||||
var i, j, tx, deps, input, dep, block;
|
|
||||||
var opt, lpid, keys, vbavailable, vbrules, mutable, clientRules;
|
|
||||||
|
|
||||||
callback = this.locker.lock(getblocktemplate, [args, callback]);
|
callback = this.locker.lock(getwork, [args, callback]);
|
||||||
|
|
||||||
if (!callback)
|
if (!callback)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (args.length > 1)
|
||||||
|
return callback(new RPCError('getwork ( "data" )'));
|
||||||
|
|
||||||
|
if (args.length === 1) {
|
||||||
|
if (!utils.isHex(args[0]))
|
||||||
|
return callback(new RPCError('Invalid parameter.'));
|
||||||
|
|
||||||
|
data = new Buffer(args[0], 'hex');
|
||||||
|
|
||||||
|
return this._submitwork(data, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._getwork(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
RPC.prototype.submitblock = function submitblock(args, callback) {
|
||||||
|
var block;
|
||||||
|
|
||||||
|
callback = this.locker.lock(submitblock, [args, callback]);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.help || args.length < 1 || args.length > 2) {
|
||||||
|
return callback(new RPCError('submitblock "hexdata"'
|
||||||
|
+ ' ( "jsonparametersobject" )'));
|
||||||
|
}
|
||||||
|
|
||||||
|
block = bcoin.block.fromRaw(toString(args[0]), 'hex');
|
||||||
|
|
||||||
|
this._submitblock(block, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
RPC.prototype._submitblock = function submitblock(block, callback) {
|
||||||
|
if (block.prevBlock !== this.chain.tip.hash)
|
||||||
|
return callback(null, 'rejected: inconclusive-not-best-prevblk');
|
||||||
|
|
||||||
|
this.chain.add(block, function(err, total) {
|
||||||
|
if (err) {
|
||||||
|
if (err.type === 'VerifyError')
|
||||||
|
return callback(null, 'rejected: ' + err.reason);
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
callback(null, null);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
|
||||||
|
var self = this;
|
||||||
|
var mode = 'template';
|
||||||
|
var version = -1;
|
||||||
|
var coinbase = true;
|
||||||
|
var i, opt, lpid, keys, rules;
|
||||||
|
var cap, coinbasevalue, coinbasetxn;
|
||||||
|
|
||||||
if (args.help || args.length > 1)
|
if (args.help || args.length > 1)
|
||||||
return callback(new RPCError('getblocktemplate ( "jsonrequestobject" )'));
|
return callback(new RPCError('getblocktemplate ( "jsonrequestobject" )'));
|
||||||
|
|
||||||
@ -1487,25 +1536,32 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
|
|||||||
|
|
||||||
block = bcoin.block.fromRaw(opt.data, 'hex');
|
block = bcoin.block.fromRaw(opt.data, 'hex');
|
||||||
|
|
||||||
if (block.prevBlock !== self.chain.tip.hash)
|
return this._submitblock(block, callback);
|
||||||
return callback(new RPCError('inconclusive-not-best-prevblk'));
|
|
||||||
|
|
||||||
return this.chain.add(block, function(err) {
|
|
||||||
if (err) {
|
|
||||||
if (err.reason)
|
|
||||||
return callback(null, err.reason);
|
|
||||||
return callback(null, 'rejected');
|
|
||||||
}
|
|
||||||
callback(null, null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(opt.rules)) {
|
if (Array.isArray(opt.rules)) {
|
||||||
clientRules = [];
|
rules = [];
|
||||||
for (i = 0; i < opt.rules.length; i++)
|
for (i = 0; i < opt.rules.length; i++)
|
||||||
clientRules.push(String(opt.rules[i]));
|
rules.push(toString(opt.rules[i]));
|
||||||
} else if (utils.isNumber(opt.maxversion)) {
|
} else if (utils.isNumber(opt.maxversion)) {
|
||||||
maxVersion = opt.maxversion;
|
version = opt.maxversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(opt.capabilities)) {
|
||||||
|
for (i = 0; i < opt.capabilities.length; i++) {
|
||||||
|
cap = toString(opt.capabilities[i]);
|
||||||
|
switch (cap) {
|
||||||
|
case 'coinbasetxn':
|
||||||
|
coinbasetxn = true;
|
||||||
|
break;
|
||||||
|
case 'coinbasevalue':
|
||||||
|
coinbasevalue = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coinbasetxn && !coinbasevalue)
|
||||||
|
coinbase = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1520,110 +1576,143 @@ RPC.prototype.getblocktemplate = function getblocktemplate(args, callback) {
|
|||||||
this._poll(lpid, function(err) {
|
this._poll(lpid, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
self._tmpl(version, coinbase, rules, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
self._createBlock(function(err, attempt) {
|
RPC.prototype._tmpl = function _tmpl(version, coinbase, rules, callback) {
|
||||||
|
var self = this;
|
||||||
|
var txs = [];
|
||||||
|
var txIndex = {};
|
||||||
|
var i, j, tx, deps, input, dep, block;
|
||||||
|
var keys, vbavailable, vbrules, mutable, template;
|
||||||
|
|
||||||
|
callback = this.locker.lock(_tmpl, [version, coinbase, rules, callback]);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._createBlock(function(err, attempt) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
block = attempt.block;
|
||||||
|
|
||||||
|
for (i = 1; i < block.txs.length; i++) {
|
||||||
|
tx = block.txs[i];
|
||||||
|
txIndex[tx.hash('hex')] = i;
|
||||||
|
deps = [];
|
||||||
|
|
||||||
|
for (j = 0; j < tx.inputs.length; j++) {
|
||||||
|
input = tx.inputs[j];
|
||||||
|
dep = txIndex[input.prevout.hash];
|
||||||
|
if (dep != null)
|
||||||
|
deps.push(dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
txs.push({
|
||||||
|
data: tx.toRaw().toString('hex'),
|
||||||
|
txid: tx.rhash,
|
||||||
|
hash: tx.rwhash,
|
||||||
|
depends: deps,
|
||||||
|
fee: tx.getFee(),
|
||||||
|
sigops: tx.getSigops(),
|
||||||
|
weight: tx.getWeight()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = Object.keys(self.network.deployments);
|
||||||
|
vbavailable = {};
|
||||||
|
vbrules = [];
|
||||||
|
mutable = ['time', 'transactions', 'prevblock'];
|
||||||
|
|
||||||
|
if (version >= 2)
|
||||||
|
mutable.push('version/force');
|
||||||
|
|
||||||
|
utils.forEachSerial(keys, function(id, next) {
|
||||||
|
var deployment = self.network.deployments[id];
|
||||||
|
self.chain.getState(self.chain.tip, id, function(err, state) {
|
||||||
|
if (err)
|
||||||
|
return next(err);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case constants.thresholdStates.DEFINED:
|
||||||
|
case constants.thresholdStates.FAILED:
|
||||||
|
break;
|
||||||
|
case constants.thresholdStates.LOCKED_IN:
|
||||||
|
block.version |= 1 << deployment.bit;
|
||||||
|
case constants.thresholdStates.STARTED:
|
||||||
|
vbavailable[id] = deployment.bit;
|
||||||
|
if (rules) {
|
||||||
|
if (rules.indexOf(id) === -1 && !deployment.force)
|
||||||
|
block.version &= ~(1 << deployment.bit);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case constants.thresholdStates.ACTIVE:
|
||||||
|
vbrules.push(id);
|
||||||
|
if (rules) {
|
||||||
|
if (rules.indexOf(id) === -1 && !deployment.force)
|
||||||
|
return next(new RPCError('Client must support ' + id + '.'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
block = attempt.block;
|
block.version >>>= 0;
|
||||||
|
|
||||||
for (i = 1; i < block.txs.length; i++) {
|
template = {
|
||||||
tx = block.txs[i];
|
capabilities: ['proposal'],
|
||||||
txIndex[tx.hash('hex')] = i;
|
version: block.version,
|
||||||
deps = [];
|
rules: vbrules,
|
||||||
|
vbavailable: vbavailable,
|
||||||
|
vbrequired: 0,
|
||||||
|
previousblockhash: utils.revHex(block.prevBlock),
|
||||||
|
transactions: txs,
|
||||||
|
coinbaseaux: {
|
||||||
|
flags: attempt.coinbaseFlags.toString('hex')
|
||||||
|
},
|
||||||
|
coinbasevalue: attempt.coinbase.outputs[0].value,
|
||||||
|
longpollid: self.chain.tip.rhash + utils.pad32(self.mempool.totalTX),
|
||||||
|
target: utils.revHex(attempt.target.toString('hex')),
|
||||||
|
submitold: false,
|
||||||
|
mintime: block.ts,
|
||||||
|
maxtime: bcoin.now(),
|
||||||
|
mutable: mutable,
|
||||||
|
noncerange: '00000000ffffffff',
|
||||||
|
sigoplimit: attempt.witness
|
||||||
|
? constants.block.MAX_SIGOPS_WEIGHT
|
||||||
|
: constants.block.MAX_SIGOPS,
|
||||||
|
sizelimit: constants.block.MAX_SIZE,
|
||||||
|
weightlimit: constants.block.MAX_WEIGHT,
|
||||||
|
curtime: bcoin.now(),
|
||||||
|
bits: utils.hex32(block.bits),
|
||||||
|
height: attempt.height,
|
||||||
|
default_witness_commitment: attempt.witness
|
||||||
|
? attempt.coinbase.outputs[1].script.toJSON()
|
||||||
|
: undefined
|
||||||
|
};
|
||||||
|
|
||||||
for (j = 0; j < tx.inputs.length; j++) {
|
if (!coinbase) {
|
||||||
input = tx.inputs[j];
|
template.coinbaseaux = undefined;
|
||||||
dep = txIndex[input.prevout.hash];
|
template.coinbasevalue = undefined;
|
||||||
if (dep != null)
|
tx = block.txs[0];
|
||||||
deps.push(dep);
|
template.coinbasetxn = {
|
||||||
}
|
|
||||||
|
|
||||||
txs.push({
|
|
||||||
data: tx.toRaw().toString('hex'),
|
data: tx.toRaw().toString('hex'),
|
||||||
txid: tx.rhash,
|
txid: tx.rhash,
|
||||||
hash: tx.rwhash,
|
hash: tx.rwhash,
|
||||||
depends: deps,
|
depends: [],
|
||||||
fee: tx.getFee(),
|
fee: 0,
|
||||||
sigops: tx.getSigops(),
|
sigops: tx.getSigops(),
|
||||||
weight: tx.getWeight()
|
weight: tx.getWeight()
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = Object.keys(self.network.deployments);
|
callback(null, template);
|
||||||
vbavailable = {};
|
|
||||||
vbrules = [];
|
|
||||||
mutable = ['time', 'transactions', 'prevblock'];
|
|
||||||
|
|
||||||
if (maxVersion >= 2)
|
|
||||||
mutable.push('version/force');
|
|
||||||
|
|
||||||
utils.forEachSerial(keys, function(id, next) {
|
|
||||||
var deployment = self.network.deployments[id];
|
|
||||||
self.chain.getState(self.chain.tip, id, function(err, state) {
|
|
||||||
if (err)
|
|
||||||
return next(err);
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case constants.thresholdStates.DEFINED:
|
|
||||||
case constants.thresholdStates.FAILED:
|
|
||||||
break;
|
|
||||||
case constants.thresholdStates.LOCKED_IN:
|
|
||||||
block.version |= 1 << deployment.bit;
|
|
||||||
case constants.thresholdStates.STARTED:
|
|
||||||
vbavailable[id] = deployment.bit;
|
|
||||||
if (clientRules) {
|
|
||||||
if (clientRules.indexOf(id) === -1 && !deployment.force)
|
|
||||||
block.version &= ~(1 << deployment.bit);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case constants.thresholdStates.ACTIVE:
|
|
||||||
vbrules.push(id);
|
|
||||||
if (clientRules) {
|
|
||||||
if (clientRules.indexOf(id) === -1 && !deployment.force)
|
|
||||||
return next(new RPCError('Client must support ' + id + '.'));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}, function(err) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
block.version >>>= 0;
|
|
||||||
|
|
||||||
callback(null, {
|
|
||||||
capabilities: ['proposal'],
|
|
||||||
version: block.version,
|
|
||||||
rules: vbrules,
|
|
||||||
vbavailable: vbavailable,
|
|
||||||
vbrequired: 0,
|
|
||||||
previousblockhash: utils.revHex(block.prevBlock),
|
|
||||||
transactions: txs,
|
|
||||||
coinbaseaux: {
|
|
||||||
flags: new Buffer(attempt.coinbaseFlags, 'utf8').toString('hex')
|
|
||||||
},
|
|
||||||
coinbasevalue: attempt.coinbase.outputs[0].value,
|
|
||||||
longpollid: self.chain.tip.rhash + utils.pad32(self.mempool.totalTX),
|
|
||||||
target: utils.revHex(attempt.target.toString('hex')),
|
|
||||||
mintime: attempt.block.ts,
|
|
||||||
mutable: mutable,
|
|
||||||
noncerange: '00000000ffffffff',
|
|
||||||
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: utils.hex32(block.bits),
|
|
||||||
height: attempt.height,
|
|
||||||
default_witness_commitment: attempt.witness
|
|
||||||
? attempt.coinbase.outputs[1].script.toJSON()
|
|
||||||
: undefined
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1632,60 +1721,77 @@ RPC.prototype._poll = function _poll(lpid, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var watched, lastTX;
|
var watched, lastTX;
|
||||||
|
|
||||||
if (lpid == null)
|
if (typeof lpid !== 'string')
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
if (typeof lpid === 'string') {
|
if (lpid.length !== 74)
|
||||||
if (lpid.length < 65)
|
return callback(new RPCError('Invalid parameter.'));
|
||||||
return callback(new RPCError('Invalid parameter.'));
|
|
||||||
watched = lpid.slice(0, 64);
|
|
||||||
lastTX = +lpid.slice(64);
|
|
||||||
if (!utils.isHex(watched) || !utils.isNumber(lastTX))
|
|
||||||
return callback(new RPCError('Invalid parameter.'));
|
|
||||||
watched = utils.revHex(watched);
|
|
||||||
} else {
|
|
||||||
watched = this.chain.tip.hash;
|
|
||||||
lastTX = this.lastTX;
|
|
||||||
}
|
|
||||||
|
|
||||||
function listener() {
|
watched = lpid.slice(0, 64);
|
||||||
if (self.chain.tip.hash !== watched || self.mempool.totalTX !== lastTX) {
|
lastTX = +lpid.slice(64, 74);
|
||||||
self.chain.removeListener('block', listener);
|
|
||||||
self.mempool.removeListener('tx', listener);
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chain.on('block', listener);
|
if (!utils.isHex(watched) || !utils.isNumber(lastTX))
|
||||||
this.mempool.on('tx', listener);
|
return callback(new RPCError('Invalid parameter.'));
|
||||||
|
|
||||||
|
watched = utils.revHex(watched);
|
||||||
|
|
||||||
|
if (self.chain.tip.hash !== watched)
|
||||||
|
return callback();
|
||||||
|
|
||||||
|
this.once('clear block', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
RPC.prototype._clearBlock = function _clearBlock() {
|
RPC.prototype._clearBlock = function _clearBlock() {
|
||||||
this.prevBlock = null;
|
|
||||||
this.currentBlock = null;
|
this.currentBlock = null;
|
||||||
this.lastTX = 0;
|
this.blockStart = 0;
|
||||||
this.start = 0;
|
};
|
||||||
|
|
||||||
|
RPC.prototype._bindChain = function _bindChain() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (this._boundChain)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._boundChain = true;
|
||||||
|
|
||||||
|
this.chain.on('connect', function() {
|
||||||
|
if (!self.currentBlock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self._clearBlock();
|
||||||
|
self.emit('clear block');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.mempool.on('tx', function() {
|
||||||
|
var diff;
|
||||||
|
|
||||||
|
if (!self.currentBlock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
diff = utils.now() - self.blockStart;
|
||||||
|
|
||||||
|
if (diff > 5) {
|
||||||
|
self._clearBlock();
|
||||||
|
self.emit('clear block');
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
this._bindChain();
|
||||||
|| (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.totalTX;
|
|
||||||
self.start = utils.now();
|
|
||||||
callback(null, attempt);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null, this.currentBlock);
|
if (this.currentBlock)
|
||||||
|
return callback(null, this.currentBlock);
|
||||||
|
|
||||||
|
this.miner.createBlock(function(err, attempt) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
self.currentBlock = attempt;
|
||||||
|
self.blockStart = utils.now();
|
||||||
|
callback(null, attempt);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
RPC.prototype.getmininginfo = function getmininginfo(args, callback) {
|
RPC.prototype.getmininginfo = function getmininginfo(args, callback) {
|
||||||
@ -1714,8 +1820,8 @@ RPC.prototype.getmininginfo = function getmininginfo(args, callback) {
|
|||||||
genproclimit: self.proclimit,
|
genproclimit: self.proclimit,
|
||||||
networkhashps: hashps,
|
networkhashps: hashps,
|
||||||
pooledtx: self.mempool.totalTX,
|
pooledtx: self.mempool.totalTX,
|
||||||
testnet: self.network.type !== bcoin.network.main,
|
testnet: self.network !== bcoin.network.main,
|
||||||
chain: self.network.type,
|
chain: 'main',
|
||||||
generate: self.mining
|
generate: self.mining
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1773,23 +1879,6 @@ RPC.prototype.prioritisetransaction = function prioritisetransaction(args, callb
|
|||||||
callback(null, true);
|
callback(null, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
RPC.prototype.submitblock = function submitblock(args, callback) {
|
|
||||||
var block;
|
|
||||||
|
|
||||||
if (args.help || args.length < 1 || args.length > 2) {
|
|
||||||
return callback(new RPCError('submitblock "hexdata"'
|
|
||||||
+ ' ( "jsonparametersobject" )'));
|
|
||||||
}
|
|
||||||
|
|
||||||
block = bcoin.block.fromRaw(toString(args[0]), 'hex');
|
|
||||||
|
|
||||||
this.chain.add(block, function(err, total) {
|
|
||||||
if (err)
|
|
||||||
return callback(null, 'rejected');
|
|
||||||
callback(null, 'valid');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
RPC.prototype._hashps = function _hashps(lookup, height, callback) {
|
RPC.prototype._hashps = function _hashps(lookup, height, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var minTime, maxTime, pb0, time, workDiff, timeDiff, ps;
|
var minTime, maxTime, pb0, time, workDiff, timeDiff, ps;
|
||||||
|
|||||||
@ -40,6 +40,9 @@ function Miner(options) {
|
|||||||
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
||||||
this.version = null;
|
this.version = null;
|
||||||
|
|
||||||
|
if (typeof this.coinbaseFlags === 'string')
|
||||||
|
this.coinbaseFlags = new Buffer(this.coinbaseFlags, 'utf8');
|
||||||
|
|
||||||
this.pool = options.pool;
|
this.pool = options.pool;
|
||||||
this.chain = options.chain;
|
this.chain = options.chain;
|
||||||
this.logger = options.logger || this.chain.logger;
|
this.logger = options.logger || this.chain.logger;
|
||||||
@ -144,7 +147,8 @@ Miner.prototype._open = function open(callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
self.logger.info('Miner loaded (flags=%s).', self.coinbaseFlags);
|
self.logger.info('Miner loaded (flags=%s).',
|
||||||
|
self.coinbaseFlags.toString('utf8'));
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -57,6 +57,9 @@ function MinerBlock(options) {
|
|||||||
this.timeout = null;
|
this.timeout = null;
|
||||||
this.callback = null;
|
this.callback = null;
|
||||||
|
|
||||||
|
if (typeof this.coinbaseFlags === 'string')
|
||||||
|
this.coinbaseFlags = new Buffer(this.coinbaseFlags, 'utf8');
|
||||||
|
|
||||||
this.coinbase = new bcoin.tx();
|
this.coinbase = new bcoin.tx();
|
||||||
this.coinbase.mutable = true;
|
this.coinbase.mutable = true;
|
||||||
|
|
||||||
@ -417,7 +420,7 @@ MinerBlock.prototype.toRaw = function toRaw(writer) {
|
|||||||
p.writeU32(this.block.version);
|
p.writeU32(this.block.version);
|
||||||
p.writeU32(this.block.bits);
|
p.writeU32(this.block.bits);
|
||||||
p.writeVarBytes(this.address.toRaw());
|
p.writeVarBytes(this.address.toRaw());
|
||||||
p.writeVarString(this.coinbaseFlags, 'utf8');
|
p.writeVarBytes(this.coinbaseFlags);
|
||||||
p.writeU8(this.witness ? 1 : 0);
|
p.writeU8(this.witness ? 1 : 0);
|
||||||
p.writeVarint(this.block.txs.length - 1);
|
p.writeVarint(this.block.txs.length - 1);
|
||||||
|
|
||||||
@ -443,7 +446,7 @@ MinerBlock.fromRaw = function fromRaw(data) {
|
|||||||
var version = p.readU32();
|
var version = p.readU32();
|
||||||
var bits = p.readU32();
|
var bits = p.readU32();
|
||||||
var address = bcoin.address.fromRaw(p.readVarBytes());
|
var address = bcoin.address.fromRaw(p.readVarBytes());
|
||||||
var coinbaseFlags = p.readVarString('utf8');
|
var coinbaseFlags = p.readVarBytes();
|
||||||
var witness = p.readU8() === 1;
|
var witness = p.readU8() === 1;
|
||||||
var count = p.readVarint();
|
var count = p.readVarint();
|
||||||
var txs = [];
|
var txs = [];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user