From df9fc17f57d98077c468294b9f347fe614f90b78 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Mon, 27 Apr 2020 20:00:18 +0200 Subject: [PATCH] [QA][Bug] Shorter wallet_basic.py functional test --- test/functional/test_framework/util.py | 4 +- test/functional/test_runner.py | 4 +- test/functional/wallet_basic.py | 126 ++++++------------------ test/functional/wallet_zapwallettxes.py | 30 ++++-- 4 files changed, 53 insertions(+), 111 deletions(-) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index ed91eda474268..5484bcff18280 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -28,10 +28,10 @@ def assert_fee_amount(fee, tx_size, fee_per_kB): """Assert the fee was in range""" target_fee = round(tx_size * fee_per_kB / 1000, 8) if fee < target_fee: - raise AssertionError("Fee of %s BTC too low! (Should be %s BTC)" % (str(fee), str(target_fee))) + raise AssertionError("Fee of %s PIV too low! (Should be %s PIV)" % (str(fee), str(target_fee))) # allow the wallet's estimation to be at most 2 bytes off if fee > (tx_size + 20) * fee_per_kB / 1000: - raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)" % (str(fee), str(target_fee))) + raise AssertionError("Fee of %s PIV too high! (Should be %s PIV)" % (str(fee), str(target_fee))) def assert_equal(thing1, thing2, *args): if thing1 != thing2 or any(thing1 != arg for arg in args): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 75c6ec399bad9..6eca61693b96e 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -56,10 +56,11 @@ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel - 'wallet_basic.py', # ~ 833 sec + 'wallet_basic.py', # ~ 498 sec 'wallet_backup.py', # ~ 477 sec # vv Tests less than 5m vv + 'wallet_zapwallettxes.py', # ~ 300 sec 'p2p_time_offset.py', # ~ 267 sec 'mining_pos_coldStaking.py', # ~ 215 sec 'mining_pos_reorg.py', # ~ 212 sec @@ -68,7 +69,6 @@ 'wallet_zerocoin_publicspends.py', # ~ 202 sec 'feature_logging.py', # ~ 200 sec 'rpc_rawtransaction.py', # ~ 193 sec - 'wallet_zapwallettxes.py', # ~ 180 sec 'wallet_keypool_topup.py', # ~ 174 sec 'wallet_txn_doublespend.py --mineblock', # ~ 157 sec 'wallet_txn_clone.py --mineblock', # ~ 157 sec diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index be264bc8e3717..70165891c0909 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -11,8 +11,6 @@ assert_raises_rpc_error, connect_nodes, Decimal, - sync_blocks, - sync_mempools, wait_until, ) @@ -31,14 +29,6 @@ def setup_network(self): connect_nodes(self.nodes[0], 2) self.sync_all([self.nodes[0:3]]) - def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size): - """Return curr_balance after asserting the fee was in range""" - fee = balance_with_fee - curr_balance - fee2 = round(tx_size * fee_per_byte / 1000, 8) - self.log.info("current: %s, withfee: %s, perByte: %s, size: %s, fee: %s" % (str(curr_balance), str(balance_with_fee), str(fee_per_byte), str(tx_size), str(fee2))) - assert_fee_amount(fee, tx_size, fee_per_byte * 1000) - return curr_balance - def get_vsize(self, txn): return self.nodes[0].decoderawtransaction(txn)['size'] @@ -70,36 +60,23 @@ def run_test(self): assert_equal(len(self.nodes[1].listunspent()), 1) assert_equal(len(self.nodes[2].listunspent()), 0) - # Send 21 PIV from 0 to 2 using sendtoaddress call. - # Second transaction will be child of first, and will require a fee - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 21) - #self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - walletinfo = self.nodes[0].getwalletinfo() assert_equal(walletinfo['immature_balance'], 0) - # Have node0 mine a block, thus it will collect its own fee. - self.nodes[0].generate(1) - self.sync_all([self.nodes[0:3]]) - # Exercise locking of unspent outputs - unspent_0 = self.nodes[2].listunspent()[0] + unspent_0 = self.nodes[1].listunspent()[0] unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]} - self.nodes[2].lockunspent(False, [unspent_0]) - assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20) - assert_equal([unspent_0], self.nodes[2].listlockunspent()) - self.nodes[2].lockunspent(True, [unspent_0]) - assert_equal(len(self.nodes[2].listlockunspent()), 0) - - # Have node1 generate 100 blocks (so node0 can recover the fee) - self.nodes[1].generate(100) + self.nodes[1].lockunspent(False, [unspent_0]) + assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[1].sendtoaddress, self.nodes[1].getnewaddress(), 20) + assert_equal([unspent_0], self.nodes[1].listlockunspent()) + self.nodes[1].lockunspent(True, [unspent_0]) + assert_equal(len(self.nodes[1].listlockunspent()), 0) + + # Send 21 PIV from 1 to 0 using sendtoaddress call. + self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 21) + self.nodes[1].generate(1) self.sync_all([self.nodes[0:3]]) - # node0 should end up with 100 PIV in block rewards plus fees, but - # minus the 21 plus fees sent to node2 - assert_equal(self.nodes[0].getbalance(), 500-21) - assert_equal(self.nodes[2].getbalance(), 21) - # Node0 should have two unspent outputs. # Create a couple of transactions to send them to node2, submit them through # node1, and make sure both node0 and node2 pick them up properly: @@ -107,12 +84,13 @@ def run_test(self): assert_equal(len(node0utxos), 2) # create both transactions + fee_per_kbyte = Decimal('0.001') txns_to_send = [] for utxo in node0utxos: inputs = [] outputs = {} inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]}) - outputs[self.nodes[2].getnewaddress("from1")] = float(utxo["amount"]) + outputs[self.nodes[2].getnewaddress("from1")] = float(utxo["amount"]) - float(fee_per_kbyte) raw_tx = self.nodes[0].createrawtransaction(inputs, outputs) txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx)) @@ -125,77 +103,33 @@ def run_test(self): self.sync_all([self.nodes[0:3]]) assert_equal(self.nodes[0].getbalance(), 0) - assert_equal(self.nodes[2].getbalance(), 500) - assert_equal(self.nodes[2].getbalance("from1"), 500-21) + node_2_expected_bal = Decimal('250') + Decimal('21') - 2 * fee_per_kbyte + node_2_bal = self.nodes[2].getbalance() + assert_equal(node_2_bal, node_2_expected_bal) + assert_equal(self.nodes[2].getbalance("from1"), node_2_expected_bal) # Send 10 PIV normal address = self.nodes[0].getnewaddress("test") - fee_per_byte = Decimal('0.001') / 1000 - self.nodes[2].settxfee(float(fee_per_byte * 1000)) + self.nodes[2].settxfee(float(fee_per_kbyte)) txid = self.nodes[2].sendtoaddress(address, 10, "", "") fee = self.nodes[2].gettransaction(txid)["fee"] + node_2_bal -= (Decimal('10') - fee) + assert_equal(self.nodes[2].getbalance(), node_2_bal) self.nodes[2].generate(1) self.sync_all([self.nodes[0:3]]) - node_2_bal = self.nodes[2].getbalance() - assert_equal(self.nodes[0].getbalance(), Decimal('10')) - - # Send 10 PIV with subtract fee from amount - txid = self.nodes[2].sendtoaddress(address, 10, "", "") - self.nodes[2].generate(1) - self.sync_all([self.nodes[0:3]]) - node_2_bal -= Decimal('10') - assert_equal(self.nodes[2].getbalance() - fee, node_2_bal) node_0_bal = self.nodes[0].getbalance() - assert_equal(node_0_bal, Decimal('20')) + assert_equal(node_0_bal, Decimal('10')) # Sendmany 10 PIV txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "") + fee = self.nodes[2].gettransaction(txid)["fee"] self.nodes[2].generate(1) self.sync_all([self.nodes[0:3]]) node_0_bal += Decimal('10') - node_2_bal -= Decimal('10') - #node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) + node_2_bal -= (Decimal('10') - fee) + assert_equal(self.nodes[2].getbalance(), node_2_bal) assert_equal(self.nodes[0].getbalance(), node_0_bal) - - # Sendmany 10 PIV with subtract fee from amount - txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "") - self.nodes[2].generate(1) - self.sync_all([self.nodes[0:3]]) - node_2_bal -= Decimal('10') - assert_equal(self.nodes[2].getbalance(), node_2_bal + (fee * 3)) - #node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) - - # Test ResendWalletTransactions: - # Create a couple of transactions, then start up a fourth - # node (nodes[3]) and ask nodes[0] to rebroadcast. - # EXPECT: nodes[3] should have those transactions in its mempool. - txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1) - txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) - sync_mempools(self.nodes[0:2]) - - self.start_node(3) - connect_nodes(self.nodes[0], 3) - sync_blocks(self.nodes) - - # Exercise balance rpcs - assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1) - assert_equal(self.nodes[0].getunconfirmedbalance(), 1) - - #check if we can list zero value tx as available coins - #1. create rawtx - #2. hex-changed one output to 0.0 - #3. sign and send - #4. check if recipient (node0) can list the zero value tx - usp = self.nodes[1].listunspent() - inputs = [{"txid":usp[0]['txid'], "vout":usp[0]['vout']}] - outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11} - - rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") #replace 11.11 with 0.0 (int32) - decRawTx = self.nodes[1].decoderawtransaction(rawTx) - signedRawTx = self.nodes[1].signrawtransaction(rawTx) - decRawTx = self.nodes[1].decoderawtransaction(signedRawTx['hex']) - zeroValueTxid= decRawTx['txid'] - assert_raises_rpc_error(-25, "", self.nodes[1].sendrawtransaction, signedRawTx['hex']) + assert_fee_amount(-fee, self.get_vsize(self.nodes[2].getrawtransaction(txid)), fee_per_kbyte) # This will raise an exception since generate does not accept a string assert_raises_rpc_error(-1, "not an integer", self.nodes[0].generate, "2") @@ -203,7 +137,7 @@ def run_test(self): # Import address and private key to check correct behavior of spendable unspents # 1. Send some coins to generate new UTXO address_to_import = self.nodes[2].getnewaddress() - txid = self.nodes[0].sendtoaddress(address_to_import, 1) + self.nodes[0].sendtoaddress(address_to_import, 1) self.nodes[0].generate(1) self.sync_all([self.nodes[0:3]]) @@ -238,18 +172,14 @@ def run_test(self): maintenance = [ '-rescan', '-reindex', - '-zapwallettxes=1', - '-zapwallettxes=2', - #'-salvagewallet', ] - chainlimit = 6 for m in maintenance: self.log.info("check " + m) self.stop_nodes() # set lower ancestor limit for later - self.start_node(0, [m, "-limitancestorcount="+str(chainlimit)]) - self.start_node(1, [m, "-limitancestorcount="+str(chainlimit)]) - self.start_node(2, [m, "-limitancestorcount="+str(chainlimit)]) + self.start_node(0, [m]) + self.start_node(1, [m]) + self.start_node(2, [m]) if m == '-reindex': # reindex will leave rpc warm up "early"; Wait for it to finish wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)]) diff --git a/test/functional/wallet_zapwallettxes.py b/test/functional/wallet_zapwallettxes.py index 4c6f187714c41..19afe606810fd 100755 --- a/test/functional/wallet_zapwallettxes.py +++ b/test/functional/wallet_zapwallettxes.py @@ -18,7 +18,7 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, - wait_until, + sync_mempools, ) class ZapWalletTXesTest (PivxTestFramework): @@ -40,31 +40,43 @@ def run_test(self): self.sync_all() self.nodes[0].generate(1) self.sync_all() + balance_nodes = [self.nodes[i].getbalance() for i in range(self.num_nodes)] # This transaction will not be confirmed txid2 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 20) + sync_mempools(self.nodes, wait=.1) # Confirmed and unconfirmed transactions are now in the wallet. assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) + # Exercise balance rpcs + assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], 20) + assert_equal(self.nodes[1].getunconfirmedbalance(), 20) + # Stop-start node0. Both confirmed and unconfirmed transactions remain in the wallet. self.stop_node(0) self.start_node(0) - assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) - # Stop node0 and restart with zapwallettxes and persistmempool. The unconfirmed + # Stop nodes and restart with zapwallettxes and persistmempool. The unconfirmed # transaction is zapped from the wallet, but is re-added when the mempool is reloaded. - self.stop_node(0) - self.start_node(0, ["-zapwallettxes=2"]) + # original balances are restored + for i in range(1, 3): + self.log.info("Restarting with --zapwallettxes=%d" % i) + self.stop_nodes() + self.start_node(0, ["-zapwallettxes=%d" % i]) + self.start_node(1, ["-zapwallettxes=%d" % i]) - # tx1 is still be available because it was confirmed - assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) + # tx1 is still be available because it was confirmed + assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) + + # This will raise an exception because the unconfirmed transaction has been zapped + assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', self.nodes[0].gettransaction, txid2) - # This will raise an exception because the unconfirmed transaction has been zapped - assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', self.nodes[0].gettransaction, txid2) + # Check (confirmed) balances + assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(self.num_nodes)]) if __name__ == '__main__': ZapWalletTXesTest().main()