Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_basic.py
Show All 33 Lines | def setup_network(self): | ||||
self.start_node(0) | self.start_node(0) | ||||
self.start_node(1) | self.start_node(1) | ||||
self.start_node(2) | self.start_node(2) | ||||
connect_nodes_bi(self.nodes[0], self.nodes[1]) | connect_nodes_bi(self.nodes[0], self.nodes[1]) | ||||
connect_nodes_bi(self.nodes[1], self.nodes[2]) | connect_nodes_bi(self.nodes[1], self.nodes[2]) | ||||
connect_nodes_bi(self.nodes[0], self.nodes[2]) | connect_nodes_bi(self.nodes[0], self.nodes[2]) | ||||
self.sync_all([self.nodes[0:3]]) | self.sync_all([self.nodes[0:3]]) | ||||
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size): | 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""" | """Return curr_balance after asserting the fee was in range""" | ||||
fee = balance_with_fee - curr_balance | fee = balance_with_fee - curr_balance | ||||
assert_fee_amount(fee, tx_size, fee_per_byte * 1000) | assert_fee_amount(fee, tx_size, fee_per_byte * 1000) | ||||
return curr_balance | return curr_balance | ||||
def run_test(self): | def run_test(self): | ||||
# Check that there's no UTXO on none of the nodes | # Check that there's no UTXO on none of the nodes | ||||
assert_equal(len(self.nodes[0].listunspent()), 0) | assert_equal(len(self.nodes[0].listunspent()), 0) | ||||
▲ Show 20 Lines • Show All 248 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
txIdNotBroadcasted = self.nodes[0].sendtoaddress( | txIdNotBroadcasted = self.nodes[0].sendtoaddress( | ||||
self.nodes[2].getnewaddress(), 2) | self.nodes[2].getnewaddress(), 2) | ||||
txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted) | txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted) | ||||
self.nodes[1].generate(1) # mine a block, tx should not be in there | self.nodes[1].generate(1) # mine a block, tx should not be in there | ||||
self.sync_all([self.nodes[0:3]]) | self.sync_all([self.nodes[0:3]]) | ||||
# should not be changed because tx was not broadcasted | # should not be changed because tx was not broadcasted | ||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) | assert_equal(self.nodes[2].getbalance(), node_2_bal) | ||||
# now broadcast from another node, mine a block, sync, and check the balance | # now broadcast from another node, mine a block, sync, and check the | ||||
# balance | |||||
self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex']) | self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex']) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
self.sync_all([self.nodes[0:3]]) | self.sync_all([self.nodes[0:3]]) | ||||
node_2_bal += 2 | node_2_bal += 2 | ||||
txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted) | txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted) | ||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) | assert_equal(self.nodes[2].getbalance(), node_2_bal) | ||||
# create another tx | # create another tx | ||||
Show All 9 Lines | def run_test(self): | ||||
connect_nodes_bi(self.nodes[1], self.nodes[2]) | connect_nodes_bi(self.nodes[1], self.nodes[2]) | ||||
connect_nodes_bi(self.nodes[0], self.nodes[2]) | connect_nodes_bi(self.nodes[0], self.nodes[2]) | ||||
sync_blocks(self.nodes[0:3]) | sync_blocks(self.nodes[0:3]) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
sync_blocks(self.nodes[0:3]) | sync_blocks(self.nodes[0:3]) | ||||
node_2_bal += 2 | node_2_bal += 2 | ||||
# tx should be added to balance because after restarting the nodes tx should be broadcasted | # tx should be added to balance because after restarting the nodes tx | ||||
# should be broadcasted | |||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) | assert_equal(self.nodes[2].getbalance(), node_2_bal) | ||||
# send a tx with value in a string (PR#6380 +) | # send a tx with value in a string (PR#6380 +) | ||||
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2") | txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2") | ||||
txObj = self.nodes[0].gettransaction(txId) | txObj = self.nodes[0].gettransaction(txId) | ||||
assert_equal(txObj['amount'], Decimal('-2')) | assert_equal(txObj['amount'], Decimal('-2')) | ||||
txId = self.nodes[0].sendtoaddress( | txId = self.nodes[0].sendtoaddress( | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
balance_nodes = [self.nodes[i].getbalance() for i in range(3)] | balance_nodes = [self.nodes[i].getbalance() for i in range(3)] | ||||
block_count = self.nodes[0].getblockcount() | block_count = self.nodes[0].getblockcount() | ||||
# Check modes: | # Check modes: | ||||
# - True: unicode escaped as \u.... | # - True: unicode escaped as \u.... | ||||
# - False: unicode directly as UTF-8 | # - False: unicode directly as UTF-8 | ||||
for mode in [True, False]: | for mode in [True, False]: | ||||
self.nodes[0].rpc.ensure_ascii = mode | self.nodes[0].rpc.ensure_ascii = mode | ||||
# unicode check: Basic Multilingual Plane, Supplementary Plane respectively | # unicode check: Basic Multilingual Plane, Supplementary Plane | ||||
# respectively | |||||
for label in [u'рыба', u'𝅘𝅥𝅯']: | for label in [u'рыба', u'𝅘𝅥𝅯']: | ||||
addr = self.nodes[0].getnewaddress() | addr = self.nodes[0].getnewaddress() | ||||
self.nodes[0].setlabel(addr, label) | self.nodes[0].setlabel(addr, label) | ||||
assert_equal(self.nodes[0].getaddressinfo( | assert_equal(self.nodes[0].getaddressinfo( | ||||
addr)['label'], label) | addr)['label'], label) | ||||
assert(label in self.nodes[0].listlabels()) | assert(label in self.nodes[0].listlabels()) | ||||
# restore to default | # restore to default | ||||
self.nodes[0].rpc.ensure_ascii = True | self.nodes[0].rpc.ensure_ascii = True | ||||
Show All 25 Lines | def run_test(self): | ||||
# Exercise listsinceblock with the last two blocks | # Exercise listsinceblock with the last two blocks | ||||
coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0]) | coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0]) | ||||
assert_equal(coinbase_tx_1["lastblock"], blocks[1]) | assert_equal(coinbase_tx_1["lastblock"], blocks[1]) | ||||
assert_equal(len(coinbase_tx_1["transactions"]), 1) | assert_equal(len(coinbase_tx_1["transactions"]), 1) | ||||
assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1]) | assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1]) | ||||
assert_equal(len(self.nodes[0].listsinceblock( | assert_equal(len(self.nodes[0].listsinceblock( | ||||
blocks[1])["transactions"]), 0) | blocks[1])["transactions"]), 0) | ||||
# ==Check that wallet prefers to use coins that don't exceed mempool limits ===== | # ==Check that wallet prefers to use coins that don't exceed mempool li | ||||
# Get all non-zero utxos together | # Get all non-zero utxos together | ||||
chain_addrs = [self.nodes[0].getnewaddress( | chain_addrs = [self.nodes[0].getnewaddress( | ||||
), self.nodes[0].getnewaddress()] | ), self.nodes[0].getnewaddress()] | ||||
singletxid = self.nodes[0].sendtoaddress( | singletxid = self.nodes[0].sendtoaddress( | ||||
chain_addrs[0], self.nodes[0].getbalance(), "", "", True) | chain_addrs[0], self.nodes[0].getbalance(), "", "", True) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
node0_balance = self.nodes[0].getbalance() | node0_balance = self.nodes[0].getbalance() | ||||
# Split into two chains | # Split into two chains | ||||
rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], { | rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], { | ||||
chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')}) | chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')}) | ||||
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx) | signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx) | ||||
singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"]) | singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"]) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
# Make a long chain of unconfirmed payments without hitting mempool limit | # Make a long chain of unconfirmed payments without hitting mempool limit | ||||
# Each tx we make leaves only one output of change on a chain 1 longer | # Each tx we make leaves only one output of change on a chain 1 longer | ||||
# Since the amount to send is always much less than the outputs, we only ever need one output | # Since the amount to send is always much less than the outputs, we only ever need one output | ||||
# So we should be able to generate exactly chainlimit txs for each original output | # So we should be able to generate exactly chainlimit txs for each | ||||
# original output | |||||
sending_addr = self.nodes[1].getnewaddress() | sending_addr = self.nodes[1].getnewaddress() | ||||
txid_list = [] | txid_list = [] | ||||
for i in range(chainlimit * 2): | for i in range(chainlimit * 2): | ||||
txid_list.append(self.nodes[0].sendtoaddress( | txid_list.append(self.nodes[0].sendtoaddress( | ||||
sending_addr, Decimal('0.0001'))) | sending_addr, Decimal('0.0001'))) | ||||
assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2) | assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2) | ||||
assert_equal(len(txid_list), chainlimit * 2) | assert_equal(len(txid_list), chainlimit * 2) | ||||
# Without walletrejectlongchains, we will still generate a txid | # Without walletrejectlongchains, we will still generate a txid | ||||
# The tx will be stored in the wallet but not accepted to the mempool | # The tx will be stored in the wallet but not accepted to the mempool | ||||
extra_txid = self.nodes[0].sendtoaddress( | extra_txid = self.nodes[0].sendtoaddress( | ||||
sending_addr, Decimal('0.0001')) | sending_addr, Decimal('0.0001')) | ||||
assert extra_txid not in self.nodes[0].getrawmempool() | assert extra_txid not in self.nodes[0].getrawmempool() | ||||
assert extra_txid in [tx["txid"] | assert extra_txid in [tx["txid"] | ||||
for tx in self.nodes[0].listtransactions()] | for tx in self.nodes[0].listtransactions()] | ||||
self.nodes[0].abandontransaction(extra_txid) | self.nodes[0].abandontransaction(extra_txid) | ||||
total_txs = len(self.nodes[0].listtransactions("*", 99999)) | total_txs = len(self.nodes[0].listtransactions("*", 99999)) | ||||
# Try with walletrejectlongchains | # Try with walletrejectlongchains | ||||
# Double chain limit but require combining inputs, so we pass SelectCoinsMinConf | # Double chain limit but require combining inputs, so we pass | ||||
# SelectCoinsMinConf | |||||
self.stop_node(0) | self.stop_node(0) | ||||
self.start_node(0, extra_args=[ | self.start_node(0, extra_args=[ | ||||
"-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]) | "-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]) | ||||
# wait for loadmempool | # wait for loadmempool | ||||
timeout = 10 | timeout = 10 | ||||
while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit * 2): | while (timeout > 0 and len( | ||||
self.nodes[0].getrawmempool()) < chainlimit * 2): | |||||
time.sleep(0.5) | time.sleep(0.5) | ||||
timeout -= 0.5 | timeout -= 0.5 | ||||
assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2) | assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2) | ||||
node0_balance = self.nodes[0].getbalance() | node0_balance = self.nodes[0].getbalance() | ||||
# With walletrejectlongchains we will not create the tx and store it in our wallet. | # With walletrejectlongchains we will not create the tx and store it in | ||||
# our wallet. | |||||
assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", | assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", | ||||
self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01')) | self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01')) | ||||
# Verify nothing new in wallet | # Verify nothing new in wallet | ||||
assert_equal(total_txs, len( | assert_equal(total_txs, len( | ||||
self.nodes[0].listtransactions("*", 99999))) | self.nodes[0].listtransactions("*", 99999))) | ||||
# Test getaddressinfo. Note that these addresses are taken from disablewallet.py | # Test getaddressinfo. Note that these addresses are taken from | ||||
# disablewallet.py | |||||
assert_raises_rpc_error(-5, "Invalid address", | assert_raises_rpc_error(-5, "Invalid address", | ||||
self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") | self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") | ||||
address_info = self.nodes[0].getaddressinfo( | address_info = self.nodes[0].getaddressinfo( | ||||
"mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ") | "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ") | ||||
assert_equal(address_info['address'], | assert_equal(address_info['address'], | ||||
"bchreg:qp8rs4qyd3aazk22eyzwg7fmdfzmxm02pywavdajx4") | "bchreg:qp8rs4qyd3aazk22eyzwg7fmdfzmxm02pywavdajx4") | ||||
assert_equal(address_info["scriptPubKey"], | assert_equal(address_info["scriptPubKey"], | ||||
"76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac") | "76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac") | ||||
assert not address_info["ismine"] | assert not address_info["ismine"] | ||||
assert not address_info["iswatchonly"] | assert not address_info["iswatchonly"] | ||||
assert not address_info["isscript"] | assert not address_info["isscript"] | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
WalletTest().main() | WalletTest().main() |