Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_balance.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2018-2019 The Bitcoin Core developers | # Copyright (c) 2018-2019 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test the wallet balance RPC methods.""" | """Test the wallet balance RPC methods.""" | ||||
from decimal import Decimal | |||||
from test_framework.address import ADDRESS_BCHREG_UNSPENDABLE as ADDRESS_WATCHONLY | |||||
from test_framework.test_framework import BitcoinTestFramework | |||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
) | ) | ||||
from test_framework.test_framework import BitcoinTestFramework | |||||
from decimal import Decimal | |||||
RANDOM_COINBASE_ADDRESS = 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ' | |||||
def create_transactions(node, address, amt, fees): | def create_transactions(node, address, amt, fees): | ||||
# Create and sign raw transactions from node to address for amt. | # Create and sign raw transactions from node to address for amt. | ||||
# Creates a transaction for each fee and returns an array | # Creates a transaction for each fee and returns an array | ||||
# of the raw transactions. | # of the raw transactions. | ||||
utxos = node.listunspent(0) | utxos = [u for u in node.listunspent(0) if u['spendable']] | ||||
# Create transactions | # Create transactions | ||||
inputs = [] | inputs = [] | ||||
ins_total = 0 | ins_total = 0 | ||||
for utxo in utxos: | for utxo in utxos: | ||||
inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) | inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) | ||||
ins_total += utxo['amount'] | ins_total += utxo['amount'] | ||||
if ins_total > amt: | if ins_total > amt: | ||||
Show All 17 Lines | class WalletTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 2 | self.num_nodes = 2 | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
def skip_test_if_missing_module(self): | def skip_test_if_missing_module(self): | ||||
self.skip_if_no_wallet() | self.skip_if_no_wallet() | ||||
def run_test(self): | def run_test(self): | ||||
self.nodes[0].importaddress(ADDRESS_WATCHONLY) | |||||
# Check that nodes don't own any UTXOs | # Check that nodes don't own any UTXOs | ||||
assert_equal(len(self.nodes[0].listunspent()), 0) | assert_equal(len(self.nodes[0].listunspent()), 0) | ||||
assert_equal(len(self.nodes[1].listunspent()), 0) | assert_equal(len(self.nodes[1].listunspent()), 0) | ||||
self.log.info("Mining one block for each node") | self.log.info("Mining blocks ...") | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.sync_all() | self.sync_all() | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
self.nodes[1].generatetoaddress(100, RANDOM_COINBASE_ADDRESS) | self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY) | ||||
self.sync_all() | self.sync_all() | ||||
assert_equal(self.nodes[0].getbalance(), 50) | assert_equal(self.nodes[0].getbalance(), 50) | ||||
assert_equal(self.nodes[1].getbalance(), 50) | assert_equal(self.nodes[1].getbalance(), 50) | ||||
self.log.info("Test getbalance with different arguments") | self.log.info("Test getbalance with different arguments") | ||||
assert_equal(self.nodes[0].getbalance("*"), 50) | assert_equal(self.nodes[0].getbalance("*"), 50) | ||||
assert_equal(self.nodes[0].getbalance("*", 1), 50) | assert_equal(self.nodes[0].getbalance("*", 1), 50) | ||||
assert_equal(self.nodes[0].getbalance("*", 1, True), 50) | assert_equal(self.nodes[0].getbalance("*", 1, True), 100) | ||||
assert_equal(self.nodes[0].getbalance(minconf=1), 50) | assert_equal(self.nodes[0].getbalance(minconf=1), 50) | ||||
assert_equal( | |||||
self.nodes[0].getbalance( | |||||
minconf=0, | |||||
include_watchonly=True), | |||||
100) | |||||
assert_equal( | |||||
self.nodes[1].getbalance( | |||||
minconf=0, | |||||
include_watchonly=True), | |||||
50) | |||||
# Send 40 BTC from 0 to 1 and 60 BTC from 1 to 0. | # Send 40 BTC from 0 to 1 and 60 BTC from 1 to 0. | ||||
txs = create_transactions( | txs = create_transactions( | ||||
self.nodes[0], self.nodes[1].getnewaddress(), 40, [Decimal('0.01')]) | self.nodes[0], self.nodes[1].getnewaddress(), 40, [Decimal('0.01')]) | ||||
self.nodes[0].sendrawtransaction(txs[0]['hex']) | self.nodes[0].sendrawtransaction(txs[0]['hex']) | ||||
# sending on both nodes is faster than waiting for propagation | # sending on both nodes is faster than waiting for propagation | ||||
self.nodes[1].sendrawtransaction(txs[0]['hex']) | self.nodes[1].sendrawtransaction(txs[0]['hex']) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
assert_equal(self.nodes[0].getwalletinfo()[ | assert_equal(self.nodes[0].getwalletinfo()[ | ||||
"unconfirmed_balance"], Decimal('60')) | "unconfirmed_balance"], Decimal('60')) | ||||
assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) | assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) | ||||
# Doesn't include output of node 0's send since it was spent | # Doesn't include output of node 0's send since it was spent | ||||
assert_equal(self.nodes[1].getwalletinfo()[ | assert_equal(self.nodes[1].getwalletinfo()[ | ||||
"unconfirmed_balance"], Decimal('0')) | "unconfirmed_balance"], Decimal('0')) | ||||
assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) | assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) | ||||
self.nodes[1].generatetoaddress(1, RANDOM_COINBASE_ADDRESS) | self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY) | ||||
self.sync_all() | self.sync_all() | ||||
# balances are correct after the transactions are confirmed | # balances are correct after the transactions are confirmed | ||||
# node 1's send plus change from node 0's send | # node 1's send plus change from node 0's send | ||||
assert_equal(self.nodes[0].getbalance(), Decimal('69.99')) | assert_equal(self.nodes[0].getbalance(), Decimal('69.99')) | ||||
assert_equal(self.nodes[1].getbalance(), Decimal( | assert_equal(self.nodes[1].getbalance(), Decimal( | ||||
'29.99')) # change from node 0's send | '29.99')) # change from node 0's send | ||||
# Send total balance away from node 1 | # Send total balance away from node 1 | ||||
txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress( | txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress( | ||||
), Decimal('29.97'), [Decimal('0.01')]) | ), Decimal('29.97'), [Decimal('0.01')]) | ||||
self.nodes[1].sendrawtransaction(txs[0]['hex']) | self.nodes[1].sendrawtransaction(txs[0]['hex']) | ||||
self.nodes[1].generatetoaddress(2, RANDOM_COINBASE_ADDRESS) | self.nodes[1].generatetoaddress(2, ADDRESS_WATCHONLY) | ||||
self.sync_all() | self.sync_all() | ||||
# getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago | # getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago | ||||
# TODO: fix getbalance tracking of coin spentness depth | # TODO: fix getbalance tracking of coin spentness depth | ||||
# getbalance with minconf=3 should still show the old balance | # getbalance with minconf=3 should still show the old balance | ||||
assert_equal(self.nodes[1].getbalance(minconf=3), Decimal('0')) | assert_equal(self.nodes[1].getbalance(minconf=3), Decimal('0')) | ||||
# getbalance with minconf=2 will show the new balance. | # getbalance with minconf=2 will show the new balance. | ||||
Show All 16 Lines |