diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index b6454a304..226d871e8 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -88,6 +88,7 @@ testScripts=( 'upgrade_golden.py' 'post_heartwood_rollback.py' 'feature_logging.py' + 'remove_sprout_shielding.py' ); testScriptsExt=( 'getblocktemplate_longpoll.py' diff --git a/qa/rpc-tests/remove_sprout_shielding.py b/qa/rpc-tests/remove_sprout_shielding.py new file mode 100755 index 000000000..1cf2ed0af --- /dev/null +++ b/qa/rpc-tests/remove_sprout_shielding.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +from decimal import Decimal +from test_framework.authproxy import JSONRPCException +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + assert_raises, + bitcoind_processes, + connect_nodes_bi, + initialize_chain, + start_nodes, start_node, get_coinbase_address, + wait_and_assert_operationid_status, + check_node_log, + nuparams, BLOSSOM_BRANCH_ID, HEARTWOOD_BRANCH_ID, CANOPY_BRANCH_ID +) + +import logging +import time + +HAS_CANOPY = ['-nurejectoldversions=false', + nuparams(BLOSSOM_BRANCH_ID, 205), + nuparams(HEARTWOOD_BRANCH_ID, 210), + nuparams(CANOPY_BRANCH_ID, 220), +] +class RemoveSproutShieldingTest (BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain(self.options.tmpdir) + + def setup_nodes(self): + return start_nodes(4, self.options.tmpdir, extra_args=[HAS_CANOPY]*4) + + def run_test (self): + + # Generate blocks up to Heartwood activation + logging.info("Generating initial blocks. Current height is 200, advance to 210 (activate Heartwood but not Canopy)") + self.nodes[0].generate(10) + self.sync_all() + + # Shield coinbase to Sprout on node 0. Should pass + sprout_addr = self.nodes[0].z_getnewaddress('sprout') + myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sprout_addr, 0)['opid'] + wait_and_assert_operationid_status(self.nodes[0], myopid) + print("taddr -> Sprout z_shieldcoinbase tx accepted before Canopy on node 0") + + self.nodes[0].generate(1) + self.sync_all() + assert_equal(self.nodes[0].z_getbalance(sprout_addr), Decimal('10')) + + # Fund taddr_0 from shielded coinbase on node 0 + taddr_0 = self.nodes[0].getnewaddress() + for _ in range(3): + recipients = [{"address": taddr_0, "amount": Decimal('1')}] + myopid = self.nodes[0].z_sendmany(sprout_addr, recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[0], myopid) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # Create taddr -> Sprout transaction and mine on node 0 before it is Canopy-aware. Should pass + sendmany_tx_0 = self.nodes[0].z_sendmany(taddr_0, [{"address": self.nodes[1].z_getnewaddress('sprout'), "amount": 1}]) + wait_and_assert_operationid_status(self.nodes[0], sendmany_tx_0) + print("taddr -> Sprout z_sendmany tx accepted before Canopy on node 0") + + self.nodes[0].generate(1) + self.sync_all() + + # Create mergetoaddress taddr -> Sprout transaction and mine on node 0 before it is Canopy-aware. Should pass + merge_tx_0 = self.nodes[0].z_mergetoaddress(["ANY_TADDR"], self.nodes[1].z_getnewaddress('sprout')) + wait_and_assert_operationid_status(self.nodes[0], merge_tx_0['opid']) + print("taddr -> Sprout z_mergetoaddress tx accepted before Canopy on node 0") + + # Mine to one block before Canopy activation on node 0; adding value + # to the Sprout pool will fail now since the transaction must be + # included in the next (or later) block, after Canopy has activated. + self.nodes[0].generate(4) + self.sync_all() + + # Shield coinbase to Sprout on node 0. Should fail + errorString = '' + try: + sprout_addr = self.nodes[0].z_getnewaddress('sprout') + self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sprout_addr, 0) + except JSONRPCException as e: + errorString = e.error['message'] + assert("Sprout shielding is not supported after Canopy" in errorString) + print("taddr -> Sprout z_shieldcoinbase tx rejected at Canopy activation on node 0") + + # Create taddr -> Sprout z_sendmany transaction on node 0. Should fail + errorString = '' + try: + sprout_addr = self.nodes[1].z_getnewaddress('sprout') + self.nodes[0].z_sendmany(taddr_0, [{"address": sprout_addr, "amount": 1}]) + except JSONRPCException as e: + errorString = e.error['message'] + assert("Sprout shielding is not supported after Canopy" in errorString) + print("taddr -> Sprout z_sendmany tx rejected at Canopy activation on node 0") + + # Create z_mergetoaddress [taddr, Sprout] -> Sprout transaction on node 0. Should fail + errorString = '' + try: + self.nodes[0].z_mergetoaddress(["ANY_TADDR", "ANY_SPROUT"], self.nodes[1].z_getnewaddress('sprout')) + except JSONRPCException as e: + errorString = e.error['message'] + assert("Sprout shielding is not supported after Canopy" in errorString) + print("[taddr, Sprout] -> Sprout z_mergetoaddress tx rejected at Canopy activation on node 0") + + # Create z_mergetoaddress Sprout -> Sprout transaction on node 0. Should pass + merge_tx_1 = self.nodes[0].z_mergetoaddress(["ANY_SPROUT"], self.nodes[1].z_getnewaddress('sprout')) + wait_and_assert_operationid_status(self.nodes[0], merge_tx_1['opid']) + print("Sprout -> Sprout z_mergetoaddress tx accepted at Canopy activation on node 0") + + self.nodes[0].generate(1) + self.sync_all() + + # Shield coinbase to Sapling on node 0. Should pass + sapling_addr = self.nodes[0].z_getnewaddress('sapling') + myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sapling_addr, 0)['opid'] + wait_and_assert_operationid_status(self.nodes[0], myopid) + print("taddr -> Sapling z_shieldcoinbase tx accepted after Canopy on node 0") + +if __name__ == '__main__': + RemoveSproutShieldingTest().main() +