Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_basic.py
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
assert_equal(len(self.nodes[1].listunspent()), 0) | assert_equal(len(self.nodes[1].listunspent()), 0) | ||||
assert_equal(len(self.nodes[2].listunspent()), 0) | assert_equal(len(self.nodes[2].listunspent()), 0) | ||||
self.log.info("Mining blocks...") | self.log.info("Mining blocks...") | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
walletinfo = self.nodes[0].getwalletinfo() | walletinfo = self.nodes[0].getwalletinfo() | ||||
assert_equal(walletinfo['immature_balance'], 50) | assert_equal(walletinfo['immature_balance'], 50000000) | ||||
assert_equal(walletinfo['balance'], 0) | assert_equal(walletinfo['balance'], 0) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
self.nodes[1].generate(101) | self.nodes[1].generate(101) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
assert_equal(self.nodes[0].getbalance(), 50) | assert_equal(self.nodes[0].getbalance(), 50000000) | ||||
assert_equal(self.nodes[1].getbalance(), 50) | assert_equal(self.nodes[1].getbalance(), 50000000) | ||||
assert_equal(self.nodes[2].getbalance(), 0) | assert_equal(self.nodes[2].getbalance(), 0) | ||||
# Check that only first and second nodes have UTXOs | # Check that only first and second nodes have UTXOs | ||||
utxos = self.nodes[0].listunspent() | utxos = self.nodes[0].listunspent() | ||||
assert_equal(len(utxos), 1) | assert_equal(len(utxos), 1) | ||||
assert_equal(len(self.nodes[1].listunspent()), 1) | assert_equal(len(self.nodes[1].listunspent()), 1) | ||||
assert_equal(len(self.nodes[2].listunspent()), 0) | assert_equal(len(self.nodes[2].listunspent()), 0) | ||||
self.log.info("test gettxout") | self.log.info("test gettxout") | ||||
confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"] | confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"] | ||||
# First, outputs that are unspent both in the chain and in the | # First, outputs that are unspent both in the chain and in the | ||||
# mempool should appear with or without include_mempool | # mempool should appear with or without include_mempool | ||||
txout = self.nodes[0].gettxout( | txout = self.nodes[0].gettxout( | ||||
txid=confirmed_txid, n=confirmed_index, include_mempool=False) | txid=confirmed_txid, n=confirmed_index, include_mempool=False) | ||||
assert_equal(txout['value'], 50) | assert_equal(txout['value'], 50000000) | ||||
txout = self.nodes[0].gettxout( | txout = self.nodes[0].gettxout( | ||||
txid=confirmed_txid, n=confirmed_index, include_mempool=True) | txid=confirmed_txid, n=confirmed_index, include_mempool=True) | ||||
assert_equal(txout['value'], 50) | assert_equal(txout['value'], 50000000) | ||||
# Send 21 BCH from 0 to 2 using sendtoaddress call. | # Send 21 BCH from 0 to 2 using sendtoaddress call. | ||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) | self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11000000) | ||||
mempool_txid = self.nodes[0].sendtoaddress( | mempool_txid = self.nodes[0].sendtoaddress( | ||||
self.nodes[2].getnewaddress(), 10) | self.nodes[2].getnewaddress(), 10000000) | ||||
self.log.info("test gettxout (second part)") | self.log.info("test gettxout (second part)") | ||||
# utxo spent in mempool should be visible if you exclude mempool | # utxo spent in mempool should be visible if you exclude mempool | ||||
# but invisible if you include mempool | # but invisible if you include mempool | ||||
txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False) | txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False) | ||||
assert_equal(txout['value'], 50) | assert_equal(txout['value'], 50000000) | ||||
txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True) | txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True) | ||||
assert txout is None | assert txout is None | ||||
# new utxo from mempool should be invisible if you exclude mempool | # new utxo from mempool should be invisible if you exclude mempool | ||||
# but visible if you include mempool | # but visible if you include mempool | ||||
txout = self.nodes[0].gettxout(mempool_txid, 0, False) | txout = self.nodes[0].gettxout(mempool_txid, 0, False) | ||||
assert txout is None | assert txout is None | ||||
txout1 = self.nodes[0].gettxout(mempool_txid, 0, True) | txout1 = self.nodes[0].gettxout(mempool_txid, 0, True) | ||||
txout2 = self.nodes[0].gettxout(mempool_txid, 1, True) | txout2 = self.nodes[0].gettxout(mempool_txid, 1, True) | ||||
# note the mempool tx will have randomly assigned indices | # note the mempool tx will have randomly assigned indices | ||||
# but 10 will go to node2 and the rest will go to node0 | # but 10 will go to node2 and the rest will go to node0 | ||||
balance = self.nodes[0].getbalance() | balance = self.nodes[0].getbalance() | ||||
assert_equal(set([txout1['value'], txout2['value']]), | assert_equal(set([txout1['value'], txout2['value']]), | ||||
set([10, balance])) | set([10000000, balance])) | ||||
walletinfo = self.nodes[0].getwalletinfo() | walletinfo = self.nodes[0].getwalletinfo() | ||||
assert_equal(walletinfo['immature_balance'], 0) | assert_equal(walletinfo['immature_balance'], 0) | ||||
# Have node0 mine a block, thus it will collect its own fee. | # Have node0 mine a block, thus it will collect its own fee. | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
# Exercise locking of unspent outputs | # Exercise locking of unspent outputs | ||||
unspent_0 = self.nodes[2].listunspent()[0] | unspent_0 = self.nodes[2].listunspent()[0] | ||||
unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]} | unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]} | ||||
assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", | assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", | ||||
self.nodes[2].lockunspent, True, [unspent_0]) | self.nodes[2].lockunspent, True, [unspent_0]) | ||||
self.nodes[2].lockunspent(False, [unspent_0]) | self.nodes[2].lockunspent(False, [unspent_0]) | ||||
assert_raises_rpc_error(-8, "Invalid parameter, output already locked", | assert_raises_rpc_error(-8, "Invalid parameter, output already locked", | ||||
self.nodes[2].lockunspent, False, [unspent_0]) | self.nodes[2].lockunspent, False, [unspent_0]) | ||||
assert_raises_rpc_error(-4, "Insufficient funds", | assert_raises_rpc_error(-4, "Insufficient funds", | ||||
self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20) | self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20000000) | ||||
assert_equal([unspent_0], self.nodes[2].listlockunspent()) | assert_equal([unspent_0], self.nodes[2].listlockunspent()) | ||||
self.nodes[2].lockunspent(True, [unspent_0]) | self.nodes[2].lockunspent(True, [unspent_0]) | ||||
assert_equal(len(self.nodes[2].listlockunspent()), 0) | assert_equal(len(self.nodes[2].listlockunspent()), 0) | ||||
assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')", | assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')", | ||||
self.nodes[2].lockunspent, False, | self.nodes[2].lockunspent, False, | ||||
[{"txid": "0000000000000000000000000000000000", "vout": 0}]) | [{"txid": "0000000000000000000000000000000000", "vout": 0}]) | ||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", | assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", | ||||
self.nodes[2].lockunspent, False, | self.nodes[2].lockunspent, False, | ||||
[{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}]) | [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}]) | ||||
assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction", | assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction", | ||||
self.nodes[2].lockunspent, False, | self.nodes[2].lockunspent, False, | ||||
[{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "vout": 0}]) | [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "vout": 0}]) | ||||
assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds", | assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds", | ||||
self.nodes[2].lockunspent, False, [{"txid": unspent_0["txid"], "vout": 999}]) | self.nodes[2].lockunspent, False, [{"txid": unspent_0["txid"], "vout": 999}]) | ||||
# An output should be unlocked when spent | # An output should be unlocked when spent | ||||
unspent_0 = self.nodes[1].listunspent()[0] | unspent_0 = self.nodes[1].listunspent()[0] | ||||
self.nodes[1].lockunspent(False, [unspent_0]) | self.nodes[1].lockunspent(False, [unspent_0]) | ||||
tx = self.nodes[1].createrawtransaction( | tx = self.nodes[1].createrawtransaction( | ||||
[unspent_0], {self.nodes[1].getnewaddress(): 1}) | [unspent_0], {self.nodes[1].getnewaddress(): 1000000}) | ||||
tx = self.nodes[1].fundrawtransaction(tx)['hex'] | tx = self.nodes[1].fundrawtransaction(tx)['hex'] | ||||
tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"] | tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"] | ||||
self.nodes[1].sendrawtransaction(tx) | self.nodes[1].sendrawtransaction(tx) | ||||
assert_equal(len(self.nodes[1].listlockunspent()), 0) | assert_equal(len(self.nodes[1].listlockunspent()), 0) | ||||
# Have node1 generate 100 blocks (so node0 can recover the fee) | # Have node1 generate 100 blocks (so node0 can recover the fee) | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
# node0 should end up with 100 btc in block rewards plus fees, but | # node0 should end up with 100 btc in block rewards plus fees, but | ||||
# minus the 21 plus fees sent to node2 | # minus the 21 plus fees sent to node2 | ||||
assert_equal(self.nodes[0].getbalance(), 100 - 21) | assert_equal(self.nodes[0].getbalance(), 100000000 - 21000000) | ||||
assert_equal(self.nodes[2].getbalance(), 21) | assert_equal(self.nodes[2].getbalance(), 21000000) | ||||
# Node0 should have two unspent outputs. | # Node0 should have two unspent outputs. | ||||
# Create a couple of transactions to send them to node2, submit them through | # 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: | # node1, and make sure both node0 and node2 pick them up properly: | ||||
node0utxos = self.nodes[0].listunspent(1) | node0utxos = self.nodes[0].listunspent(1) | ||||
assert_equal(len(node0utxos), 2) | assert_equal(len(node0utxos), 2) | ||||
# create both transactions | # create both transactions | ||||
txns_to_send = [] | txns_to_send = [] | ||||
for utxo in node0utxos: | for utxo in node0utxos: | ||||
inputs = [] | inputs = [] | ||||
outputs = {} | outputs = {} | ||||
inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) | inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) | ||||
outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3 | outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3000000 | ||||
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs) | raw_tx = self.nodes[0].createrawtransaction(inputs, outputs) | ||||
txns_to_send.append( | txns_to_send.append( | ||||
self.nodes[0].signrawtransactionwithwallet(raw_tx)) | self.nodes[0].signrawtransactionwithwallet(raw_tx)) | ||||
# Have node 1 (miner) send the transactions | # Have node 1 (miner) send the transactions | ||||
self.nodes[1].sendrawtransaction( | self.nodes[1].sendrawtransaction( | ||||
hexstring=txns_to_send[0]["hex"], maxfeerate=0) | hexstring=txns_to_send[0]["hex"], maxfeerate=0) | ||||
self.nodes[1].sendrawtransaction( | self.nodes[1].sendrawtransaction( | ||||
hexstring=txns_to_send[1]["hex"], maxfeerate=0) | hexstring=txns_to_send[1]["hex"], maxfeerate=0) | ||||
# Have node1 mine a block to confirm transactions: | # Have node1 mine a block to confirm transactions: | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
assert_equal(self.nodes[0].getbalance(), 0) | assert_equal(self.nodes[0].getbalance(), 0) | ||||
assert_equal(self.nodes[2].getbalance(), 94) | assert_equal(self.nodes[2].getbalance(), 94000000) | ||||
# Verify that a spent output cannot be locked anymore | # Verify that a spent output cannot be locked anymore | ||||
spent_0 = {"txid": node0utxos[0]["txid"], | spent_0 = {"txid": node0utxos[0]["txid"], | ||||
"vout": node0utxos[0]["vout"]} | "vout": node0utxos[0]["vout"]} | ||||
assert_raises_rpc_error(-8, "Invalid parameter, expected unspent output", | assert_raises_rpc_error(-8, "Invalid parameter, expected unspent output", | ||||
self.nodes[0].lockunspent, False, [spent_0]) | self.nodes[0].lockunspent, False, [spent_0]) | ||||
# Send 10 BCH normal | # Send 10 BCH normal | ||||
old_balance = self.nodes[2].getbalance() | old_balance = self.nodes[2].getbalance() | ||||
address = self.nodes[0].getnewaddress("test") | address = self.nodes[0].getnewaddress("test") | ||||
fee_per_byte = Decimal('0.001') / 1000 | fee_per_byte = Decimal('1000') / 1000 | ||||
self.nodes[2].settxfee(fee_per_byte * 1000) | self.nodes[2].settxfee(fee_per_byte * 1000) | ||||
txid = self.nodes[2].sendtoaddress(address, 10, "", "", False) | txid = self.nodes[2].sendtoaddress(address, 10000000, "", "", False) | ||||
self.nodes[2].generate(1) | self.nodes[2].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
ctx = FromHex(CTransaction(), | ctx = FromHex(CTransaction(), | ||||
self.nodes[2].gettransaction(txid)['hex']) | self.nodes[2].gettransaction(txid)['hex']) | ||||
node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), old_balance - Decimal('10'), | node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), old_balance - Decimal('10000000'), | ||||
fee_per_byte, ctx.billable_size()) | fee_per_byte, ctx.billable_size()) | ||||
assert_equal(self.nodes[0].getbalance(), Decimal('10')) | assert_equal(self.nodes[0].getbalance(), Decimal('10000000')) | ||||
# Send 10 BCH with subtract fee from amount | # Send 10 BCH with subtract fee from amount | ||||
txid = self.nodes[2].sendtoaddress(address, 10, "", "", True) | txid = self.nodes[2].sendtoaddress(address, 10000000, "", "", True) | ||||
self.nodes[2].generate(1) | self.nodes[2].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
node_2_bal -= Decimal('10') | node_2_bal -= Decimal('10000000') | ||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) | assert_equal(self.nodes[2].getbalance(), node_2_bal) | ||||
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal( | node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal( | ||||
'20'), fee_per_byte, count_bytes(self.nodes[2].gettransaction(txid)['hex'])) | '20000000'), fee_per_byte, count_bytes(self.nodes[2].gettransaction(txid)['hex'])) | ||||
# Sendmany 10 BCH | # Sendmany 10 BCH | ||||
txid = self.nodes[2].sendmany('', {address: 10}, 0, "", []) | txid = self.nodes[2].sendmany('', {address: 10000000}, 0, "", []) | ||||
self.nodes[2].generate(1) | self.nodes[2].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
node_0_bal += Decimal('10') | node_0_bal += Decimal('10000000') | ||||
ctx = FromHex(CTransaction(), | ctx = FromHex(CTransaction(), | ||||
self.nodes[2].gettransaction(txid)['hex']) | self.nodes[2].gettransaction(txid)['hex']) | ||||
node_2_bal = self.check_fee_amount(self.nodes[2].getbalance( | node_2_bal = self.check_fee_amount(self.nodes[2].getbalance( | ||||
), node_2_bal - Decimal('10'), fee_per_byte, ctx.billable_size()) | ), node_2_bal - Decimal('10000000'), fee_per_byte, ctx.billable_size()) | ||||
assert_equal(self.nodes[0].getbalance(), node_0_bal) | assert_equal(self.nodes[0].getbalance(), node_0_bal) | ||||
# Sendmany 10 BCH with subtract fee from amount | # Sendmany 10 BCH with subtract fee from amount | ||||
txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address]) | txid = self.nodes[2].sendmany( | ||||
'', {address: 10000000}, 0, "", [address]) | |||||
self.nodes[2].generate(1) | self.nodes[2].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
node_2_bal -= Decimal('10') | node_2_bal -= Decimal('10000000') | ||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) | assert_equal(self.nodes[2].getbalance(), node_2_bal) | ||||
ctx = FromHex(CTransaction(), | ctx = FromHex(CTransaction(), | ||||
self.nodes[2].gettransaction(txid)['hex']) | self.nodes[2].gettransaction(txid)['hex']) | ||||
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance( | node_0_bal = self.check_fee_amount(self.nodes[0].getbalance( | ||||
), node_0_bal + Decimal('10'), fee_per_byte, ctx.billable_size()) | ), node_0_bal + Decimal('10000000'), fee_per_byte, ctx.billable_size()) | ||||
self.start_node(3, self.extra_args[3]) | self.start_node(3, self.extra_args[3]) | ||||
connect_nodes(self.nodes[0], self.nodes[3]) | connect_nodes(self.nodes[0], self.nodes[3]) | ||||
self.sync_all() | self.sync_all() | ||||
# check if we can list zero value tx as available coins | # check if we can list zero value tx as available coins | ||||
# 1. create raw_tx | # 1. create raw_tx | ||||
# 2. hex-changed one output to 0.0 | # 2. hex-changed one output to 0.0 | ||||
# 3. sign and send | # 3. sign and send | ||||
# 4. check if recipient (node0) can list the zero value tx | # 4. check if recipient (node0) can list the zero value tx | ||||
usp = self.nodes[1].listunspent( | usp = self.nodes[1].listunspent( | ||||
query_options={'minimumAmount': '49.998'})[0] | query_options={'minimumAmount': '49998000'})[0] | ||||
inputs = [{"txid": usp['txid'], "vout": usp['vout']}] | inputs = [{"txid": usp['txid'], "vout": usp['vout']}] | ||||
outputs = {self.nodes[1].getnewaddress(): 49.998, | outputs = {self.nodes[1].getnewaddress(): 49998000, | ||||
self.nodes[0].getnewaddress(): 11.11} | self.nodes[0].getnewaddress(): 11110000} | ||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace( | rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace( | ||||
"c0833842", "00000000") # replace 11.11 with 0.0 (int32) | "c0833842", "00000000") # replace 11.11 with 0.0 (int32) | ||||
signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(rawTx) | signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(rawTx) | ||||
decoded_raw_tx = self.nodes[1].decoderawtransaction( | decoded_raw_tx = self.nodes[1].decoderawtransaction( | ||||
signed_raw_tx['hex']) | signed_raw_tx['hex']) | ||||
zero_value_txid = decoded_raw_tx['txid'] | zero_value_txid = decoded_raw_tx['txid'] | ||||
self.nodes[1].sendrawtransaction(signed_raw_tx['hex']) | self.nodes[1].sendrawtransaction(signed_raw_tx['hex']) | ||||
Show All 17 Lines | def run_test(self): | ||||
self.start_node(1, self.extra_args[1] + ["-walletbroadcast=0"]) | self.start_node(1, self.extra_args[1] + ["-walletbroadcast=0"]) | ||||
self.start_node(2, self.extra_args[2] + ["-walletbroadcast=0"]) | self.start_node(2, self.extra_args[2] + ["-walletbroadcast=0"]) | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[1], self.nodes[2]) | connect_nodes(self.nodes[1], self.nodes[2]) | ||||
connect_nodes(self.nodes[0], self.nodes[2]) | connect_nodes(self.nodes[0], self.nodes[2]) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
txid_not_broadcast = self.nodes[0].sendtoaddress( | txid_not_broadcast = self.nodes[0].sendtoaddress( | ||||
self.nodes[2].getnewaddress(), 2) | self.nodes[2].getnewaddress(), 2000000) | ||||
tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast) | tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast) | ||||
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 | # now broadcast from another node, mine a block, sync, and check the | ||||
# balance | # balance | ||||
self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex']) | self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['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 += 2000000 | ||||
tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast) | tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast) | ||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) | assert_equal(self.nodes[2].getbalance(), node_2_bal) | ||||
# create another tx | # create another tx | ||||
txid_not_broadcast = self.nodes[0].sendtoaddress( | txid_not_broadcast = self.nodes[0].sendtoaddress( | ||||
self.nodes[2].getnewaddress(), 2) | self.nodes[2].getnewaddress(), 2000000) | ||||
# restart the nodes with -walletbroadcast=1 | # restart the nodes with -walletbroadcast=1 | ||||
self.stop_nodes() | self.stop_nodes() | ||||
self.start_node(0, self.extra_args[0]) | self.start_node(0, self.extra_args[0]) | ||||
self.start_node(1, self.extra_args[1]) | self.start_node(1, self.extra_args[1]) | ||||
self.start_node(2, self.extra_args[2]) | self.start_node(2, self.extra_args[2]) | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[1], self.nodes[2]) | connect_nodes(self.nodes[1], self.nodes[2]) | ||||
connect_nodes(self.nodes[0], self.nodes[2]) | connect_nodes(self.nodes[0], self.nodes[2]) | ||||
self.sync_blocks(self.nodes[0:3]) | self.sync_blocks(self.nodes[0:3]) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.sync_blocks(self.nodes[0:3]) | self.sync_blocks(self.nodes[0:3]) | ||||
node_2_bal += 2 | node_2_bal += 2000000 | ||||
# tx should be added to balance because after restarting the nodes tx | # tx should be added to balance because after restarting the nodes tx | ||||
# should be broadcasted | # 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(), "2000000") | |||||
tx_obj = self.nodes[0].gettransaction(txid) | tx_obj = self.nodes[0].gettransaction(txid) | ||||
assert_equal(tx_obj['amount'], Decimal('-2')) | assert_equal(tx_obj['amount'], Decimal('-2000000')) | ||||
txid = self.nodes[0].sendtoaddress( | txid = self.nodes[0].sendtoaddress( | ||||
self.nodes[2].getnewaddress(), "0.0001") | self.nodes[2].getnewaddress(), "10000") | ||||
tx_obj = self.nodes[0].gettransaction(txid) | tx_obj = self.nodes[0].gettransaction(txid) | ||||
assert_equal(tx_obj['amount'], Decimal('-0.0001')) | assert_equal(tx_obj['amount'], Decimal('-10000')) | ||||
# check if JSON parser can handle scientific notation in strings | # check if JSON parser can handle scientific notation in strings | ||||
txid = self.nodes[0].sendtoaddress( | txid = self.nodes[0].sendtoaddress( | ||||
self.nodes[2].getnewaddress(), "1e-4") | self.nodes[2].getnewaddress(), "1e3") | ||||
tx_obj = self.nodes[0].gettransaction(txid) | tx_obj = self.nodes[0].gettransaction(txid) | ||||
assert_equal(tx_obj['amount'], Decimal('-0.0001')) | assert_equal(tx_obj['amount'], Decimal('-1000')) | ||||
# General checks for errors from incorrect inputs | # General checks for errors from incorrect inputs | ||||
# This will raise an exception because the amount type is wrong | # This will raise an exception because the amount type is wrong | ||||
assert_raises_rpc_error(-3, "Invalid amount", | assert_raises_rpc_error(-3, "Invalid amount", | ||||
self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4") | self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4") | ||||
# This will raise an exception since generate does not accept a string | # This will raise an exception since generate does not accept a string | ||||
assert_raises_rpc_error(-1, "not an integer", | assert_raises_rpc_error(-1, "not an integer", | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
assert_raises_rpc_error(-5, | assert_raises_rpc_error(-5, | ||||
"Pubkey is not a valid public key", | "Pubkey is not a valid public key", | ||||
self.nodes[0].importpubkey, | self.nodes[0].importpubkey, | ||||
"5361746f736869204e616b616d6f746f") | "5361746f736869204e616b616d6f746f") | ||||
# Import address and private key to check correct behavior of spendable unspents | # Import address and private key to check correct behavior of spendable unspents | ||||
# 1. Send some coins to generate new UTXO | # 1. Send some coins to generate new UTXO | ||||
address_to_import = self.nodes[2].getnewaddress() | address_to_import = self.nodes[2].getnewaddress() | ||||
txid = self.nodes[0].sendtoaddress(address_to_import, 1) | txid = self.nodes[0].sendtoaddress(address_to_import, 1000000) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.sync_all(self.nodes[0:3]) | self.sync_all(self.nodes[0:3]) | ||||
# 2. Import address from node2 to node1 | # 2. Import address from node2 to node1 | ||||
self.nodes[1].importaddress(address_to_import) | self.nodes[1].importaddress(address_to_import) | ||||
# 3. Validate that the imported address is watch-only on node1 | # 3. Validate that the imported address is watch-only on node1 | ||||
assert self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"] | assert self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"] | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
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('10000'), chain_addrs[1]: node0_balance / 2 - Decimal('10000')}) | ||||
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx) | signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx) | ||||
singletxid = self.nodes[0].sendrawtransaction( | singletxid = self.nodes[0].sendrawtransaction( | ||||
hexstring=signedtx["hex"], maxfeerate=0) | hexstring=signedtx["hex"], maxfeerate=0) | ||||
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 | # So we should be able to generate exactly chainlimit txs for each | ||||
# original output | # 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('10000'))) | ||||
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('10000')) | ||||
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 | # Double chain limit but require combining inputs, so we pass | ||||
# SelectCoinsMinConf | # SelectCoinsMinConf | ||||
self.stop_node(0) | self.stop_node(0) | ||||
self.start_node(0, | self.start_node(0, | ||||
self.extra_args[0] + ["-walletrejectlongchains", | self.extra_args[0] + ["-walletrejectlongchains", | ||||
"-limitancestorcount=" + str(2 * chainlimit)]) | "-limitancestorcount=" + str(2 * chainlimit)]) | ||||
# wait until the wallet has submitted all transactions to the mempool | # wait until the wallet has submitted all transactions to the mempool | ||||
wait_until( | wait_until( | ||||
lambda: len( | lambda: len( | ||||
self.nodes[0].getrawmempool()) == chainlimit * | self.nodes[0].getrawmempool()) == chainlimit * | ||||
2) | 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 | # With walletrejectlongchains we will not create the tx and store it in | ||||
# our wallet. | # 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('10000')) | ||||
# 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 on external address. Note that these addresses | # Test getaddressinfo on external address. Note that these addresses | ||||
# are taken from disablewallet.py | # 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'], | ||||
"ecregtest:qp8rs4qyd3aazk22eyzwg7fmdfzmxm02pyprkfhvm4") | "ecregtest:qp8rs4qyd3aazk22eyzwg7fmdfzmxm02pyprkfhvm4") | ||||
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"] | ||||
assert not address_info["ischange"] | assert not address_info["ischange"] | ||||
# Test getaddressinfo 'ischange' field on change address. | # Test getaddressinfo 'ischange' field on change address. | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
destination = self.nodes[1].getnewaddress() | destination = self.nodes[1].getnewaddress() | ||||
txid = self.nodes[0].sendtoaddress(destination, 0.123) | txid = self.nodes[0].sendtoaddress(destination, 123000) | ||||
tx = self.nodes[0].decoderawtransaction( | tx = self.nodes[0].decoderawtransaction( | ||||
self.nodes[0].gettransaction(txid)['hex']) | self.nodes[0].gettransaction(txid)['hex']) | ||||
output_addresses = [vout['scriptPubKey']['addresses'][0] | output_addresses = [vout['scriptPubKey']['addresses'][0] | ||||
for vout in tx["vout"]] | for vout in tx["vout"]] | ||||
assert len(output_addresses) > 1 | assert len(output_addresses) > 1 | ||||
for address in output_addresses: | for address in output_addresses: | ||||
ischange = self.nodes[0].getaddressinfo(address)['ischange'] | ischange = self.nodes[0].getaddressinfo(address)['ischange'] | ||||
assert_equal(ischange, address != destination) | assert_equal(ischange, address != destination) | ||||
▲ Show 20 Lines • Show All 58 Lines • Show Last 20 Lines |