Extend Sprout mergetoaddress rpc test to also work for Sapling
This commit is contained in:
parent
fe393e8a2f
commit
e0c491c073
|
@ -21,7 +21,6 @@ testScripts=(
|
|||
'wallet_shieldcoinbase_sprout.py'
|
||||
'wallet_shieldcoinbase_sapling.py'
|
||||
'wallet_listreceived.py'
|
||||
'wallet_mergetoaddress.py'
|
||||
'wallet.py'
|
||||
'wallet_overwintertx.py'
|
||||
'wallet_persistence.py'
|
||||
|
@ -30,6 +29,8 @@ testScripts=(
|
|||
'wallet_addresses.py'
|
||||
'wallet_sapling.py'
|
||||
'wallet_listnotes.py'
|
||||
'mergetoaddress_sprout.py'
|
||||
'mergetoaddress_sapling.py'
|
||||
'listtransactions.py'
|
||||
'mempool_resurrect_test.py'
|
||||
'txn_doublespend.py'
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
# Copyright (c) 2018 The Zcash developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Common code for testing z_mergetoaddress before and after sapling activation
|
||||
#
|
||||
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, connect_nodes_bi, fail, \
|
||||
initialize_chain_clean, start_node, sync_blocks, sync_mempools, \
|
||||
wait_and_assert_operationid_status
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
def assert_mergetoaddress_exception(expected_error_msg, merge_to_address_lambda):
|
||||
try:
|
||||
merge_to_address_lambda()
|
||||
fail("Expected exception: %s" % expected_error_msg)
|
||||
except JSONRPCException as e:
|
||||
assert_equal(expected_error_msg, e.error['message'])
|
||||
except Exception as e:
|
||||
fail("Expected JSONRPCException. Found %s" % repr(e))
|
||||
|
||||
|
||||
class MergeToAddressHelper:
|
||||
|
||||
def setup_chain(self, test):
|
||||
print("Initializing test directory "+test.options.tmpdir)
|
||||
initialize_chain_clean(test.options.tmpdir, 4)
|
||||
|
||||
def setup_network(self, test, additional_args=[]):
|
||||
args = ['-debug=zrpcunsafe', '-experimentalfeatures', '-zmergetoaddress']
|
||||
args += additional_args
|
||||
test.nodes = []
|
||||
test.nodes.append(start_node(0, test.options.tmpdir, args))
|
||||
test.nodes.append(start_node(1, test.options.tmpdir, args))
|
||||
args2 = ['-debug=zrpcunsafe', '-experimentalfeatures', '-zmergetoaddress', '-mempooltxinputlimit=7']
|
||||
args2 += additional_args
|
||||
test.nodes.append(start_node(2, test.options.tmpdir, args2))
|
||||
connect_nodes_bi(test.nodes, 0, 1)
|
||||
connect_nodes_bi(test.nodes, 1, 2)
|
||||
connect_nodes_bi(test.nodes, 0, 2)
|
||||
test.is_network_split = False
|
||||
test.sync_all()
|
||||
|
||||
def run_test(self, test, addr_type):
|
||||
print "Mining blocks..."
|
||||
|
||||
test.nodes[0].generate(1)
|
||||
do_not_shield_taddr = test.nodes[0].getnewaddress()
|
||||
|
||||
test.nodes[0].generate(4)
|
||||
walletinfo = test.nodes[0].getwalletinfo()
|
||||
assert_equal(walletinfo['immature_balance'], 50)
|
||||
assert_equal(walletinfo['balance'], 0)
|
||||
test.sync_all()
|
||||
test.nodes[2].generate(1)
|
||||
test.nodes[2].getnewaddress()
|
||||
test.nodes[2].generate(1)
|
||||
test.nodes[2].getnewaddress()
|
||||
test.nodes[2].generate(1)
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(101)
|
||||
test.sync_all()
|
||||
assert_equal(test.nodes[0].getbalance(), 50)
|
||||
assert_equal(test.nodes[1].getbalance(), 10)
|
||||
assert_equal(test.nodes[2].getbalance(), 30)
|
||||
|
||||
# Shield the coinbase
|
||||
myzaddr = test.nodes[0].z_getnewaddress(addr_type)
|
||||
result = test.nodes[0].z_shieldcoinbase("*", myzaddr, 0)
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Prepare some UTXOs and notes for merging
|
||||
mytaddr = test.nodes[0].getnewaddress()
|
||||
mytaddr2 = test.nodes[0].getnewaddress()
|
||||
mytaddr3 = test.nodes[0].getnewaddress()
|
||||
result = test.nodes[0].z_sendmany(myzaddr, [
|
||||
{'address': do_not_shield_taddr, 'amount': 10},
|
||||
{'address': mytaddr, 'amount': 10},
|
||||
{'address': mytaddr2, 'amount': 10},
|
||||
{'address': mytaddr3, 'amount': 10},
|
||||
], 1, 0)
|
||||
wait_and_assert_operationid_status(test.nodes[0], result)
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Merging will fail because from arguments need to be in an array
|
||||
assert_mergetoaddress_exception(
|
||||
"JSON value is not an array as expected",
|
||||
lambda: test.nodes[0].z_mergetoaddress("*", myzaddr))
|
||||
|
||||
# Merging will fail when trying to spend from watch-only address
|
||||
test.nodes[2].importaddress(mytaddr)
|
||||
assert_mergetoaddress_exception(
|
||||
"Could not find any funds to merge.",
|
||||
lambda: test.nodes[2].z_mergetoaddress([mytaddr], myzaddr))
|
||||
|
||||
# Merging will fail because fee is negative
|
||||
assert_mergetoaddress_exception(
|
||||
"Amount out of range",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, -1))
|
||||
|
||||
# Merging will fail because fee is larger than MAX_MONEY
|
||||
assert_mergetoaddress_exception(
|
||||
"Amount out of range",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('21000000.00000001')))
|
||||
|
||||
# Merging will fail because fee is larger than sum of UTXOs
|
||||
assert_mergetoaddress_exception(
|
||||
"Insufficient funds, have 50.00, which is less than miners fee 999.00",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, 999))
|
||||
|
||||
# Merging will fail because transparent limit parameter must be at least 0
|
||||
assert_mergetoaddress_exception(
|
||||
"Limit on maximum number of UTXOs cannot be negative",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), -1))
|
||||
|
||||
# Merging will fail because transparent limit parameter is absurdly large
|
||||
assert_mergetoaddress_exception(
|
||||
"JSON integer out of range",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), 99999999999999))
|
||||
|
||||
# Merging will fail because shielded limit parameter must be at least 0
|
||||
assert_mergetoaddress_exception(
|
||||
"Limit on maximum number of notes cannot be negative",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), 50, -1))
|
||||
|
||||
# Merging will fail because shielded limit parameter is absurdly large
|
||||
assert_mergetoaddress_exception(
|
||||
"JSON integer out of range",
|
||||
lambda: test.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), 50, 99999999999999))
|
||||
|
||||
# Merging will fail for this specific case where it would spend a fee and do nothing
|
||||
assert_mergetoaddress_exception(
|
||||
"Destination address is also the only source address, and all its funds are already merged.",
|
||||
lambda: test.nodes[0].z_mergetoaddress([mytaddr], mytaddr))
|
||||
|
||||
# Merge UTXOs from node 0 of value 30, standard fee of 0.00010000
|
||||
result = test.nodes[0].z_mergetoaddress([mytaddr, mytaddr2, mytaddr3], myzaddr)
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Confirm balances and that do_not_shield_taddr containing funds of 10 was left alone
|
||||
assert_equal(test.nodes[0].getbalance(), 10)
|
||||
assert_equal(test.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10.0'))
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('39.99990000'))
|
||||
assert_equal(test.nodes[1].getbalance(), 40)
|
||||
assert_equal(test.nodes[2].getbalance(), 30)
|
||||
|
||||
# Shield all notes to another z-addr
|
||||
myzaddr2 = test.nodes[0].z_getnewaddress(addr_type)
|
||||
result = test.nodes[0].z_mergetoaddress(["ANY_ZADDR"], myzaddr2, 0)
|
||||
assert_equal(result["mergingUTXOs"], Decimal('0'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('0'))
|
||||
assert_equal(result["mergingNotes"], Decimal('2'))
|
||||
assert_equal(result["remainingNotes"], Decimal('0'))
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
test.sync_all()
|
||||
blockhash = test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
assert_equal(len(test.nodes[0].getblock(blockhash[0])['tx']), 2)
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr), 0)
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr2), Decimal('39.99990000'))
|
||||
|
||||
# Shield coinbase UTXOs from any node 2 taddr, and set fee to 0
|
||||
result = test.nodes[2].z_shieldcoinbase("*", myzaddr, 0)
|
||||
wait_and_assert_operationid_status(test.nodes[2], result['opid'])
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
assert_equal(test.nodes[0].getbalance(), 10)
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr), Decimal('30'))
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr2), Decimal('39.99990000'))
|
||||
assert_equal(test.nodes[1].getbalance(), 60)
|
||||
assert_equal(test.nodes[2].getbalance(), 0)
|
||||
|
||||
# Merge all notes from node 0 into a node 0 taddr, and set fee to 0
|
||||
result = test.nodes[0].z_mergetoaddress(["ANY_ZADDR"], mytaddr, 0)
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
assert_equal(test.nodes[0].getbalance(), Decimal('79.99990000'))
|
||||
assert_equal(test.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10.0'))
|
||||
assert_equal(test.nodes[0].z_getbalance(mytaddr), Decimal('69.99990000'))
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr), 0)
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr2), 0)
|
||||
assert_equal(test.nodes[1].getbalance(), 70)
|
||||
assert_equal(test.nodes[2].getbalance(), 0)
|
||||
|
||||
# Merge all node 0 UTXOs together into a node 1 taddr, and set fee to 0
|
||||
test.nodes[1].getnewaddress() # Ensure we have an empty address
|
||||
n1taddr = test.nodes[1].getnewaddress()
|
||||
result = test.nodes[0].z_mergetoaddress(["ANY_TADDR"], n1taddr, 0)
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
assert_equal(test.nodes[0].getbalance(), 0)
|
||||
assert_equal(test.nodes[0].z_getbalance(do_not_shield_taddr), 0)
|
||||
assert_equal(test.nodes[0].z_getbalance(mytaddr), 0)
|
||||
assert_equal(test.nodes[0].z_getbalance(myzaddr), 0)
|
||||
assert_equal(test.nodes[1].getbalance(), Decimal('159.99990000'))
|
||||
assert_equal(test.nodes[1].z_getbalance(n1taddr), Decimal('79.99990000'))
|
||||
assert_equal(test.nodes[2].getbalance(), 0)
|
||||
|
||||
# Generate 800 regular UTXOs on node 0, and 20 regular UTXOs on node 2
|
||||
mytaddr = test.nodes[0].getnewaddress()
|
||||
n2taddr = test.nodes[2].getnewaddress()
|
||||
test.nodes[1].generate(1000)
|
||||
test.sync_all()
|
||||
for i in range(800):
|
||||
test.nodes[1].sendtoaddress(mytaddr, 1)
|
||||
for i in range(20):
|
||||
test.nodes[1].sendtoaddress(n2taddr, 1)
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Merging the 800 UTXOs will occur over two transactions, since max tx size is 100,000 bytes.
|
||||
# We don't verify mergingTransparentValue as UTXOs are not selected in any specific order, so value can change on each test run.
|
||||
# We set an unrealistically high limit parameter of 99999, to verify that max tx size will constrain the number of UTXOs.
|
||||
result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, 0, 99999)
|
||||
assert_equal(result["mergingUTXOs"], Decimal('662'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('138'))
|
||||
assert_equal(result["mergingNotes"], Decimal('0'))
|
||||
assert_equal(result["mergingShieldedValue"], Decimal('0'))
|
||||
assert_equal(result["remainingNotes"], Decimal('0'))
|
||||
assert_equal(result["remainingShieldedValue"], Decimal('0'))
|
||||
remainingTransparentValue = result["remainingTransparentValue"]
|
||||
opid1 = result['opid']
|
||||
|
||||
# Verify that UTXOs are locked (not available for selection) by queuing up another merging operation
|
||||
result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, 0, 0)
|
||||
assert_equal(result["mergingUTXOs"], Decimal('138'))
|
||||
assert_equal(result["mergingTransparentValue"], Decimal(remainingTransparentValue))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('0'))
|
||||
assert_equal(result["remainingTransparentValue"], Decimal('0'))
|
||||
assert_equal(result["mergingNotes"], Decimal('0'))
|
||||
assert_equal(result["mergingShieldedValue"], Decimal('0'))
|
||||
assert_equal(result["remainingNotes"], Decimal('0'))
|
||||
assert_equal(result["remainingShieldedValue"], Decimal('0'))
|
||||
opid2 = result['opid']
|
||||
|
||||
# wait for both aysnc operations to complete
|
||||
wait_and_assert_operationid_status(test.nodes[0], opid1)
|
||||
wait_and_assert_operationid_status(test.nodes[0], opid2)
|
||||
|
||||
# sync_all() invokes sync_mempool() but node 2's mempool limit will cause tx1 and tx2 to be rejected.
|
||||
# So instead, we sync on blocks and mempool for node 0 and node 1, and after a new block is generated
|
||||
# which mines tx1 and tx2, all nodes will have an empty mempool which can then be synced.
|
||||
sync_blocks(test.nodes[:2])
|
||||
sync_mempools(test.nodes[:2])
|
||||
# Generate enough blocks to ensure all transactions are mined
|
||||
while test.nodes[1].getmempoolinfo()['size'] > 0:
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Verify maximum number of UTXOs which node 2 can shield is limited by option -mempooltxinputlimit
|
||||
# This option is used when the limit parameter is set to 0.
|
||||
result = test.nodes[2].z_mergetoaddress([n2taddr], myzaddr, Decimal('0.0001'), 0)
|
||||
assert_equal(result["mergingUTXOs"], Decimal('7'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('13'))
|
||||
assert_equal(result["mergingNotes"], Decimal('0'))
|
||||
assert_equal(result["remainingNotes"], Decimal('0'))
|
||||
wait_and_assert_operationid_status(test.nodes[2], result['opid'])
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Verify maximum number of UTXOs which node 0 can shield is set by default limit parameter of 50
|
||||
mytaddr = test.nodes[0].getnewaddress()
|
||||
for i in range(100):
|
||||
test.nodes[1].sendtoaddress(mytaddr, 1)
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, Decimal('0.0001'))
|
||||
assert_equal(result["mergingUTXOs"], Decimal('50'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('50'))
|
||||
assert_equal(result["mergingNotes"], Decimal('0'))
|
||||
# Remaining notes are only counted if we are trying to merge any notes
|
||||
assert_equal(result["remainingNotes"], Decimal('0'))
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
|
||||
# Verify maximum number of UTXOs which node 0 can shield can be set by the limit parameter
|
||||
result = test.nodes[0].z_mergetoaddress([mytaddr], myzaddr, Decimal('0.0001'), 33)
|
||||
assert_equal(result["mergingUTXOs"], Decimal('33'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('17'))
|
||||
assert_equal(result["mergingNotes"], Decimal('0'))
|
||||
# Remaining notes are only counted if we are trying to merge any notes
|
||||
assert_equal(result["remainingNotes"], Decimal('0'))
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
# Don't sync node 2 which rejects the tx due to its mempooltxinputlimit
|
||||
sync_blocks(test.nodes[:2])
|
||||
sync_mempools(test.nodes[:2])
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Verify maximum number of notes which node 0 can shield can be set by the limit parameter
|
||||
# Also check that we can set off a second merge before the first one is complete
|
||||
|
||||
# myzaddr has 5 notes at this point
|
||||
result1 = test.nodes[0].z_mergetoaddress([myzaddr], myzaddr, 0.0001, 50, 2)
|
||||
result2 = test.nodes[0].z_mergetoaddress([myzaddr], myzaddr, 0.0001, 50, 2)
|
||||
|
||||
# First merge should select from all notes
|
||||
assert_equal(result1["mergingUTXOs"], Decimal('0'))
|
||||
# Remaining UTXOs are only counted if we are trying to merge any UTXOs
|
||||
assert_equal(result1["remainingUTXOs"], Decimal('0'))
|
||||
assert_equal(result1["mergingNotes"], Decimal('2'))
|
||||
assert_equal(result1["remainingNotes"], Decimal('3'))
|
||||
|
||||
# Second merge should ignore locked notes
|
||||
assert_equal(result2["mergingUTXOs"], Decimal('0'))
|
||||
assert_equal(result2["remainingUTXOs"], Decimal('0'))
|
||||
assert_equal(result2["mergingNotes"], Decimal('2'))
|
||||
assert_equal(result2["remainingNotes"], Decimal('1'))
|
||||
wait_and_assert_operationid_status(test.nodes[0], result1['opid'])
|
||||
wait_and_assert_operationid_status(test.nodes[0], result2['opid'])
|
||||
|
||||
test.sync_all()
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
||||
|
||||
# Shield both UTXOs and notes to a z-addr
|
||||
result = test.nodes[0].z_mergetoaddress(["*"], myzaddr, 0, 10, 2)
|
||||
assert_equal(result["mergingUTXOs"], Decimal('10'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('7'))
|
||||
assert_equal(result["mergingNotes"], Decimal('2'))
|
||||
assert_equal(result["remainingNotes"], Decimal('1'))
|
||||
wait_and_assert_operationid_status(test.nodes[0], result['opid'])
|
||||
# Don't sync node 2 which rejects the tx due to its mempooltxinputlimit
|
||||
sync_blocks(test.nodes[:2])
|
||||
sync_mempools(test.nodes[:2])
|
||||
test.nodes[1].generate(1)
|
||||
test.sync_all()
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2017 The Zcash developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from mergetoaddress_helper import MergeToAddressHelper
|
||||
|
||||
|
||||
class MergeToAddressSapling (BitcoinTestFramework):
|
||||
helper = MergeToAddressHelper()
|
||||
|
||||
def setup_chain(self):
|
||||
self.helper.setup_chain(self)
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.helper.setup_network(self, [
|
||||
'-nuparams=5ba81b19:100', # Overwinter
|
||||
'-nuparams=76b809bb:100', # Sapling
|
||||
])
|
||||
|
||||
def run_test(self):
|
||||
self.helper.run_test(self, 'sapling')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
MergeToAddressSapling().main()
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2017 The Zcash developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from mergetoaddress_helper import MergeToAddressHelper
|
||||
|
||||
|
||||
class MergeToAddressSprout (BitcoinTestFramework):
|
||||
helper = MergeToAddressHelper()
|
||||
|
||||
def setup_chain(self):
|
||||
self.helper.setup_chain(self)
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.helper.setup_network(self)
|
||||
|
||||
def run_test(self):
|
||||
self.helper.run_test(self, 'sprout')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
MergeToAddressSprout().main()
|
Loading…
Reference in New Issue