mining: refactor proof handling.
This commit is contained in:
parent
b453898f6e
commit
b0c2b89e79
@ -915,7 +915,7 @@ RPC.prototype._submitWork = co(function* _submitWork(data) {
|
|||||||
var header = Headers.fromAbbr(data);
|
var header = Headers.fromAbbr(data);
|
||||||
var nonce = header.nonce;
|
var nonce = header.nonce;
|
||||||
var ts = header.ts;
|
var ts = header.ts;
|
||||||
var job, n1, n2, hash, block, entry;
|
var job, n1, n2, proof, block, entry;
|
||||||
|
|
||||||
if (!attempt)
|
if (!attempt)
|
||||||
return false;
|
return false;
|
||||||
@ -942,12 +942,12 @@ RPC.prototype._submitWork = co(function* _submitWork(data) {
|
|||||||
n1 = job.nonce1;
|
n1 = job.nonce1;
|
||||||
n2 = job.nonce2;
|
n2 = job.nonce2;
|
||||||
|
|
||||||
hash = attempt.hash(n1, n2, ts, nonce);
|
proof = attempt.getProof(n1, n2, ts, nonce);
|
||||||
|
|
||||||
if (!consensus.verifyPOW(hash, attempt.bits))
|
if (!proof.verify(attempt.target))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
block = attempt.commit(n1, n2, ts, nonce);
|
block = attempt.commit(proof);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
entry = yield this.chain.add(block);
|
entry = yield this.chain.add(block);
|
||||||
@ -983,12 +983,14 @@ RPC.prototype._createWork = co(function* _createWork() {
|
|||||||
var n1 = this.nonce1;
|
var n1 = this.nonce1;
|
||||||
var n2 = this.nonce2;
|
var n2 = this.nonce2;
|
||||||
var ts = attempt.ts;
|
var ts = attempt.ts;
|
||||||
var data, head;
|
var data, root, head;
|
||||||
|
|
||||||
data = new Buffer(128);
|
data = new Buffer(128);
|
||||||
data.fill(0);
|
data.fill(0);
|
||||||
|
|
||||||
head = attempt.getHeader(n1, n2, ts, 0);
|
root = attempt.getRoot(n1, n2);
|
||||||
|
head = attempt.getHeader(root, ts, 0);
|
||||||
|
|
||||||
head.copy(data, 0);
|
head.copy(data, 0);
|
||||||
|
|
||||||
data[80] = 0x80;
|
data[80] = 0x80;
|
||||||
|
|||||||
124
lib/mining/common.js
Normal file
124
lib/mining/common.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*!
|
||||||
|
* common.js - mining utils
|
||||||
|
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @exports mining/common
|
||||||
|
*/
|
||||||
|
|
||||||
|
var common = exports;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DIFF_TARGET = 0x00000000ffff0000000000000000000000000000000000000000000000000000;
|
||||||
|
var B192 = 0x1000000000000000000000000000000000000000000000000;
|
||||||
|
var B128 = 0x100000000000000000000000000000000;
|
||||||
|
var B64 = 0x10000000000000000;
|
||||||
|
var B0 = 0x1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap 32 bit endianness of uint256.
|
||||||
|
* @param {Buffer} data
|
||||||
|
* @returns {Buffer}
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.swap32 = function swap32(data) {
|
||||||
|
var i, field;
|
||||||
|
|
||||||
|
for (i = 0; i < data.length; i += 4) {
|
||||||
|
field = data.readUInt32LE(i, true);
|
||||||
|
data.writeUInt32BE(field, i, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap 32 bit endianness of uint256 (hex).
|
||||||
|
* @param {String} data
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.hswap32 = function hswap32(hex) {
|
||||||
|
var data = new Buffer(hex, 'hex');
|
||||||
|
exports.swap32(data)
|
||||||
|
return data.toString('hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two uint256le's.
|
||||||
|
* @param {Buffer} a
|
||||||
|
* @param {Buffer} b
|
||||||
|
* @returns {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.rcmp = function rcmp(a, b) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
assert(a.length === b.length);
|
||||||
|
|
||||||
|
for (i = a.length - 1; i >= 0; i--) {
|
||||||
|
if (a[i] < b[i])
|
||||||
|
return -1;
|
||||||
|
if (a[i] > b[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a uint256le to a double.
|
||||||
|
* @param {Buffer} target
|
||||||
|
* @returns {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.double256 = function double256(target) {
|
||||||
|
var n = 0;
|
||||||
|
var hi, lo;
|
||||||
|
|
||||||
|
assert(target.length === 32);
|
||||||
|
|
||||||
|
hi = target.readUInt32LE(28, true);
|
||||||
|
lo = target.readUInt32LE(24, true);
|
||||||
|
n += (hi * 0x100000000 + lo) * B192;
|
||||||
|
|
||||||
|
hi = target.readUInt32LE(20, true);
|
||||||
|
lo = target.readUInt32LE(16, true);
|
||||||
|
n += (hi * 0x100000000 + lo) * B128;
|
||||||
|
|
||||||
|
hi = target.readUInt32LE(12, true);
|
||||||
|
lo = target.readUInt32LE(8, true);
|
||||||
|
n += (hi * 0x100000000 + lo) * B64;
|
||||||
|
|
||||||
|
hi = target.readUInt32LE(4, true);
|
||||||
|
lo = target.readUInt32LE(0, true);
|
||||||
|
n += (hi * 0x100000000 + lo) * B0;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate mining difficulty
|
||||||
|
* from little-endian target.
|
||||||
|
* @param {Buffer} target
|
||||||
|
* @returns {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.getDifficulty = function getDifficulty(target) {
|
||||||
|
var d = DIFF_TARGET;
|
||||||
|
var n = exports.double256(target);
|
||||||
|
if (n === 0)
|
||||||
|
return d;
|
||||||
|
if (n > d)
|
||||||
|
return d;
|
||||||
|
return Math.floor(d / n);
|
||||||
|
};
|
||||||
@ -279,7 +279,7 @@ CPUMiner.prototype.notifyEntry = function notifyEntry() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype.findNonce = function findNonce(job) {
|
CPUMiner.prototype.findNonce = function findNonce(job) {
|
||||||
var data = job.getHeader(0);
|
var data = job.getHeader();
|
||||||
var target = job.attempt.target;
|
var target = job.attempt.target;
|
||||||
var interval = CPUMiner.INTERVAL;
|
var interval = CPUMiner.INTERVAL;
|
||||||
var min = 0;
|
var min = 0;
|
||||||
@ -309,7 +309,7 @@ CPUMiner.prototype.findNonce = function findNonce(job) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype.findNonceAsync = co(function* findNonceAsync(job) {
|
CPUMiner.prototype.findNonceAsync = co(function* findNonceAsync(job) {
|
||||||
var data = job.getHeader(0);
|
var data = job.getHeader();
|
||||||
var target = job.attempt.target;
|
var target = job.attempt.target;
|
||||||
var interval = CPUMiner.INTERVAL;
|
var interval = CPUMiner.INTERVAL;
|
||||||
var min = 0;
|
var min = 0;
|
||||||
@ -439,12 +439,14 @@ function CPUJob(miner, attempt) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CPUJob.prototype.getHeader = function getHeader(nonce) {
|
CPUJob.prototype.getHeader = function getHeader() {
|
||||||
var attempt = this.attempt;
|
var attempt = this.attempt;
|
||||||
var n1 = this.nonce1;
|
var n1 = this.nonce1;
|
||||||
var n2 = this.nonce2;
|
var n2 = this.nonce2;
|
||||||
var ts = attempt.ts;
|
var ts = attempt.ts;
|
||||||
return this.attempt.getHeader(n1, n2, ts, nonce);
|
var root = attempt.getRoot(n1, n2);
|
||||||
|
var data = attempt.getHeader(root, ts, 0);
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -458,11 +460,14 @@ CPUJob.prototype.commit = function commit(nonce) {
|
|||||||
var n1 = this.nonce1;
|
var n1 = this.nonce1;
|
||||||
var n2 = this.nonce2;
|
var n2 = this.nonce2;
|
||||||
var ts = attempt.ts;
|
var ts = attempt.ts;
|
||||||
|
var proof;
|
||||||
|
|
||||||
assert(!this.committed, 'Job already committed.');
|
assert(!this.committed, 'Job already committed.');
|
||||||
this.committed = true;
|
this.committed = true;
|
||||||
|
|
||||||
return this.attempt.commit(n1, n2, ts, nonce);
|
proof = attempt.getProof(n1, n2, ts, nonce);
|
||||||
|
|
||||||
|
return attempt.commit(proof);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
exports.BlockTemplate = require('./template');
|
exports.BlockTemplate = require('./template');
|
||||||
|
exports.common = require('./common');
|
||||||
exports.CPUMiner = require('./cpuminer');
|
exports.CPUMiner = require('./cpuminer');
|
||||||
exports.mine = require('./mine');
|
exports.mine = require('./mine');
|
||||||
exports.Miner = require('./miner');
|
exports.Miner = require('./miner');
|
||||||
|
|||||||
@ -21,6 +21,7 @@ var consensus = require('../protocol/consensus');
|
|||||||
var policy = require('../protocol/policy');
|
var policy = require('../protocol/policy');
|
||||||
var encoding = require('../utils/encoding');
|
var encoding = require('../utils/encoding');
|
||||||
var CoinView = require('../coins/coinview');
|
var CoinView = require('../coins/coinview');
|
||||||
|
var common = require('./common');
|
||||||
var DUMMY = new Buffer(0);
|
var DUMMY = new Buffer(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,7 +61,7 @@ function BlockTemplate(options) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.commitmentHash = function commitmentHash() {
|
BlockTemplate.prototype.getWitnessHash = function getWitnessHash() {
|
||||||
var nonce = encoding.ZERO_HASH;
|
var nonce = encoding.ZERO_HASH;
|
||||||
var leaves = [];
|
var leaves = [];
|
||||||
var i, item, root, data;
|
var i, item, root, data;
|
||||||
@ -139,7 +140,7 @@ BlockTemplate.prototype.createCoinbase = function createCoinbase() {
|
|||||||
if (this.witness) {
|
if (this.witness) {
|
||||||
// Commitment output.
|
// Commitment output.
|
||||||
commit = new Output();
|
commit = new Output();
|
||||||
hash = this.commitmentHash();
|
hash = this.getWitnessHash();
|
||||||
commit.script.fromCommitment(hash);
|
commit.script.fromCommitment(hash);
|
||||||
cb.outputs.push(commit);
|
cb.outputs.push(commit);
|
||||||
}
|
}
|
||||||
@ -220,7 +221,7 @@ BlockTemplate.prototype.refresh = function refresh() {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.getCoinbase = function getCoinbase(nonce1, nonce2) {
|
BlockTemplate.prototype.getRawCoinbase = function getRawCoinbase(nonce1, nonce2) {
|
||||||
var size = 0;
|
var size = 0;
|
||||||
var bw;
|
var bw;
|
||||||
|
|
||||||
@ -245,23 +246,21 @@ BlockTemplate.prototype.getCoinbase = function getCoinbase(nonce1, nonce2) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.getRoot = function getRoot(nonce1, nonce2) {
|
BlockTemplate.prototype.getRoot = function getRoot(nonce1, nonce2) {
|
||||||
var raw = this.getCoinbase(nonce1, nonce2);
|
var raw = this.getRawCoinbase(nonce1, nonce2);
|
||||||
var hash = crypto.hash256(raw);
|
var hash = crypto.hash256(raw);
|
||||||
return this.tree.withFirst(hash);
|
return this.tree.withFirst(hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create raw block header with given parameters.
|
* Create raw block header with given parameters.
|
||||||
* @param {Number} nonce1
|
* @param {Buffer} root
|
||||||
* @param {Number} nonce2
|
|
||||||
* @param {Number} ts
|
* @param {Number} ts
|
||||||
* @param {Number} nonce
|
* @param {Number} nonce
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.getHeader = function getHeader(nonce1, nonce2, ts, nonce) {
|
BlockTemplate.prototype.getHeader = function getHeader(root, ts, nonce) {
|
||||||
var bw = new StaticWriter(80);
|
var bw = new StaticWriter(80);
|
||||||
var root = this.getRoot(nonce1, nonce2);
|
|
||||||
|
|
||||||
bw.writeU32(this.version);
|
bw.writeU32(this.version);
|
||||||
bw.writeHash(this.prevBlock);
|
bw.writeHash(this.prevBlock);
|
||||||
@ -274,17 +273,19 @@ BlockTemplate.prototype.getHeader = function getHeader(nonce1, nonce2, ts, nonce
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate block hash with given parameters.
|
* Calculate proof with given parameters.
|
||||||
* @param {Number} nonce1
|
* @param {Number} nonce1
|
||||||
* @param {Number} nonce2
|
* @param {Number} nonce2
|
||||||
* @param {Number} ts
|
* @param {Number} ts
|
||||||
* @param {Number} nonce
|
* @param {Number} nonce
|
||||||
* @returns {Buffer}
|
* @returns {BlockProof}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.hash = function hash(nonce1, nonce2, ts, nonce) {
|
BlockTemplate.prototype.getProof = function getProof(nonce1, nonce2, ts, nonce) {
|
||||||
var data = this.getHeader(nonce1, nonce2, ts, nonce);
|
var root = this.getRoot(nonce1, nonce2);
|
||||||
return crypto.hash256(data);
|
var data = this.getHeader(root, ts, nonce);
|
||||||
|
var hash = crypto.hash256(data);
|
||||||
|
return new BlockProof(hash, root, nonce1, nonce2, ts, nonce);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -294,8 +295,8 @@ BlockTemplate.prototype.hash = function hash(nonce1, nonce2, ts, nonce) {
|
|||||||
* @returns {TX}
|
* @returns {TX}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.coinbase = function coinbase(nonce1, nonce2) {
|
BlockTemplate.prototype.getCoinbase = function getCoinbase(nonce1, nonce2) {
|
||||||
var raw = this.getCoinbase(nonce1, nonce2);
|
var raw = this.getRawCoinbase(nonce1, nonce2);
|
||||||
var tx = TX.fromRaw(raw);
|
var tx = TX.fromRaw(raw);
|
||||||
var input;
|
var input;
|
||||||
|
|
||||||
@ -310,19 +311,19 @@ BlockTemplate.prototype.coinbase = function coinbase(nonce1, nonce2) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create block from given parameters.
|
* Create block from calculated proof.
|
||||||
* @param {Number} nonce1
|
* @param {BlockProof} proof
|
||||||
* @param {Number} nonce2
|
|
||||||
* @param {Number} ts
|
|
||||||
* @param {Number} nonce
|
|
||||||
* @returns {Block}
|
* @returns {Block}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.commit = function commit(nonce1, nonce2, ts, nonce) {
|
BlockTemplate.prototype.commit = function commit(proof) {
|
||||||
var tx = this.coinbase(nonce1, nonce2);
|
var root = proof.root;
|
||||||
var root = this.tree.withFirst(tx.hash());
|
var n1 = proof.nonce1;
|
||||||
|
var n2 = proof.nonce2;
|
||||||
|
var ts = proof.ts;
|
||||||
|
var nonce = proof.nonce;
|
||||||
var block = new Block();
|
var block = new Block();
|
||||||
var i, item;
|
var i, tx, item;
|
||||||
|
|
||||||
block.version = this.version;
|
block.version = this.version;
|
||||||
block.prevBlock = this.prevBlock;
|
block.prevBlock = this.prevBlock;
|
||||||
@ -331,6 +332,8 @@ BlockTemplate.prototype.commit = function commit(nonce1, nonce2, ts, nonce) {
|
|||||||
block.bits = this.bits;
|
block.bits = this.bits;
|
||||||
block.nonce = nonce;
|
block.nonce = nonce;
|
||||||
|
|
||||||
|
tx = this.getCoinbase(n1, n2);
|
||||||
|
|
||||||
block.txs.push(tx);
|
block.txs.push(tx);
|
||||||
|
|
||||||
for (i = 0; i < this.items.length; i++) {
|
for (i = 0; i < this.items.length; i++) {
|
||||||
@ -348,7 +351,7 @@ BlockTemplate.prototype.commit = function commit(nonce1, nonce2, ts, nonce) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.toCoinbase = function toCoinbase() {
|
BlockTemplate.prototype.toCoinbase = function toCoinbase() {
|
||||||
return this.coinbase(0, 0);
|
return this.getCoinbase(0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -358,7 +361,17 @@ BlockTemplate.prototype.toCoinbase = function toCoinbase() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.toBlock = function toBlock() {
|
BlockTemplate.prototype.toBlock = function toBlock() {
|
||||||
return this.commit(0, 0, this.ts, 0);
|
var proof = this.getProof(0, 0, this.ts, 0);
|
||||||
|
return this.commit(proof);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the target difficulty.
|
||||||
|
* @returns {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
BlockTemplate.prototype.getDifficulty = function getDifficulty() {
|
||||||
|
return common.getDifficulty(this.target);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -601,6 +614,38 @@ MerkleTree.fromLeaves = function fromLeaves(leaves) {
|
|||||||
return new MerkleTree().fromLeaves(leaves);
|
return new MerkleTree().fromLeaves(leaves);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BlockProof
|
||||||
|
* @constructor
|
||||||
|
* @param {Hash} hash
|
||||||
|
* @param {Hash} root
|
||||||
|
* @param {Number} nonce1
|
||||||
|
* @param {Number} nonce2
|
||||||
|
* @param {Number} ts
|
||||||
|
* @param {Number} nonce
|
||||||
|
*/
|
||||||
|
|
||||||
|
function BlockProof(hash, root, nonce1, nonce2, ts, nonce) {
|
||||||
|
this.hash = hash;
|
||||||
|
this.root = root;
|
||||||
|
this.nonce1 = nonce1;
|
||||||
|
this.nonce2 = nonce2;
|
||||||
|
this.ts = ts;
|
||||||
|
this.nonce = nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockProof.prototype.rhash = function rhash() {
|
||||||
|
return util.revHex(this.hash.toString('hex'));
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockProof.prototype.verify = function verify(target) {
|
||||||
|
return common.rcmp(this.hash, target) <= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockProof.prototype.getDifficulty = function getDifficulty() {
|
||||||
|
return common.getDifficulty(this.hash);
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user