miner/template: refactor options handling.

This commit is contained in:
Christopher Jeffrey 2017-03-10 15:57:42 -08:00
parent b0c2b89e79
commit bfd7cc9266
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 193 additions and 32 deletions

View File

@ -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);
};

View File

@ -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();

View File

@ -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;
};
/**

View File

@ -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');
}));