diff --git a/README.md b/README.md index c6a6abf2c..5a276efa5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 4.6.0 +Zcash 4.6.0-1 =========== diff --git a/configure.ac b/configure.ac index d2dbb6ae7..4162fa308 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 4) define(_CLIENT_VERSION_MINOR, 6) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_BUILD, 51) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 3caf05a22..84754abf5 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (4.6.0+1) stable; urgency=medium + + * 4.6.0-1 release. + + -- Electric Coin Company Wed, 05 Jan 2022 20:18:43 +0000 + zcash (4.6.0) stable; urgency=medium * 4.6.0 release. diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 9f72e1d22..69db0cca2 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-4.6.0" +name: "zcash-4.6.0-1" enable_cache: true distro: "debian" suites: diff --git a/doc/authors.md b/doc/authors.md index 9ca489b67..c7d8886dd 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,7 +1,7 @@ Zcash Contributors ================== -Jack Grigg (1124) +Jack Grigg (1127) Simon Liu (460) Sean Bowe (367) Daira Hopwood (270) @@ -16,7 +16,7 @@ Jonas Schnelli (89) Jay Graber (89) Marco Falke (82) Cory Fields (75) -Larry Ruane (69) +Larry Ruane (72) Ying Tong Lai (56) Nathan Wilcox (56) Matt Corallo (52) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 0290a4767..51ebcfcf1 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. -.TH ZCASH-CLI "1" "December 2021" "zcash-cli v4.6.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH ZCASH-CLI "1" "January 2022" "zcash-cli v4.6.0-1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v4.6.0 +zcash-cli \- manual page for zcash-cli v4.6.0-1 .SH DESCRIPTION -Zcash RPC client version v4.6.0 +Zcash RPC client version v4.6.0\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 098737863..ddb563fcf 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. -.TH ZCASH-TX "1" "December 2021" "zcash-tx v4.6.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH ZCASH-TX "1" "January 2022" "zcash-tx v4.6.0-1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v4.6.0 +zcash-tx \- manual page for zcash-tx v4.6.0-1 .SH DESCRIPTION -Zcash zcash\-tx utility version v4.6.0 +Zcash zcash\-tx utility version v4.6.0\-1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index ab62ba23e..cb512e41c 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. -.TH ZCASHD "1" "December 2021" "zcashd v4.6.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH ZCASHD "1" "January 2022" "zcashd v4.6.0-1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v4.6.0 +zcashd \- manual page for zcashd v4.6.0-1 .SH DESCRIPTION -Zcash Daemon version v4.6.0 +Zcash Daemon version v4.6.0\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -84,7 +84,7 @@ Keep at most unconnectable transactions in memory (default: 100) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-8\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-16\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR diff --git a/doc/release-notes/release-notes-4.6.0-1.md b/doc/release-notes/release-notes-4.6.0-1.md new file mode 100644 index 000000000..975376aa1 --- /dev/null +++ b/doc/release-notes/release-notes-4.6.0-1.md @@ -0,0 +1,37 @@ +`getblocktemplate` regression fix +================================= + +We added support for the NU5 consensus rules in v4.5.0, which alters the +block header to contain a `hashBlockCommitments` value instead of the +chain history root. However, the output of `getblocktemplate` wasn't +returning this value; once NU5 activated, the `blockcommitmentshash` +field was being set to "null" (all-zeroes). + +In v4.6.0 we added full NU5 support to `getblocktemplate`, by adding a +`defaultroots` field that gave default values for `hashBlockCommitments` +and the components required to derive it. However, in doing so we +introduced a regression in the (now-deprecated) legacy fields, where +prior to NU5 activation they contained nonsense. + +This release fixes the output of `getblocktemplate` to have the intended +semantics for all fields: + +- The `blockcommitmentshash` and `authdataroot` fields in `defaultroots` + are now omitted from block templates for heights before NU5 activation. + +- The legacy fields now always contain the default value to be placed + into the block header (regaining their previous semantics). + +Changelog +========= + +Jack Grigg (3): + rpc: Fix regression in getblocktemplate output + make-release.py: Versioning changes for 4.6.0-1. + make-release.py: Updated manpages for 4.6.0-1. + +Larry Ruane (3): + assert that the return value of submitblock is None + test: check getblocktemplate output before and after NU5 + test: Fix ZIP 244 implementation + diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index 324e4e431..da3f638f9 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -8,11 +8,8 @@ import codecs from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, - BLOSSOM_BRANCH_ID, CANOPY_BRANCH_ID, - HEARTWOOD_BRANCH_ID, NU5_BRANCH_ID, - get_coinbase_address, hex_str_to_bytes, nuparams, start_nodes, @@ -20,8 +17,9 @@ from test_framework.util import ( ) from test_framework.mininode import ( CTransaction, + uint256_from_str, ) -from test_framework.blocktools import( +from test_framework.blocktools import ( create_block ) from decimal import Decimal @@ -39,48 +37,57 @@ class GetBlockTemplateTest(BitcoinTestFramework): def setup_network(self, split=False): args = [ - nuparams(BLOSSOM_BRANCH_ID, 1), - nuparams(HEARTWOOD_BRANCH_ID, 1), - nuparams(CANOPY_BRANCH_ID, 1), - nuparams(NU5_BRANCH_ID, 1), + nuparams(CANOPY_BRANCH_ID, 115), + nuparams(NU5_BRANCH_ID, 130), ] self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [args] * self.num_nodes) - self.is_network_split=False - self.sync_all() + self.is_network_split = False + self.node = self.nodes[0] - def run_test(self): - node = self.nodes[0] - print("Generating blocks") - node.generate(110) + def add_nu5_v4_tx_to_mempool(self): + node = self.node + # sprout to transparent (v4) + recipients = [{"address": self.transparent_addr, "amount": Decimal('0.1')}] + myopid = node.z_sendmany(self.sprout_addr, recipients) + wait_and_assert_operationid_status(node, myopid) - print("Add transactions to the mempool so they will be in the template") - # This part of the test should be improved, submit some V4 transactions - # and varying combinations of shielded and transparent - for _ in range(5): - # submit a tx with a shielded output - taddr0 = get_coinbase_address(node) - zaddr = node.z_getnewaddress('sapling') - recipients = [{"address": zaddr, "amount": Decimal('0.1')}] - myopid = node.z_sendmany(taddr0, recipients, 1, 0) - wait_and_assert_operationid_status(node, myopid) + def add_transparent_tx_to_mempool(self): + node = self.node + # transparent to transparent (v5 after nu5) + outputs = {self.transparent_addr: 0.1} + node.sendmany('', outputs) - # submit a tx with a transparent output - outputs = {node.getnewaddress():0.2} - node.sendmany('', outputs) + def gbt_submitblock(self, nu5_active): + node = self.node + mempool_tx_list = node.getrawmempool() - print("Getting block template") gbt = node.getblocktemplate() + # make sure no transactions were left out (or added) + assert_equal(len(mempool_tx_list), len(gbt['transactions'])) + assert_equal(set(mempool_tx_list), set([tx['hash'] for tx in gbt['transactions']])) + prevhash = int(gbt['previousblockhash'], 16) - blockcommitmentshash = int(gbt['defaultroots']['blockcommitmentshash'], 16) nTime = gbt['mintime'] nBits = int(gbt['bits'], 16) + if nu5_active: + blockcommitmentshash = int(gbt['defaultroots']['blockcommitmentshash'], 16) + else: + blockcommitmentshash = int(gbt['defaultroots']['chainhistoryroot'], 16) + assert 'blockcommitmentshash' not in gbt['defaultroots'] + # Confirm that the legacy fields match this default value. + assert_equal(blockcommitmentshash, int(gbt['blockcommitmentshash'], 16)) + assert_equal(blockcommitmentshash, int(gbt['lightclientroothash'], 16)) + assert_equal(blockcommitmentshash, int(gbt['finalsaplingroothash'], 16)) + f = BytesIO(hex_str_to_bytes(gbt['coinbasetxn']['data'])) coinbase = CTransaction() coinbase.deserialize(f) + coinbase.calc_sha256() + assert_equal(coinbase.hash, gbt['coinbasetxn']['hash']) + assert_equal(coinbase.auth_digest_hex, gbt['coinbasetxn']['authdigest']) - print("Creating_block from template (simulating a miner)") block = create_block(prevhash, coinbase, nTime, nBits, blockcommitmentshash) # copy the non-coinbase transactions from the block template to the block @@ -88,18 +95,92 @@ class GetBlockTemplateTest(BitcoinTestFramework): f = BytesIO(hex_str_to_bytes(gbt_tx['data'])) tx = CTransaction() tx.deserialize(f) + tx.calc_sha256() + assert_equal(tx.auth_digest_hex, node.getrawtransaction(tx.hash, 1)['authdigest']) block.vtx.append(tx) block.hashMerkleRoot = int(gbt['defaultroots']['merkleroot'], 16) assert_equal(block.hashMerkleRoot, block.calc_merkle_root(), "merkleroot") assert_equal(len(block.vtx), len(gbt['transactions']) + 1, "number of transactions") assert_equal(block.hashPrevBlock, int(gbt['previousblockhash'], 16), "prevhash") + if nu5_active: + assert_equal(uint256_from_str(block.calc_auth_data_root()), int(gbt['defaultroots']['authdataroot'], 16)) + else: + assert 'authdataroot' not in gbt['defaultroots'] block.solve() - block = block.serialize() - block = codecs.encode(block, 'hex_codec') + block.calc_sha256() - print("Submitting block") - submitblock_reply = node.submitblock(block) + submitblock_reply = node.submitblock(codecs.encode(block.serialize(), 'hex_codec')) assert_equal(None, submitblock_reply) + assert_equal(block.hash, node.getbestblockhash()) + # Wait until the wallet has been notified of all blocks, so that it doesn't try to + # double-spend transparent coins in subsequent test phases. + self.sync_all() + + def run_test(self): + node = self.node + + # Generate Sprout funds before Canopy activates; using the Sprout address will + # force the generation of v4 transactions from NU5. + print("Generating pre-Canopy blocks to create sprout funds") + # coinbase only becomes mature after 100 blocks, so make one mature. + node.generate(105) + + self.sprout_addr = node.z_getnewaddress('sprout') + myopid = node.z_shieldcoinbase('*', self.sprout_addr)['opid'] + wait_and_assert_operationid_status(node, myopid) + + self.transparent_addr = node.getnewaddress() + node.generate(15) + + # at height 120, NU5 is not active + assert_equal(node.getblockchaininfo()['upgrades']['37519621']['status'], 'pending') + + print("Testing getblocktemplate for pre-NU5") + + # Only the coinbase; this covers the case where the Merkle root + # is equal to the coinbase txid. + print("- only coinbase") + self.gbt_submitblock(False) + + # Adding one transaction triggering a single Merkle digest. + print("- one transaction (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(False) + + # Adding two transactions to trigger hash Merkle root edge case. + print("- two transactions (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(False) + + # Activate NU5, repeat the above cases + node.generate(7) + assert_equal(node.getblockchaininfo()['upgrades']['37519621']['status'], 'active') + + print("Testing getblocktemplate for post-NU5") + + # Only the coinbase; this covers the case where the block authdata root + # is equal to the coinbase authdata + print("- only coinbase") + self.gbt_submitblock(True) + + # Adding one transaction triggering a single Merkle digest. + print("- one transaction (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(True) + + # Adding two transactions to trigger hash Merkle root edge case. + print("- two transactions (plus coinbase)") + self.add_transparent_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(True) + + # Adding both v4 and v5 to cover legacy auth digest. + print("- both v4 and v5 transactions (plus coinbase)") + self.add_nu5_v4_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.add_transparent_tx_to_mempool() + self.gbt_submitblock(True) if __name__ == '__main__': diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 11635f838..2c51f4421 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1126,11 +1126,14 @@ class CTransaction(object): if self.nVersion >= 5: from . import zip244 txid = zip244.txid_digest(self) + self.auth_digest = zip244.auth_digest(self) else: txid = hash256(self.serialize()) + self.auth_digest = b'\xFF'*32 if self.sha256 is None: self.sha256 = uint256_from_str(txid) self.hash = encode(txid[::-1], 'hex_codec').decode('ascii') + self.auth_digest_hex = encode(self.auth_digest[::-1], 'hex_codec').decode('ascii') def is_valid(self): self.calc_sha256() @@ -1263,6 +1266,27 @@ class CBlock(CBlockHeader): hashes = newhashes return uint256_from_str(hashes[0]) + def calc_auth_data_root(self): + hashes = [] + nleaves = 0 + for tx in self.vtx: + tx.calc_sha256() + hashes.append(tx.auth_digest) + nleaves += 1 + # Continue adding leaves (of zeros) until reaching a power of 2 + while nleaves & (nleaves-1) > 0: + hashes.append(b'\x00'*32) + nleaves += 1 + while len(hashes) > 1: + newhashes = [] + for i in range(0, len(hashes), 2): + digest = blake2b(digest_size=32, person=b'ZcashAuthDatHash') + digest.update(hashes[i]) + digest.update(hashes[i+1]) + newhashes.append(digest.digest()) + hashes = newhashes + return hashes[0] + def is_valid(self, n=48, k=5): # H(I||... digest = blake2b(digest_size=(512//n)*n//8, person=zcash_person(n, k)) diff --git a/qa/rpc-tests/test_framework/zip244.py b/qa/rpc-tests/test_framework/zip244.py index adbfbda59..f9cd5ceee 100644 --- a/qa/rpc-tests/test_framework/zip244.py +++ b/qa/rpc-tests/test_framework/zip244.py @@ -15,7 +15,7 @@ import struct from pyblake2 import blake2b -from .mininode import ser_uint256 +from .mininode import ser_string, ser_uint256 from .script import ( SIGHASH_ANYONECANPAY, SIGHASH_NONE, @@ -41,7 +41,7 @@ def transparent_digest(tx): def transparent_scripts_digest(tx): digest = blake2b(digest_size=32, person=b'ZTxAuthTransHash') for x in tx.vin: - digest.update(bytes(x.scriptSig)) + digest.update(ser_string(x.scriptSig)) return digest.digest() # Sapling @@ -288,7 +288,7 @@ def outputs_sig_digest(tx, nHashType, txin): def txin_sig_digest(tx, txin): digest = blake2b(digest_size=32, person=b'Zcash___TxInHash') digest.update(bytes(tx.vin[txin.nIn].prevout)) - digest.update(bytes(txin.scriptCode)) + digest.update(ser_string(txin.scriptCode)) digest.update(struct.pack('hashPrevBlock = pindexPrev->GetBlockHash(); if (chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_NU5)) { // hashBlockCommitments depends on the block transactions, so we have to - // update it whenever the coinbase transaction changes. Leave it unset here, - // like hashMerkleRoot, and instead cache what we will need to calculate it. + // update it whenever the coinbase transaction changes. + // + // - For the internal miner (either directly or via the `generate` RPC), this + // will occur in `IncrementExtraNonce()`, like for `hashMerkleRoot`. + // - For `getblocktemplate`, we have two sets of fields to handle: + // - The `defaultroots` fields, which contain both the default value (if + // nothing in the template is altered), and the roots that can be used to + // recalculate it (if some or all of the template is altered). + // - The legacy `finalsaplingroothash`, `lightclientroothash`, and + // `blockcommitmentshash` fields, which had the semantics of "place this + // value into the block header and things will work" (except for in + // v4.6.0 where they were accidentally set to always be the NU5 value). + // + // To accommodate all use cases, we calculate the `hashBlockCommitments` + // default value here (unlike `hashMerkleRoot`), and additionally cache the + // values necessary to recalculate it. pblocktemplate->hashChainHistoryRoot = view.GetHistoryRoot(prevConsensusBranchId); + pblocktemplate->hashAuthDataRoot = pblock->BuildAuthDataMerkleTree(); + pblock->hashBlockCommitments = DeriveBlockCommitmentsHash( + pblocktemplate->hashChainHistoryRoot, + pblocktemplate->hashAuthDataRoot); } else if (IsActivationHeight(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_HEARTWOOD)) { + pblocktemplate->hashChainHistoryRoot.SetNull(); + pblocktemplate->hashAuthDataRoot.SetNull(); pblock->hashBlockCommitments.SetNull(); } else if (chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_HEARTWOOD)) { - pblock->hashBlockCommitments = view.GetHistoryRoot(prevConsensusBranchId); + pblocktemplate->hashChainHistoryRoot = view.GetHistoryRoot(prevConsensusBranchId); + pblocktemplate->hashAuthDataRoot.SetNull(); + pblock->hashBlockCommitments = pblocktemplate->hashChainHistoryRoot; } else { + pblocktemplate->hashChainHistoryRoot.SetNull(); + pblocktemplate->hashAuthDataRoot.SetNull(); pblock->hashBlockCommitments = sapling_tree.root(); } UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); @@ -727,9 +751,10 @@ void IncrementExtraNonce( pblock->vtx[0] = txCoinbase; pblock->hashMerkleRoot = pblock->BuildMerkleTree(); if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_NU5)) { + pblocktemplate->hashAuthDataRoot = pblock->BuildAuthDataMerkleTree(); pblock->hashBlockCommitments = DeriveBlockCommitmentsHash( pblocktemplate->hashChainHistoryRoot, - pblock->BuildAuthDataMerkleTree()); + pblocktemplate->hashAuthDataRoot); } } diff --git a/src/miner.h b/src/miner.h index 9b76ec6ba..52ac1a29d 100644 --- a/src/miner.h +++ b/src/miner.h @@ -110,6 +110,10 @@ struct CBlockTemplate // Cached whenever we update `block`, so we can update hashBlockCommitments // when we change the coinbase transaction. uint256 hashChainHistoryRoot; + // Cached whenever we update `block`, so we can return it from `getblocktemplate` + // (enabling the caller to update `hashBlockCommitments` when they change + // `hashPrevBlock`). + uint256 hashAuthDataRoot; std::vector vTxFees; std::vector vTxSigOps; }; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 48e0d6932..c9f6fc73d 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -454,9 +454,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) " \"finalsaplingroothash\" : \"xxxx\", (string) (DEPRECATED) The hash of the light client root field in the block header\n" " \"defaultroots\" : { (json object) root hashes that need to be recomputed if the transaction set is modified\n" " \"merkleroot\" : \"xxxx\" (string) The hash of the transactions in the block header\n" - " \"authdataroot\" : \"xxxx\" (string) The hash of the authorizing data merkel tree\n" " \"chainhistoryroot\" : \"xxxx\" (string) The hash of the chain history\n" - " \"blockcommitmentshash\" : \"xxxx\" (string) The hash of the block commitments field in the block header\n" + " \"authdataroot\" : \"xxxx\" (string) (From NU5) The hash of the authorizing data merkel tree\n" + " \"blockcommitmentshash\" : \"xxxx\" (string) (From NU5) The hash of the block commitments field in the block header\n" " }\n" " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" " {\n" @@ -723,6 +723,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) entry.pushKV("data", EncodeHexTx(tx)); entry.pushKV("hash", txHash.GetHex()); + entry.pushKV("authdigest", tx.GetAuthDigest().GetHex()); UniValue deps(UniValue::VARR); for (const CTxIn &in : tx.vin) @@ -764,27 +765,25 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) aMutable.push_back("prevblock"); } - auto hashAuthDataRoot = pblock->BuildAuthDataMerkleTree(); - std::string hashBlockCommitments_hex = DeriveBlockCommitmentsHash( - pblocktemplate->hashChainHistoryRoot, - hashAuthDataRoot).GetHex(); UniValue result(UniValue::VOBJ); result.pushKV("capabilities", aCaps); result.pushKV("version", pblock->nVersion); result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); // The following 3 are deprecated; remove in a future release. - result.pushKV("blockcommitmentshash", hashBlockCommitments_hex); - result.pushKV("lightclientroothash", hashBlockCommitments_hex); - result.pushKV("finalsaplingroothash", hashBlockCommitments_hex); + result.pushKV("blockcommitmentshash", pblock->hashBlockCommitments.GetHex()); + result.pushKV("lightclientroothash", pblock->hashBlockCommitments.GetHex()); + result.pushKV("finalsaplingroothash", pblock->hashBlockCommitments.GetHex()); { // These are items in the result object that are valid only if the // block template returned by this RPC is used unmodified. Otherwise, // these values must be recomputed. UniValue defaults(UniValue::VOBJ); defaults.pushKV("merkleroot", pblock->BuildMerkleTree().GetHex()); - defaults.pushKV("authdataroot", hashAuthDataRoot.GetHex()); defaults.pushKV("chainhistoryroot", pblocktemplate->hashChainHistoryRoot.GetHex()); - defaults.pushKV("blockcommitmentshash", hashBlockCommitments_hex); + if (consensus.NetworkUpgradeActive(pindexPrev->nHeight+1, Consensus::UPGRADE_NU5)) { + defaults.pushKV("authdataroot", pblocktemplate->hashAuthDataRoot.GetHex()); + defaults.pushKV("blockcommitmentshash", pblock->hashBlockCommitments.GetHex()); + } result.pushKV("defaultroots", defaults); } result.pushKV("transactions", transactions);