From c937ba5ae5443b39fa53945348c875ca844193b1 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Fri, 3 Dec 2021 11:02:59 -0700 Subject: [PATCH] getblocktemplate: add NU5 commitments to new `defaultroots` section - merkleroot - authdataroot - chainhistoryroot - blockcommitmentshash --- qa/rpc-tests/getblocktemplate.py | 32 +++++++++++++++++++++----------- src/rpc/mining.cpp | 29 ++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index 223132da4..e7a8633ee 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -4,9 +4,15 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php . from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, connect_nodes_bi, \ - start_nodes - +from test_framework.util import ( + assert_equal, + BLOSSOM_BRANCH_ID, + CANOPY_BRANCH_ID, + HEARTWOOD_BRANCH_ID, + NU5_BRANCH_ID, + nuparams, + start_nodes, +) class GetBlockTemplateTest(BitcoinTestFramework): ''' @@ -15,12 +21,16 @@ class GetBlockTemplateTest(BitcoinTestFramework): def __init__(self): super().__init__() - self.num_nodes = 2 + self.num_nodes = 1 self.setup_clean_chain = True def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) + args = [nuparams(BLOSSOM_BRANCH_ID, 1), + nuparams(HEARTWOOD_BRANCH_ID, 1), + nuparams(CANOPY_BRANCH_ID, 1), + nuparams(NU5_BRANCH_ID, 1), + ] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [args] * self.num_nodes) self.is_network_split=False self.sync_all() @@ -51,15 +61,15 @@ class GetBlockTemplateTest(BitcoinTestFramework): # Test 5: General checks tmpl = node.getblocktemplate() assert_equal(16, len(tmpl['noncerange'])) + # should be proposing height 2, since current tip is height 1 + assert_equal(2, tmpl['height']) # Test 6: coinbasetxn checks - assert('foundersreward' in tmpl['coinbasetxn']) assert(tmpl['coinbasetxn']['required']) - # Test 7: hashFinalSaplingRoot checks - assert('finalsaplingroothash' in tmpl) - finalsaplingroothash = '3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb' - assert_equal(finalsaplingroothash, tmpl['finalsaplingroothash']) + # Test 7: blockcommitmentshash checks + assert('blockcommitmentshash' in tmpl) + assert('00' * 32 != tmpl['finalsaplingroothash']) if __name__ == '__main__': GetBlockTemplateTest().main() diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 76b6d35f8..7ed48d59a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -428,6 +428,11 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) "amounts, use 'getblocksubsidy HEIGHT' passing in the height returned\n" "by this API.\n" + "\nThe roots returned in 'defaultroots' are only valid if the block template is\n" + "used unmodified. If any part of the block template marked as 'mutable' in the\n" + "output is mutated, these roots may need to be recomputed. For more information\n" + "on the derivation process, see ZIP 244.\n" + "\nArguments:\n" "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n" " {\n" @@ -753,15 +758,29 @@ 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()); - result.pushKV("blockcommitmentshash", pblock->hashBlockCommitments.GetHex()); - // Deprecated; remove in a future release. - result.pushKV("lightclientroothash", pblock->hashBlockCommitments.GetHex()); - // Deprecated; remove in a future release. - result.pushKV("finalsaplingroothash", pblock->hashBlockCommitments.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); + { + // 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); + result.pushKV("defaultroots", defaults); + } result.pushKV("transactions", transactions); if (coinbasetxn) { assert(txCoinbase.isObject());