From d7d6480ce35893de1342f050f793cba81c853692 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Tue, 11 Sep 2018 14:51:38 -0600 Subject: [PATCH] z_listunspent rpc unit test: add testing for Sapling --- qa/rpc-tests/wallet_listnotes.py | 155 ++++++++++++++++++++++++------- 1 file changed, 120 insertions(+), 35 deletions(-) diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index f839b1ffd..32997df43 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -20,65 +20,150 @@ class WalletListNotes(BitcoinTestFramework): def run_test(self): # Current height = 200 -> Sprout + assert_equal(200, self.nodes[0].getblockcount()) sproutzaddr = self.nodes[0].z_getnewaddress('sprout') + + # test that we can create a sapling zaddr before sapling activates saplingzaddr = self.nodes[0].z_getnewaddress('sapling') - print "sprout zaddr", sproutzaddr - print "saplingzaddr", saplingzaddr + + # we've got lots of coinbase (taddr) but no shielded funds yet + assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - # Current height = 201 -> Sprout + # Set current height to 201 -> Sprout self.nodes[0].generate(1) self.sync_all() - + assert_equal(201, self.nodes[0].getblockcount()) + mining_addr = self.nodes[0].listunspent()[0]['address'] - # Shield coinbase funds - recipients = [] - recipients.append({"address":sproutzaddr, "amount":Decimal('10.0')-Decimal('0.0001')}) # utxo amount less fee + + # Shield coinbase funds (must be a multiple of 10, no change allowed pre-sapling) + receive_amount_10 = Decimal('10.0') - Decimal('0.0001') + recipients = [{"address":sproutzaddr, "amount":receive_amount_10}] myopid = self.nodes[0].z_sendmany(mining_addr, recipients) txid_1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + self.sync_all() - # No funds in sproutzaddr yet - assert_equal(set(self.nodes[0].z_listunspent()), set()) + # 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))) - print self.nodes[0].z_gettotalbalance() # no private balance displayed bc no confirmations yet + # no private balance because no confirmations yet + assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - # list unspent, allowing 0 confirmations + # list private unspent, this time allowing 0 confirmations unspent_cb = self.nodes[0].z_listunspent(0) - # list unspent, filtering by address - unspent_cb_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr]) + assert_equal(1, len(unspent_cb)) + assert_equal(False, unspent_cb[0]['change']) + assert_equal(txid_1, unspent_cb[0]['txid']) + assert_equal(True, unspent_cb[0]['spendable']) + assert_equal(sproutzaddr, unspent_cb[0]['address']) + assert_equal(receive_amount_10, 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) - assert_equal(len(unspent_cb), 1) - assert_equal(unspent_cb[0]['change'], False) - assert_equal(unspent_cb[0]['txid'], txid_1) - assert_equal(unspent_cb[0]['spendable'], True) - assert_equal(unspent_cb[0]['address'], sproutzaddr) - assert_equal(unspent_cb[0]['amount'], Decimal('10.0')-Decimal('0.0001')) - # Generate a block to confirm shield coinbase tx - # Current height = 202 -> Overwinter. Default address type is Sprout + # Generate a block to confirm shield coinbase tx self.nodes[0].generate(1) self.sync_all() - sproutzaddr2 = self.nodes[0].z_getnewaddress('sprout') - recipients = [{"address": sproutzaddr2, "amount":Decimal('1.0')-Decimal('0.0001')}] + # Current height = 202 -> Overwinter. Default address type remains Sprout + assert_equal(202, self.nodes[0].getblockcount()) + + # Send 1.0 (actually 0.9999) from sproutzaddr to a new zaddr + sproutzaddr2 = self.nodes[0].z_getnewaddress() + receive_amount_1 = Decimal('1.0') - Decimal('0.0001') + change_amount_9 = receive_amount_10 - Decimal('1.0') + assert_equal('sprout', self.nodes[0].z_validateaddress(sproutzaddr2)['type']) + recipients = [{"address": sproutzaddr2, "amount":receive_amount_1}] myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients) 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) - unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr2]) assert_equal(len(unspent_tx), 2) - assert_equal(unspent_tx[0]['change'], False) - assert_equal(unspent_tx[0]['txid'], txid_2) - assert_equal(unspent_tx[0]['spendable'], True) - assert_equal(unspent_tx[0]['address'], sproutzaddr2) - assert_equal(unspent_tx[0]['amount'], Decimal('1.0')-Decimal('0.0001')) - # TODO: test change + # 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(True, unspent_tx[0]['spendable']) + assert_equal(sproutzaddr2, unspent_tx[0]['address']) + assert_equal(receive_amount_1, unspent_tx[0]['amount']) + + assert_equal(True, unspent_tx[1]['change']) + assert_equal(txid_2, unspent_tx[1]['txid']) + assert_equal(True, unspent_tx[1]['spendable']) + assert_equal(sproutzaddr, unspent_tx[1]['address']) + assert_equal(change_amount_9, unspent_tx[1]['amount']) + + unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr2]) + 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]) + + # Set current height to 204 -> Sapling + self.nodes[0].generate(2) + self.sync_all() + assert_equal(204, self.nodes[0].getblockcount()) # No funds in saplingzaddr yet - assert_equal(set(self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr])), set()) - - # Current height = 204 -> Sapling - # self.nodes[0].generate(2) + assert_equal(0, len(self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr]))) + + # Send 0.9999 to our sapling zaddr + # (sending from a sprout zaddr to a sapling zaddr is disallowed, + # so send from coin base) + receive_amount_2 = Decimal('2.0') - Decimal('0.0001') + recipients = [{"address": saplingzaddr, "amount":receive_amount_2}] + myopid = self.nodes[0].z_sendmany(mining_addr, recipients) + 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(True, unspent_tx[0]['spendable']) + assert_equal(sproutzaddr2, unspent_tx[0]['address']) + assert_equal(receive_amount_1, unspent_tx[0]['amount']) + + assert_equal(False, unspent_tx[1]['change']) + assert_equal(txid_3, unspent_tx[1]['txid']) + assert_equal(True, unspent_tx[1]['spendable']) + assert_equal(saplingzaddr, unspent_tx[1]['address']) + assert_equal(receive_amount_2, unspent_tx[1]['amount']) + + assert_equal(True, unspent_tx[2]['change']) + assert_equal(txid_2, unspent_tx[2]['txid']) + assert_equal(True, unspent_tx[2]['spendable']) + assert_equal(sproutzaddr, unspent_tx[2]['address']) + assert_equal(change_amount_9, 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[1], 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[1], 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 if __name__ == '__main__': - WalletListNotes().main() \ No newline at end of file + WalletListNotes().main()