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