From 023591978aca3bc8a85c618d4b628ca3899fb0c9 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 13 Mar 2017 19:54:21 -0700 Subject: [PATCH] rpc: fix wit commitment for getblocktemplate. --- lib/http/rpc.js | 2 + lib/mining/template.js | 99 +++++++++++++++++++++--------------------- lib/utils/util.js | 31 ++++++++++--- 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/lib/http/rpc.js b/lib/http/rpc.js index a378c1ca..1d5349cd 100644 --- a/lib/http/rpc.js +++ b/lib/http/rpc.js @@ -1307,6 +1307,8 @@ RPC.prototype._createTemplate = co(function* _createTemplate(version, coinbase, output = tx.outputs[tx.outputs.length - 1]; assert(output.script.isCommitment()); json.default_witness_commitment = output.script.toJSON(); + } else if (rules && rules.indexOf('segwit') !== -1) { + json.default_witness_commitment = attempt.getWitnessScript().toJSON(); } return json; diff --git a/lib/mining/template.js b/lib/mining/template.js index 37f4c898..16eb7129 100644 --- a/lib/mining/template.js +++ b/lib/mining/template.js @@ -52,6 +52,7 @@ function BlockTemplate(options) { this.interval = 210000; this.fees = 0; this.tree = new MerkleTree(); + this.commitment = DUMMY; this.left = DUMMY; this.right = DUMMY; this.items = []; @@ -188,6 +189,15 @@ BlockTemplate.prototype.getWitnessHash = function getWitnessHash() { return crypto.hash256(data); }; +/** + * Create witness commitment script. + * @returns {Script} + */ + +BlockTemplate.prototype.getWitnessScript = function getWitnessScript() { + return Script.fromCommitment(this.commitment); +}; + /** * Set the target (bits). * @param {Number} bits @@ -222,14 +232,15 @@ BlockTemplate.prototype.getReward = function getReward() { /** * Initialize the default coinbase. + * @param {Buffer} hash - Witness commitment hash. * @returns {TX} */ -BlockTemplate.prototype.createCoinbase = function createCoinbase() { +BlockTemplate.prototype.createCoinbase = function createCoinbase(hash) { var scale = consensus.WITNESS_SCALE_FACTOR; var cb = new TX(); var padding = 0; - var input, output, commit, hash; + var input, output, commit; // Coinbase input. input = new Input(); @@ -241,11 +252,11 @@ BlockTemplate.prototype.createCoinbase = function createCoinbase() { input.script.push(encoding.ZERO_HASH160); // Smaller nonce for good measure. - input.script.push(util.nonce().slice(0, 4)); + input.script.push(util.nonce(4)); // Extra nonce: incremented when // the nonce overflows. - input.script.push(extraNonce(0, 0)); + input.script.push(encoding.ZERO_U64); input.script.compile(); @@ -269,7 +280,6 @@ BlockTemplate.prototype.createCoinbase = function createCoinbase() { if (this.witness) { // Commitment output. commit = new Output(); - hash = this.getWitnessHash(); commit.script.fromCommitment(hash); cb.outputs.push(commit); } @@ -320,7 +330,8 @@ BlockTemplate.prototype.createCoinbase = function createCoinbase() { */ BlockTemplate.prototype.refresh = function refresh() { - var cb = this.createCoinbase(); + var hash = this.getWitnessHash(); + var cb = this.createCoinbase(hash); var raw = cb.toNormal(); var size = 0; var left, right; @@ -338,6 +349,7 @@ BlockTemplate.prototype.refresh = function refresh() { size += 4 + 4; // nonce1 + nonce2 right = raw.slice(size); + this.commitment = hash; this.left = left; this.right = right; this.tree = MerkleTree.fromItems(this.items); @@ -644,6 +656,38 @@ BlockEntry.fromEntry = function fromEntry(entry, attempt) { return item; }; +/* + * 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); +}; + /* * MerkleTree * @constructor @@ -743,49 +787,6 @@ MerkleTree.fromLeaves = function 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 - */ - -function extraNonce(nonce1, nonce2) { - var bw = new StaticWriter(8); - bw.writeU32BE(nonce1); - bw.writeU32BE(nonce2); - return bw.render(); -}; - /* * Expose */ diff --git a/lib/utils/util.js b/lib/utils/util.js index b5f8bed9..248e6e42 100644 --- a/lib/utils/util.js +++ b/lib/utils/util.js @@ -568,17 +568,34 @@ util.random = function random(min, max) { }; /** - * Create a 64 bit nonce. + * Create a 32 or 64 bit nonce. + * @param {Number} size * @returns {Buffer} */ -util.nonce = function _nonce() { - var nonce = new Buffer(8); - var a = util.random(0, 0x100000000); - var b = util.random(0, 0x100000000); +util.nonce = function _nonce(size) { + var n, nonce; - nonce.writeUInt32LE(a, 0, true); - nonce.writeUInt32LE(b, 4, true); + if (!size) + size = 8; + + switch (size) { + case 8: + nonce = new Buffer(8); + n = util.random(0, 0x100000000); + nonce.writeUInt32LE(n, 0, true); + n = util.random(0, 0x100000000); + nonce.writeUInt32LE(n, 4, true); + break; + case 4: + nonce = new Buffer(4); + n = util.random(0, 0x100000000); + nonce.writeUInt32LE(n, 0, true); + break; + default: + assert(false, 'Bad nonce size.'); + break; + } return nonce; };