miner/template: refactor options handling.
This commit is contained in:
parent
b0c2b89e79
commit
bfd7cc9266
@ -7,6 +7,8 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var consensus = require('../protocol/consensus');
|
||||
var BN = require('bn.js');
|
||||
|
||||
/**
|
||||
* @exports mining/common
|
||||
@ -18,7 +20,7 @@ var common = exports;
|
||||
* Constants
|
||||
*/
|
||||
|
||||
var DIFF_TARGET = 0x00000000ffff0000000000000000000000000000000000000000000000000000;
|
||||
var DIFF = 0x00000000ffff0000000000000000000000000000000000000000000000000000;
|
||||
var B192 = 0x1000000000000000000000000000000000000000000000000;
|
||||
var B128 = 0x100000000000000000000000000000000;
|
||||
var B64 = 0x10000000000000000;
|
||||
@ -30,7 +32,7 @@ var B0 = 0x1;
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.swap32 = function swap32(data) {
|
||||
common.swap32 = function swap32(data) {
|
||||
var i, field;
|
||||
|
||||
for (i = 0; i < data.length; i += 4) {
|
||||
@ -43,14 +45,13 @@ exports.swap32 = function swap32(data) {
|
||||
|
||||
/**
|
||||
* Swap 32 bit endianness of uint256 (hex).
|
||||
* @param {String} data
|
||||
* @param {String} str
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
exports.hswap32 = function hswap32(hex) {
|
||||
var data = new Buffer(hex, 'hex');
|
||||
exports.swap32(data)
|
||||
return data.toString('hex');
|
||||
common.swap32hex = function swap32hex(str) {
|
||||
var data = new Buffer(str, 'hex');
|
||||
return common.swap32(data).toString('hex');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -60,7 +61,7 @@ exports.hswap32 = function hswap32(hex) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.rcmp = function rcmp(a, b) {
|
||||
common.rcmp = function rcmp(a, b) {
|
||||
var i;
|
||||
|
||||
assert(a.length === b.length);
|
||||
@ -81,7 +82,7 @@ exports.rcmp = function rcmp(a, b) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.double256 = function double256(target) {
|
||||
common.double256 = function double256(target) {
|
||||
var n = 0;
|
||||
var hi, lo;
|
||||
|
||||
@ -113,12 +114,48 @@ exports.double256 = function double256(target) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.getDifficulty = function getDifficulty(target) {
|
||||
var d = DIFF_TARGET;
|
||||
var n = exports.double256(target);
|
||||
common.getDifficulty = function getDifficulty(target) {
|
||||
var d = DIFF;
|
||||
var n = common.double256(target);
|
||||
|
||||
if (n === 0)
|
||||
return d;
|
||||
|
||||
if (n > d)
|
||||
return d;
|
||||
|
||||
return Math.floor(d / n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get target from bits as a uint256le.
|
||||
* @param {Number} bits
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
common.getTarget = function getTarget(bits) {
|
||||
var target = consensus.fromCompact(bits);
|
||||
|
||||
if (target.isNeg())
|
||||
throw new Error('Target is negative.');
|
||||
|
||||
if (target.cmpn(0) === 0)
|
||||
throw new Error('Target is zero.');
|
||||
|
||||
return target.toArrayLike(Buffer, 'le', 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get bits from target.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
common.getBits = function getBits(data) {
|
||||
var target = new BN(data, 'le');
|
||||
|
||||
if (target.cmpn(0) === 0)
|
||||
throw new Error('Target is zero.');
|
||||
|
||||
return consensus.toCompact(target);
|
||||
};
|
||||
|
||||
@ -138,7 +138,7 @@ Miner.prototype._createBlock = co(function* createBlock(tip, address) {
|
||||
address: address,
|
||||
coinbaseFlags: this.options.coinbaseFlags,
|
||||
witness: this.chain.state.hasWitness(),
|
||||
halvingInterval: this.network.halvingInterval,
|
||||
interval: this.network.halvingInterval,
|
||||
weight: this.options.reservedWeight,
|
||||
sigops: this.options.reservedSigops
|
||||
});
|
||||
@ -146,11 +146,12 @@ Miner.prototype._createBlock = co(function* createBlock(tip, address) {
|
||||
this.assemble(attempt);
|
||||
|
||||
this.logger.debug(
|
||||
'Created miner block (height=%d, weight=%d, fees=%d, txs=%s).',
|
||||
'Created block template (height=%d, weight=%d, fees=%d, txs=%s, diff=%d).',
|
||||
attempt.height,
|
||||
attempt.weight,
|
||||
Amount.btc(attempt.fees),
|
||||
attempt.items.length + 1);
|
||||
attempt.items.length + 1,
|
||||
attempt.getDifficulty());
|
||||
|
||||
if (this.options.preverify) {
|
||||
block = attempt.toBlock();
|
||||
|
||||
@ -35,27 +35,127 @@ function BlockTemplate(options) {
|
||||
if (!(this instanceof BlockTemplate))
|
||||
return new BlockTemplate(options);
|
||||
|
||||
this.prevBlock = options.prevBlock;
|
||||
this.version = options.version;
|
||||
this.height = options.height;
|
||||
this.ts = options.ts;
|
||||
this.bits = options.bits;
|
||||
this.target = consensus.fromCompact(this.bits).toArrayLike(Buffer, 'le', 32);
|
||||
this.locktime = options.locktime;
|
||||
this.flags = options.flags;
|
||||
this.coinbaseFlags = options.coinbaseFlags;
|
||||
this.witness = options.witness;
|
||||
this.address = options.address;
|
||||
this.sigops = options.sigops;
|
||||
this.weight = options.weight;
|
||||
this.reward = consensus.getReward(this.height, options.halvingInterval);
|
||||
this.prevBlock = encoding.NULL_HASH;
|
||||
this.version = 1;
|
||||
this.height = 0;
|
||||
this.ts = 0;
|
||||
this.bits = 0;
|
||||
this.target = encoding.ZERO_HASH;
|
||||
this.locktime = 0;
|
||||
this.flags = 0;
|
||||
this.coinbaseFlags = DUMMY;
|
||||
this.witness = false;
|
||||
this.address = new Address();
|
||||
this.sigops = 400;
|
||||
this.weight = 4000;
|
||||
this.interval = 210000;
|
||||
this.fees = 0;
|
||||
this.tree = new MerkleTree();
|
||||
this.left = DUMMY;
|
||||
this.right = DUMMY;
|
||||
this.fees = 0;
|
||||
this.items = [];
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
* @returns {BlockTemplate}
|
||||
*/
|
||||
|
||||
BlockTemplate.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options);
|
||||
|
||||
if (options.prevBlock != null) {
|
||||
assert(typeof options.prevBlock === 'string');
|
||||
this.prevBlock = options.prevBlock;
|
||||
}
|
||||
|
||||
if (options.version != null) {
|
||||
assert(typeof options.version === 'number');
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(typeof options.height === 'number');
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
if (options.ts != null) {
|
||||
assert(typeof options.ts === 'number');
|
||||
this.ts = options.ts;
|
||||
}
|
||||
|
||||
if (options.bits != null)
|
||||
this.setBits(options.bits);
|
||||
|
||||
if (options.target != null)
|
||||
this.setTarget(options.target);
|
||||
|
||||
if (options.locktime != null) {
|
||||
assert(typeof options.locktime === 'number');
|
||||
this.locktime = options.locktime;
|
||||
}
|
||||
|
||||
if (options.flags != null) {
|
||||
assert(typeof options.flags === 'number');
|
||||
this.flags = options.flags;
|
||||
}
|
||||
|
||||
if (options.coinbaseFlags != null) {
|
||||
assert(Buffer.isBuffer(options.coinbaseFlags));
|
||||
this.coinbaseFlags = options.coinbaseFlags;
|
||||
}
|
||||
|
||||
if (options.witness != null) {
|
||||
assert(typeof options.witness === 'boolean');
|
||||
this.witness = options.witness;
|
||||
}
|
||||
|
||||
if (options.address != null)
|
||||
this.address.fromOptions(options.address);
|
||||
|
||||
if (options.sigops != null) {
|
||||
assert(typeof options.sigops === 'number');
|
||||
this.sigops = options.sigops;
|
||||
}
|
||||
|
||||
if (options.weight != null) {
|
||||
assert(typeof options.weight === 'number');
|
||||
this.weight = options.weight;
|
||||
}
|
||||
|
||||
if (options.interval != null) {
|
||||
assert(typeof options.interval === 'number');
|
||||
this.interval = options.interval;
|
||||
}
|
||||
|
||||
if (options.fees != null) {
|
||||
assert(typeof options.fees === 'number');
|
||||
this.fees = options.fees;
|
||||
}
|
||||
|
||||
if (options.items != null) {
|
||||
assert(Array.isArray(options.items));
|
||||
this.items = options.items;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate block template from options.
|
||||
* @param {Object} options
|
||||
* @returns {BlockTemplate}
|
||||
*/
|
||||
|
||||
BlockTemplate.fromOptions = function fromOptions(options) {
|
||||
return new BlockTemplate().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create witness commitment hash.
|
||||
* @returns {Buffer}
|
||||
@ -82,13 +182,36 @@ BlockTemplate.prototype.getWitnessHash = function getWitnessHash() {
|
||||
return crypto.hash256(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the target (bits).
|
||||
* @param {Number} bits
|
||||
*/
|
||||
|
||||
BlockTemplate.prototype.setBits = function setBits(bits) {
|
||||
assert(typeof bits === 'number');
|
||||
this.bits = bits;
|
||||
this.target = common.getTarget(bits);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the target (uint256le).
|
||||
* @param {Buffer} target
|
||||
*/
|
||||
|
||||
BlockTemplate.prototype.setTarget = function setTarget(target) {
|
||||
assert(Buffer.isBuffer(target));
|
||||
this.bits = common.getBits(target);
|
||||
this.target = target;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the block reward.
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
BlockTemplate.prototype.getReward = function getReward() {
|
||||
return this.reward + this.fees;
|
||||
var reward = consensus.getReward(this.height, this.interval);
|
||||
return reward + this.fees;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -707,7 +707,7 @@ describe('Chain', function() {
|
||||
it('should fail to connect bad amount', co(function* () {
|
||||
var job = yield cpu.createJob();
|
||||
|
||||
job.attempt.reward += 1;
|
||||
job.attempt.fees += 1;
|
||||
job.refresh();
|
||||
assert.equal(yield mineBlock(job), 'bad-cb-amount');
|
||||
}));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user