Any projects which want to use Hush code from now on will need to be licensed as GPLv3 or we will send the lawyers: https://www.softwarefreedom.org/ Notably, Komodo (KMD) is licensed as GPLv2 and is no longer compatible to receive code changes, without causing legal issues. MIT projects, such as Zcash, also cannot pull in changes from the Hush Full Node without permission from The Hush Developers, which may in some circumstances grant an MIT license on a case-by-case basis.
151 lines
6.3 KiB
Python
Executable File
151 lines
6.3 KiB
Python
Executable File
#!/usr/bin/env python2
|
|
# Copyright (c) 2018 The Zcash developers
|
|
# Distributed under the GPLv3 software license, see the accompanying
|
|
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
from test_framework.util import (
|
|
assert_equal,
|
|
connect_nodes_bi,
|
|
initialize_chain_clean,
|
|
start_nodes,
|
|
wait_and_assert_operationid_status,
|
|
)
|
|
|
|
from decimal import Decimal
|
|
|
|
SAPLING_TREE_EMPTY_ROOT = "3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb"
|
|
NULL_FIELD = "0000000000000000000000000000000000000000000000000000000000000000"
|
|
|
|
# Verify block header field 'hashFinalSaplingRoot' (returned in rpc as 'finalsaplingroot')
|
|
# is updated when Sapling transactions with outputs (commitments) are mined into a block.
|
|
class FinalSaplingRootTest(BitcoinTestFramework):
|
|
|
|
def setup_chain(self):
|
|
print("Initializing test directory "+self.options.tmpdir)
|
|
initialize_chain_clean(self.options.tmpdir, 4)
|
|
|
|
def setup_network(self, split=False):
|
|
self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[
|
|
'-nuparams=5ba81b19:100', # Overwinter
|
|
'-nuparams=76b809bb:200', # Sapling
|
|
'-txindex' # Avoid JSONRPC error: No information available about transaction
|
|
]] * 4 )
|
|
connect_nodes_bi(self.nodes,0,1)
|
|
connect_nodes_bi(self.nodes,1,2)
|
|
connect_nodes_bi(self.nodes,0,2)
|
|
connect_nodes_bi(self.nodes,0,3)
|
|
self.is_network_split=False
|
|
self.sync_all()
|
|
|
|
def run_test(self):
|
|
# Activate Overwinter and Sapling
|
|
self.nodes[0].generate(200)
|
|
self.sync_all()
|
|
|
|
# Verfify genesis block contains null field for what is now called the final sapling root field.
|
|
blk = self.nodes[0].getblock("0")
|
|
assert_equal(blk["finalsaplingroot"], NULL_FIELD)
|
|
|
|
# Verify all generated blocks contain the empty root of the Sapling tree.
|
|
blockcount = self.nodes[0].getblockcount()
|
|
for height in xrange(1, blockcount + 1):
|
|
blk = self.nodes[0].getblock(str(height))
|
|
assert_equal(blk["finalsaplingroot"], SAPLING_TREE_EMPTY_ROOT)
|
|
|
|
# Node 0 shields some funds
|
|
taddr0 = self.nodes[0].getnewaddress()
|
|
saplingAddr0 = self.nodes[0].z_getnewaddress('sapling')
|
|
recipients = []
|
|
recipients.append({"address": saplingAddr0, "amount": Decimal('20')})
|
|
myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0)
|
|
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
# Verify the final Sapling root has changed
|
|
blk = self.nodes[0].getblock("201")
|
|
root = blk["finalsaplingroot"]
|
|
assert(root is not SAPLING_TREE_EMPTY_ROOT)
|
|
assert(root is not NULL_FIELD)
|
|
|
|
# Verify there is a Sapling output description (its commitment was added to tree)
|
|
result = self.nodes[0].getrawtransaction(mytxid, 1)
|
|
assert_equal(len(result["vShieldedOutput"]), 1)
|
|
|
|
# Mine an empty block and verify the final Sapling root does not change
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
assert_equal(root, self.nodes[0].getblock("202")["finalsaplingroot"])
|
|
|
|
# Mine a block with a transparent tx and verify the final Sapling root does not change
|
|
taddr1 = self.nodes[1].getnewaddress()
|
|
self.nodes[0].sendtoaddress(taddr1, Decimal("1.23"))
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
assert_equal(len(self.nodes[0].getblock("203")["tx"]), 2)
|
|
assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal("1.23"))
|
|
assert_equal(root, self.nodes[0].getblock("203")["finalsaplingroot"])
|
|
|
|
# Mine a block with a Sprout shielded tx and verify the final Sapling root does not change
|
|
zaddr1 = self.nodes[1].z_getnewaddress()
|
|
recipients = []
|
|
recipients.append({"address": zaddr1, "amount": Decimal('10')})
|
|
myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0)
|
|
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
assert_equal(len(self.nodes[0].getblock("204")["tx"]), 2)
|
|
assert_equal(self.nodes[1].z_getbalance(zaddr1), Decimal("10"))
|
|
assert_equal(root, self.nodes[0].getblock("204")["finalsaplingroot"])
|
|
|
|
# Mine a block with a Sapling shielded recipient and verify the final Sapling root changes
|
|
saplingAddr1 = self.nodes[1].z_getnewaddress("sapling")
|
|
recipients = []
|
|
recipients.append({"address": saplingAddr1, "amount": Decimal('12.34')})
|
|
myopid = self.nodes[0].z_sendmany(saplingAddr0, recipients, 1, 0)
|
|
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
assert_equal(len(self.nodes[0].getblock("205")["tx"]), 2)
|
|
assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal("12.34"))
|
|
assert(root is not self.nodes[0].getblock("205")["finalsaplingroot"])
|
|
|
|
# Verify there is a Sapling output description (its commitment was added to tree)
|
|
result = self.nodes[0].getrawtransaction(mytxid, 1)
|
|
assert_equal(len(result["vShieldedOutput"]), 2) # there is Sapling shielded change
|
|
|
|
# Mine a block with a Sapling shielded sender and transparent recipient and verify the final Sapling root doesn't change
|
|
taddr2 = self.nodes[0].getnewaddress()
|
|
recipients = []
|
|
recipients.append({"address": taddr2, "amount": Decimal('12.34')})
|
|
myopid = self.nodes[1].z_sendmany(saplingAddr1, recipients, 1, 0)
|
|
mytxid = wait_and_assert_operationid_status(self.nodes[1], myopid)
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
assert_equal(len(self.nodes[0].getblock("206")["tx"]), 2)
|
|
assert_equal(self.nodes[0].z_getbalance(taddr2), Decimal("12.34"))
|
|
|
|
blk = self.nodes[0].getblock("206")
|
|
root = blk["finalsaplingroot"]
|
|
assert_equal(root, self.nodes[0].getblock("205")["finalsaplingroot"])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
FinalSaplingRootTest().main()
|