zcashd/qa/rpc-tests/wallet_listnotes.py

222 lines
10 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
NU5_BRANCH_ID,
assert_equal,
assert_true,
get_coinbase_address,
nuparams,
start_nodes,
wait_and_assert_operationid_status,
DEFAULT_FEE
)
from decimal import Decimal
# Test wallet z_listunspent behaviour across network upgrades
class WalletListNotes(BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, [[
nuparams(NU5_BRANCH_ID, 215),
]] * 4)
def run_test(self):
# Current height = 200 -> Sapling
assert_equal(200, self.nodes[0].getblockcount())
sproutzaddr = self.nodes[0].z_getnewaddress('sprout')
# we've got lots of coinbase (taddr) but no shielded funds yet
assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private']))
# Set current height to 201
self.nodes[0].generate(1)
self.sync_all()
assert_equal(201, self.nodes[0].getblockcount())
# Shield one coinbase output
receive_amount_1 = Decimal('10.0') - DEFAULT_FEE
result = self.nodes[0].z_shieldcoinbase('*', sproutzaddr, DEFAULT_FEE, 1)
txid_1 = wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.sync_all()
# No funds (with (default) one or more confirmations) in sproutzaddr yet
assert_equal(0, len(self.nodes[0].z_listunspent()))
assert_equal(0, len(self.nodes[0].z_listunspent(1)))
# no private balance because no confirmations yet
assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private']))
# list private unspent, this time allowing 0 confirmations
unspent_cb = self.nodes[0].z_listunspent(0)
assert_equal(1, len(unspent_cb))
assert_equal(False, unspent_cb[0]['change'])
assert_equal(txid_1, unspent_cb[0]['txid'])
assert_equal('sprout', unspent_cb[0]['pool'])
assert_equal(True, unspent_cb[0]['spendable'])
assert_equal(sproutzaddr, unspent_cb[0]['address'])
assert_equal(receive_amount_1, unspent_cb[0]['amount'])
# list unspent, filtering by address, should produce same result
unspent_cb_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr])
assert_equal(unspent_cb, unspent_cb_filter)
# Generate a block to confirm shield coinbase tx
self.nodes[0].generate(1)
self.sync_all()
# Current height = 202
assert_equal(202, self.nodes[0].getblockcount())
# Send 1.0 minus default fee from sproutzaddr to a new Sapling zaddr
saplingzaddr = self.nodes[0].z_getnewaddress('sapling')
receive_amount_2 = Decimal('1.0')
change_amount_2 = receive_amount_1 - receive_amount_2 - DEFAULT_FEE
assert_equal('sapling', self.nodes[0].z_validateaddress(saplingzaddr)['type'])
recipients = [{"address": saplingzaddr, "amount":receive_amount_2}]
myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, DEFAULT_FEE)
txid_2 = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
# list unspent, allowing 0conf txs
unspent_tx = self.nodes[0].z_listunspent(0)
assert_equal(len(unspent_tx), 2)
# sort low-to-high by amount (order of returned entries is not guaranteed)
unspent_tx = sorted(unspent_tx, key=lambda k: k['amount'])
assert_equal(False, unspent_tx[0]['change'])
assert_equal(txid_2, unspent_tx[0]['txid'])
assert_equal('sapling', unspent_tx[0]['pool'])
assert_equal(True, unspent_tx[0]['spendable'])
assert_equal(saplingzaddr, unspent_tx[0]['address'])
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
assert_equal(True, unspent_tx[1]['change'])
assert_equal(txid_2, unspent_tx[1]['txid'])
assert_equal('sprout', unspent_tx[1]['pool'])
assert_equal(True, unspent_tx[1]['spendable'])
assert_equal(sproutzaddr, unspent_tx[1]['address'])
assert_equal(change_amount_2, unspent_tx[1]['amount'])
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr])
assert_equal(1, len(unspent_tx_filter))
assert_equal(unspent_tx[0], unspent_tx_filter[0])
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr])
assert_equal(1, len(unspent_tx_filter))
assert_equal(unspent_tx[1], unspent_tx_filter[0])
self.nodes[0].generate(1)
self.sync_all()
# Send 2.0 minus default fee to a new sapling zaddr
saplingzaddr2 = self.nodes[0].z_getnewaddress('sapling')
receive_amount_3 = Decimal('2.0')
change_amount_3 = change_amount_2 - receive_amount_3 - DEFAULT_FEE
recipients = [{"address": saplingzaddr2, "amount":receive_amount_3}]
myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, DEFAULT_FEE)
txid_3 = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
unspent_tx = self.nodes[0].z_listunspent(0)
assert_equal(3, len(unspent_tx))
# low-to-high in amount
unspent_tx = sorted(unspent_tx, key=lambda k: k['amount'])
assert_equal(False, unspent_tx[0]['change'])
assert_equal(txid_2, unspent_tx[0]['txid'])
assert_equal('sapling', unspent_tx[0]['pool'])
assert_equal(True, unspent_tx[0]['spendable'])
assert_equal(saplingzaddr, unspent_tx[0]['address'])
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
assert_equal(False, unspent_tx[1]['change'])
assert_equal(txid_3, unspent_tx[1]['txid'])
assert_equal('sapling', unspent_tx[1]['pool'])
assert_equal(True, unspent_tx[1]['spendable'])
assert_equal(saplingzaddr2, unspent_tx[1]['address'])
assert_equal(receive_amount_3, unspent_tx[1]['amount'])
assert_equal(True, unspent_tx[2]['change'])
assert_equal(txid_3, unspent_tx[2]['txid'])
assert_equal('sprout', unspent_tx[2]['pool'])
assert_equal(True, unspent_tx[2]['spendable'])
assert_equal(sproutzaddr, unspent_tx[2]['address'])
assert_equal(change_amount_3, unspent_tx[2]['amount'])
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr])
assert_equal(1, len(unspent_tx_filter))
assert_equal(unspent_tx[0], unspent_tx_filter[0])
# test that pre- and post-sapling can be filtered in a single call
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False,
[sproutzaddr, saplingzaddr])
assert_equal(2, len(unspent_tx_filter))
unspent_tx_filter = sorted(unspent_tx_filter, key=lambda k: k['amount'])
assert_equal(unspent_tx[0], unspent_tx_filter[0])
assert_equal(unspent_tx[2], unspent_tx_filter[1])
# so far, this node has no watchonly addresses, so results are the same
unspent_tx_watchonly = self.nodes[0].z_listunspent(0, 9999, True)
unspent_tx_watchonly = sorted(unspent_tx_watchonly, key=lambda k: k['amount'])
assert_equal(unspent_tx, unspent_tx_watchonly)
# TODO: use z_exportviewingkey, z_importviewingkey to test includeWatchonly
# but this requires Sapling support for those RPCs
# Set current height to 215 -> NU5
self.nodes[0].generate(12)
self.sync_all()
assert_equal(215, self.nodes[0].getblockcount())
# Create an Orchard note.
account0 = self.nodes[0].z_getnewaccount()['account']
ua0 = self.nodes[0].z_getaddressforaccount(account0)['address']
receive_amount_4 = Decimal('10.0')
recipients = [{"address": ua0, "amount": receive_amount_4}]
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
txid_4 = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
unspent_tx = self.nodes[0].z_listunspent(0)
assert_equal(4, len(unspent_tx))
# low-to-high in amount
unspent_tx = sorted(unspent_tx, key=lambda k: k['amount'])
assert_equal(False, unspent_tx[0]['change'])
assert_equal(txid_2, unspent_tx[0]['txid'])
assert_equal('sapling', unspent_tx[0]['pool'])
assert_equal(True, unspent_tx[0]['spendable'])
assert_true('account' not in unspent_tx[0])
assert_equal(saplingzaddr, unspent_tx[0]['address'])
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
assert_equal(False, unspent_tx[1]['change'])
assert_equal(txid_3, unspent_tx[1]['txid'])
assert_equal('sapling', unspent_tx[1]['pool'])
assert_equal(True, unspent_tx[1]['spendable'])
assert_true('account' not in unspent_tx[1])
assert_equal(saplingzaddr2, unspent_tx[1]['address'])
assert_equal(receive_amount_3, unspent_tx[1]['amount'])
assert_equal(True, unspent_tx[2]['change'])
assert_equal(txid_3, unspent_tx[2]['txid'])
assert_equal('sprout', unspent_tx[2]['pool'])
assert_equal(True, unspent_tx[2]['spendable'])
assert_true('account' not in unspent_tx[2])
assert_equal(sproutzaddr, unspent_tx[2]['address'])
assert_equal(change_amount_3, unspent_tx[2]['amount'])
assert_equal(False, unspent_tx[3]['change'])
assert_equal(txid_4, unspent_tx[3]['txid'])
assert_equal('orchard', unspent_tx[3]['pool'])
assert_equal(True, unspent_tx[3]['spendable'])
assert_equal(account0, unspent_tx[3]['account'])
assert_equal(ua0, unspent_tx[3]['address'])
assert_equal(receive_amount_4, unspent_tx[3]['amount'])
if __name__ == '__main__':
WalletListNotes().main()