commit
0403799be2
|
@ -1,4 +1,4 @@
|
||||||
Zcash 4.6.0
|
Zcash 4.6.0-1
|
||||||
<img align="right" width="120" height="80" src="doc/imgs/logo.png">
|
<img align="right" width="120" height="80" src="doc/imgs/logo.png">
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ AC_PREREQ([2.60])
|
||||||
define(_CLIENT_VERSION_MAJOR, 4)
|
define(_CLIENT_VERSION_MAJOR, 4)
|
||||||
define(_CLIENT_VERSION_MINOR, 6)
|
define(_CLIENT_VERSION_MINOR, 6)
|
||||||
define(_CLIENT_VERSION_REVISION, 0)
|
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(_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_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)
|
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
zcash (4.6.0+1) stable; urgency=medium
|
||||||
|
|
||||||
|
* 4.6.0-1 release.
|
||||||
|
|
||||||
|
-- Electric Coin Company <team@electriccoin.co> Wed, 05 Jan 2022 20:18:43 +0000
|
||||||
|
|
||||||
zcash (4.6.0) stable; urgency=medium
|
zcash (4.6.0) stable; urgency=medium
|
||||||
|
|
||||||
* 4.6.0 release.
|
* 4.6.0 release.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
name: "zcash-4.6.0"
|
name: "zcash-4.6.0-1"
|
||||||
enable_cache: true
|
enable_cache: true
|
||||||
distro: "debian"
|
distro: "debian"
|
||||||
suites:
|
suites:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Zcash Contributors
|
Zcash Contributors
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Jack Grigg (1124)
|
Jack Grigg (1127)
|
||||||
Simon Liu (460)
|
Simon Liu (460)
|
||||||
Sean Bowe (367)
|
Sean Bowe (367)
|
||||||
Daira Hopwood (270)
|
Daira Hopwood (270)
|
||||||
|
@ -16,7 +16,7 @@ Jonas Schnelli (89)
|
||||||
Jay Graber (89)
|
Jay Graber (89)
|
||||||
Marco Falke (82)
|
Marco Falke (82)
|
||||||
Cory Fields (75)
|
Cory Fields (75)
|
||||||
Larry Ruane (69)
|
Larry Ruane (72)
|
||||||
Ying Tong Lai (56)
|
Ying Tong Lai (56)
|
||||||
Nathan Wilcox (56)
|
Nathan Wilcox (56)
|
||||||
Matt Corallo (52)
|
Matt Corallo (52)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
|
||||||
.TH ZCASH-CLI "1" "December 2021" "zcash-cli v4.6.0" "User Commands"
|
.TH ZCASH-CLI "1" "January 2022" "zcash-cli v4.6.0-1" "User Commands"
|
||||||
.SH NAME
|
.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
|
.SH DESCRIPTION
|
||||||
Zcash RPC client version v4.6.0
|
Zcash RPC client version v4.6.0\-1
|
||||||
.PP
|
.PP
|
||||||
In order to ensure you are adequately protecting your privacy when using Zcash,
|
In order to ensure you are adequately protecting your privacy when using Zcash,
|
||||||
please see <https://z.cash/support/security/>.
|
please see <https://z.cash/support/security/>.
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
|
||||||
.TH ZCASH-TX "1" "December 2021" "zcash-tx v4.6.0" "User Commands"
|
.TH ZCASH-TX "1" "January 2022" "zcash-tx v4.6.0-1" "User Commands"
|
||||||
.SH NAME
|
.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
|
.SH DESCRIPTION
|
||||||
Zcash zcash\-tx utility version v4.6.0
|
Zcash zcash\-tx utility version v4.6.0\-1
|
||||||
.SS "Usage:"
|
.SS "Usage:"
|
||||||
.TP
|
.TP
|
||||||
zcash\-tx [options] <hex\-tx> [commands]
|
zcash\-tx [options] <hex\-tx> [commands]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
|
||||||
.TH ZCASHD "1" "December 2021" "zcashd v4.6.0" "User Commands"
|
.TH ZCASHD "1" "January 2022" "zcashd v4.6.0-1" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
zcashd \- manual page for zcashd v4.6.0
|
zcashd \- manual page for zcashd v4.6.0-1
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Zcash Daemon version v4.6.0
|
Zcash Daemon version v4.6.0\-1
|
||||||
.PP
|
.PP
|
||||||
In order to ensure you are adequately protecting your privacy when using Zcash,
|
In order to ensure you are adequately protecting your privacy when using Zcash,
|
||||||
please see <https://z.cash/support/security/>.
|
please see <https://z.cash/support/security/>.
|
||||||
|
@ -84,7 +84,7 @@ Keep at most <n> unconnectable transactions in memory (default: 100)
|
||||||
.HP
|
.HP
|
||||||
\fB\-par=\fR<n>
|
\fB\-par=\fR<n>
|
||||||
.IP
|
.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)
|
leave that many cores free, default: 0)
|
||||||
.HP
|
.HP
|
||||||
\fB\-pid=\fR<file>
|
\fB\-pid=\fR<file>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -8,11 +8,8 @@ import codecs
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
BLOSSOM_BRANCH_ID,
|
|
||||||
CANOPY_BRANCH_ID,
|
CANOPY_BRANCH_ID,
|
||||||
HEARTWOOD_BRANCH_ID,
|
|
||||||
NU5_BRANCH_ID,
|
NU5_BRANCH_ID,
|
||||||
get_coinbase_address,
|
|
||||||
hex_str_to_bytes,
|
hex_str_to_bytes,
|
||||||
nuparams,
|
nuparams,
|
||||||
start_nodes,
|
start_nodes,
|
||||||
|
@ -20,8 +17,9 @@ from test_framework.util import (
|
||||||
)
|
)
|
||||||
from test_framework.mininode import (
|
from test_framework.mininode import (
|
||||||
CTransaction,
|
CTransaction,
|
||||||
|
uint256_from_str,
|
||||||
)
|
)
|
||||||
from test_framework.blocktools import(
|
from test_framework.blocktools import (
|
||||||
create_block
|
create_block
|
||||||
)
|
)
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
@ -39,48 +37,57 @@ class GetBlockTemplateTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def setup_network(self, split=False):
|
def setup_network(self, split=False):
|
||||||
args = [
|
args = [
|
||||||
nuparams(BLOSSOM_BRANCH_ID, 1),
|
nuparams(CANOPY_BRANCH_ID, 115),
|
||||||
nuparams(HEARTWOOD_BRANCH_ID, 1),
|
nuparams(NU5_BRANCH_ID, 130),
|
||||||
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.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [args] * self.num_nodes)
|
||||||
self.is_network_split=False
|
self.is_network_split = False
|
||||||
self.sync_all()
|
self.node = self.nodes[0]
|
||||||
|
|
||||||
def run_test(self):
|
def add_nu5_v4_tx_to_mempool(self):
|
||||||
node = self.nodes[0]
|
node = self.node
|
||||||
print("Generating blocks")
|
# sprout to transparent (v4)
|
||||||
node.generate(110)
|
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")
|
def add_transparent_tx_to_mempool(self):
|
||||||
# This part of the test should be improved, submit some V4 transactions
|
node = self.node
|
||||||
# and varying combinations of shielded and transparent
|
# transparent to transparent (v5 after nu5)
|
||||||
for _ in range(5):
|
outputs = {self.transparent_addr: 0.1}
|
||||||
# submit a tx with a shielded output
|
node.sendmany('', outputs)
|
||||||
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)
|
|
||||||
|
|
||||||
# submit a tx with a transparent output
|
def gbt_submitblock(self, nu5_active):
|
||||||
outputs = {node.getnewaddress():0.2}
|
node = self.node
|
||||||
node.sendmany('', outputs)
|
mempool_tx_list = node.getrawmempool()
|
||||||
|
|
||||||
print("Getting block template")
|
|
||||||
gbt = node.getblocktemplate()
|
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)
|
prevhash = int(gbt['previousblockhash'], 16)
|
||||||
blockcommitmentshash = int(gbt['defaultroots']['blockcommitmentshash'], 16)
|
|
||||||
nTime = gbt['mintime']
|
nTime = gbt['mintime']
|
||||||
nBits = int(gbt['bits'], 16)
|
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']))
|
f = BytesIO(hex_str_to_bytes(gbt['coinbasetxn']['data']))
|
||||||
coinbase = CTransaction()
|
coinbase = CTransaction()
|
||||||
coinbase.deserialize(f)
|
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)
|
block = create_block(prevhash, coinbase, nTime, nBits, blockcommitmentshash)
|
||||||
|
|
||||||
# copy the non-coinbase transactions from the block template to the block
|
# 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']))
|
f = BytesIO(hex_str_to_bytes(gbt_tx['data']))
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.deserialize(f)
|
tx.deserialize(f)
|
||||||
|
tx.calc_sha256()
|
||||||
|
assert_equal(tx.auth_digest_hex, node.getrawtransaction(tx.hash, 1)['authdigest'])
|
||||||
block.vtx.append(tx)
|
block.vtx.append(tx)
|
||||||
block.hashMerkleRoot = int(gbt['defaultroots']['merkleroot'], 16)
|
block.hashMerkleRoot = int(gbt['defaultroots']['merkleroot'], 16)
|
||||||
assert_equal(block.hashMerkleRoot, block.calc_merkle_root(), "merkleroot")
|
assert_equal(block.hashMerkleRoot, block.calc_merkle_root(), "merkleroot")
|
||||||
assert_equal(len(block.vtx), len(gbt['transactions']) + 1, "number of transactions")
|
assert_equal(len(block.vtx), len(gbt['transactions']) + 1, "number of transactions")
|
||||||
assert_equal(block.hashPrevBlock, int(gbt['previousblockhash'], 16), "prevhash")
|
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.solve()
|
||||||
block = block.serialize()
|
block.calc_sha256()
|
||||||
block = codecs.encode(block, 'hex_codec')
|
|
||||||
|
|
||||||
print("Submitting block")
|
submitblock_reply = node.submitblock(codecs.encode(block.serialize(), 'hex_codec'))
|
||||||
submitblock_reply = node.submitblock(block)
|
|
||||||
assert_equal(None, submitblock_reply)
|
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__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1126,11 +1126,14 @@ class CTransaction(object):
|
||||||
if self.nVersion >= 5:
|
if self.nVersion >= 5:
|
||||||
from . import zip244
|
from . import zip244
|
||||||
txid = zip244.txid_digest(self)
|
txid = zip244.txid_digest(self)
|
||||||
|
self.auth_digest = zip244.auth_digest(self)
|
||||||
else:
|
else:
|
||||||
txid = hash256(self.serialize())
|
txid = hash256(self.serialize())
|
||||||
|
self.auth_digest = b'\xFF'*32
|
||||||
if self.sha256 is None:
|
if self.sha256 is None:
|
||||||
self.sha256 = uint256_from_str(txid)
|
self.sha256 = uint256_from_str(txid)
|
||||||
self.hash = encode(txid[::-1], 'hex_codec').decode('ascii')
|
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):
|
def is_valid(self):
|
||||||
self.calc_sha256()
|
self.calc_sha256()
|
||||||
|
@ -1263,6 +1266,27 @@ class CBlock(CBlockHeader):
|
||||||
hashes = newhashes
|
hashes = newhashes
|
||||||
return uint256_from_str(hashes[0])
|
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):
|
def is_valid(self, n=48, k=5):
|
||||||
# H(I||...
|
# H(I||...
|
||||||
digest = blake2b(digest_size=(512//n)*n//8, person=zcash_person(n, k))
|
digest = blake2b(digest_size=(512//n)*n//8, person=zcash_person(n, k))
|
||||||
|
|
|
@ -15,7 +15,7 @@ import struct
|
||||||
|
|
||||||
from pyblake2 import blake2b
|
from pyblake2 import blake2b
|
||||||
|
|
||||||
from .mininode import ser_uint256
|
from .mininode import ser_string, ser_uint256
|
||||||
from .script import (
|
from .script import (
|
||||||
SIGHASH_ANYONECANPAY,
|
SIGHASH_ANYONECANPAY,
|
||||||
SIGHASH_NONE,
|
SIGHASH_NONE,
|
||||||
|
@ -41,7 +41,7 @@ def transparent_digest(tx):
|
||||||
def transparent_scripts_digest(tx):
|
def transparent_scripts_digest(tx):
|
||||||
digest = blake2b(digest_size=32, person=b'ZTxAuthTransHash')
|
digest = blake2b(digest_size=32, person=b'ZTxAuthTransHash')
|
||||||
for x in tx.vin:
|
for x in tx.vin:
|
||||||
digest.update(bytes(x.scriptSig))
|
digest.update(ser_string(x.scriptSig))
|
||||||
return digest.digest()
|
return digest.digest()
|
||||||
|
|
||||||
# Sapling
|
# Sapling
|
||||||
|
@ -288,7 +288,7 @@ def outputs_sig_digest(tx, nHashType, txin):
|
||||||
def txin_sig_digest(tx, txin):
|
def txin_sig_digest(tx, txin):
|
||||||
digest = blake2b(digest_size=32, person=b'Zcash___TxInHash')
|
digest = blake2b(digest_size=32, person=b'Zcash___TxInHash')
|
||||||
digest.update(bytes(tx.vin[txin.nIn].prevout))
|
digest.update(bytes(tx.vin[txin.nIn].prevout))
|
||||||
digest.update(bytes(txin.scriptCode))
|
digest.update(ser_string(txin.scriptCode))
|
||||||
digest.update(struct.pack('<Q', txin.amount))
|
digest.update(struct.pack('<Q', txin.amount))
|
||||||
digest.update(struct.pack('<I', tx.vin[txin.nIn].nSequence))
|
digest.update(struct.pack('<I', tx.vin[txin.nIn].nSequence))
|
||||||
return digest.digest()
|
return digest.digest()
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#define CLIENT_VERSION_MAJOR 4
|
#define CLIENT_VERSION_MAJOR 4
|
||||||
#define CLIENT_VERSION_MINOR 6
|
#define CLIENT_VERSION_MINOR 6
|
||||||
#define CLIENT_VERSION_REVISION 0
|
#define CLIENT_VERSION_REVISION 0
|
||||||
#define CLIENT_VERSION_BUILD 50
|
#define CLIENT_VERSION_BUILD 51
|
||||||
|
|
||||||
//! Set to true for release, false for prerelease or test build
|
//! Set to true for release, false for prerelease or test build
|
||||||
#define CLIENT_VERSION_IS_RELEASE true
|
#define CLIENT_VERSION_IS_RELEASE true
|
||||||
|
|
|
@ -642,14 +642,38 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const MinerAddre
|
||||||
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
|
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
|
||||||
if (chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_NU5)) {
|
if (chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_NU5)) {
|
||||||
// hashBlockCommitments depends on the block transactions, so we have to
|
// hashBlockCommitments depends on the block transactions, so we have to
|
||||||
// update it whenever the coinbase transaction changes. Leave it unset here,
|
// update it whenever the coinbase transaction changes.
|
||||||
// like hashMerkleRoot, and instead cache what we will need to calculate it.
|
//
|
||||||
|
// - 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->hashChainHistoryRoot = view.GetHistoryRoot(prevConsensusBranchId);
|
||||||
|
pblocktemplate->hashAuthDataRoot = pblock->BuildAuthDataMerkleTree();
|
||||||
|
pblock->hashBlockCommitments = DeriveBlockCommitmentsHash(
|
||||||
|
pblocktemplate->hashChainHistoryRoot,
|
||||||
|
pblocktemplate->hashAuthDataRoot);
|
||||||
} else if (IsActivationHeight(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_HEARTWOOD)) {
|
} else if (IsActivationHeight(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_HEARTWOOD)) {
|
||||||
|
pblocktemplate->hashChainHistoryRoot.SetNull();
|
||||||
|
pblocktemplate->hashAuthDataRoot.SetNull();
|
||||||
pblock->hashBlockCommitments.SetNull();
|
pblock->hashBlockCommitments.SetNull();
|
||||||
} else if (chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_HEARTWOOD)) {
|
} 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 {
|
} else {
|
||||||
|
pblocktemplate->hashChainHistoryRoot.SetNull();
|
||||||
|
pblocktemplate->hashAuthDataRoot.SetNull();
|
||||||
pblock->hashBlockCommitments = sapling_tree.root();
|
pblock->hashBlockCommitments = sapling_tree.root();
|
||||||
}
|
}
|
||||||
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
||||||
|
@ -727,9 +751,10 @@ void IncrementExtraNonce(
|
||||||
pblock->vtx[0] = txCoinbase;
|
pblock->vtx[0] = txCoinbase;
|
||||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_NU5)) {
|
if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_NU5)) {
|
||||||
|
pblocktemplate->hashAuthDataRoot = pblock->BuildAuthDataMerkleTree();
|
||||||
pblock->hashBlockCommitments = DeriveBlockCommitmentsHash(
|
pblock->hashBlockCommitments = DeriveBlockCommitmentsHash(
|
||||||
pblocktemplate->hashChainHistoryRoot,
|
pblocktemplate->hashChainHistoryRoot,
|
||||||
pblock->BuildAuthDataMerkleTree());
|
pblocktemplate->hashAuthDataRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,10 @@ struct CBlockTemplate
|
||||||
// Cached whenever we update `block`, so we can update hashBlockCommitments
|
// Cached whenever we update `block`, so we can update hashBlockCommitments
|
||||||
// when we change the coinbase transaction.
|
// when we change the coinbase transaction.
|
||||||
uint256 hashChainHistoryRoot;
|
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<CAmount> vTxFees;
|
std::vector<CAmount> vTxFees;
|
||||||
std::vector<int64_t> vTxSigOps;
|
std::vector<int64_t> vTxSigOps;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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"
|
" \"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"
|
" \"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"
|
" \"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"
|
" \"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"
|
" }\n"
|
||||||
" \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
|
" \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
|
@ -723,6 +723,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||||
entry.pushKV("data", EncodeHexTx(tx));
|
entry.pushKV("data", EncodeHexTx(tx));
|
||||||
|
|
||||||
entry.pushKV("hash", txHash.GetHex());
|
entry.pushKV("hash", txHash.GetHex());
|
||||||
|
entry.pushKV("authdigest", tx.GetAuthDigest().GetHex());
|
||||||
|
|
||||||
UniValue deps(UniValue::VARR);
|
UniValue deps(UniValue::VARR);
|
||||||
for (const CTxIn &in : tx.vin)
|
for (const CTxIn &in : tx.vin)
|
||||||
|
@ -764,27 +765,25 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||||
aMutable.push_back("prevblock");
|
aMutable.push_back("prevblock");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hashAuthDataRoot = pblock->BuildAuthDataMerkleTree();
|
|
||||||
std::string hashBlockCommitments_hex = DeriveBlockCommitmentsHash(
|
|
||||||
pblocktemplate->hashChainHistoryRoot,
|
|
||||||
hashAuthDataRoot).GetHex();
|
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
result.pushKV("capabilities", aCaps);
|
result.pushKV("capabilities", aCaps);
|
||||||
result.pushKV("version", pblock->nVersion);
|
result.pushKV("version", pblock->nVersion);
|
||||||
result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
|
result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
|
||||||
// The following 3 are deprecated; remove in a future release.
|
// The following 3 are deprecated; remove in a future release.
|
||||||
result.pushKV("blockcommitmentshash", hashBlockCommitments_hex);
|
result.pushKV("blockcommitmentshash", pblock->hashBlockCommitments.GetHex());
|
||||||
result.pushKV("lightclientroothash", hashBlockCommitments_hex);
|
result.pushKV("lightclientroothash", pblock->hashBlockCommitments.GetHex());
|
||||||
result.pushKV("finalsaplingroothash", hashBlockCommitments_hex);
|
result.pushKV("finalsaplingroothash", pblock->hashBlockCommitments.GetHex());
|
||||||
{
|
{
|
||||||
// These are items in the result object that are valid only if the
|
// These are items in the result object that are valid only if the
|
||||||
// block template returned by this RPC is used unmodified. Otherwise,
|
// block template returned by this RPC is used unmodified. Otherwise,
|
||||||
// these values must be recomputed.
|
// these values must be recomputed.
|
||||||
UniValue defaults(UniValue::VOBJ);
|
UniValue defaults(UniValue::VOBJ);
|
||||||
defaults.pushKV("merkleroot", pblock->BuildMerkleTree().GetHex());
|
defaults.pushKV("merkleroot", pblock->BuildMerkleTree().GetHex());
|
||||||
defaults.pushKV("authdataroot", hashAuthDataRoot.GetHex());
|
|
||||||
defaults.pushKV("chainhistoryroot", pblocktemplate->hashChainHistoryRoot.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("defaultroots", defaults);
|
||||||
}
|
}
|
||||||
result.pushKV("transactions", transactions);
|
result.pushKV("transactions", transactions);
|
||||||
|
|
Loading…
Reference in New Issue