Skip to content

Commit 81bd349

Browse files
author
MarcoFalke
committed
Merge #14845: [tests] Add wallet_balance.py
c1825b9 [tests] Add wallet_balance.py (John Newbery) Pull request description: Adds a test specifically to test the wallet's getbalance and getunconfirmedbalance RPCs. `wallet_basic.py` is too large and should be broken down into more focused test cases. I wrote `wallet_balance.py` to test the changes in #14602. Offering as a PR in case people think it's more generally useful. Tree-SHA512: 573ae8faf377df3d87d5112870b40690efb285fc5578fff8acc2ac1a0e4625ae65d3dfa8abbac577c87bec015038f425833783fa09f014f87906e8d098ed30d7
2 parents 13a7454 + c1825b9 commit 81bd349

File tree

3 files changed

+134
-13
lines changed

3 files changed

+134
-13
lines changed

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
'wallet_importprunedfunds.py',
154154
'p2p_leak_tx.py',
155155
'rpc_signmessage.py',
156+
'wallet_balance.py',
156157
'feature_nulldummy.py',
157158
'mempool_accept.py',
158159
'wallet_import_rescan.py',

test/functional/wallet_balance.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2018 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""Test the wallet balance RPC methods."""
6+
from decimal import Decimal
7+
8+
from test_framework.test_framework import BitcoinTestFramework
9+
from test_framework.util import (
10+
assert_equal,
11+
assert_raises_rpc_error,
12+
)
13+
14+
RANDOM_COINBASE_ADDRESS = 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ'
15+
16+
def create_transactions(node, address, amt, fees):
17+
# Create and sign raw transactions from node to address for amt.
18+
# Creates a transaction for each fee and returns an array
19+
# of the raw transactions.
20+
utxos = node.listunspent(0)
21+
22+
# Create transactions
23+
inputs = []
24+
ins_total = 0
25+
for utxo in utxos:
26+
inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
27+
ins_total += utxo['amount']
28+
if ins_total > amt:
29+
break
30+
31+
txs = []
32+
for fee in fees:
33+
outputs = {address: amt, node.getrawchangeaddress(): ins_total - amt - fee}
34+
raw_tx = node.createrawtransaction(inputs, outputs, 0, True)
35+
raw_tx = node.signrawtransactionwithwallet(raw_tx)
36+
txs.append(raw_tx)
37+
38+
return txs
39+
40+
class WalletTest(BitcoinTestFramework):
41+
def set_test_params(self):
42+
self.num_nodes = 2
43+
self.setup_clean_chain = True
44+
45+
def skip_test_if_missing_module(self):
46+
self.skip_if_no_wallet()
47+
48+
def run_test(self):
49+
# Check that nodes don't own any UTXOs
50+
assert_equal(len(self.nodes[0].listunspent()), 0)
51+
assert_equal(len(self.nodes[1].listunspent()), 0)
52+
53+
self.log.info("Mining one block for each node")
54+
55+
self.nodes[0].generate(1)
56+
self.sync_all()
57+
self.nodes[1].generate(1)
58+
self.nodes[1].generatetoaddress(100, RANDOM_COINBASE_ADDRESS)
59+
self.sync_all()
60+
61+
assert_equal(self.nodes[0].getbalance(), 50)
62+
assert_equal(self.nodes[1].getbalance(), 50)
63+
64+
self.log.info("Test getbalance with different arguments")
65+
assert_equal(self.nodes[0].getbalance("*"), 50)
66+
assert_equal(self.nodes[0].getbalance("*", 1), 50)
67+
assert_equal(self.nodes[0].getbalance("*", 1, True), 50)
68+
assert_equal(self.nodes[0].getbalance(minconf=1), 50)
69+
70+
# Send 40 BTC from 0 to 1 and 60 BTC from 1 to 0.
71+
txs = create_transactions(self.nodes[0], self.nodes[1].getnewaddress(), 40, [Decimal('0.01')])
72+
self.nodes[0].sendrawtransaction(txs[0]['hex'])
73+
self.nodes[1].sendrawtransaction(txs[0]['hex']) # sending on both nodes is faster than waiting for propagation
74+
75+
self.sync_all()
76+
txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress(), 60, [Decimal('0.01'), Decimal('0.02')])
77+
self.nodes[1].sendrawtransaction(txs[0]['hex'])
78+
self.nodes[0].sendrawtransaction(txs[0]['hex']) # sending on both nodes is faster than waiting for propagation
79+
self.sync_all()
80+
81+
# First argument of getbalance must be set to "*"
82+
assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[1].getbalance, "")
83+
84+
self.log.info("Test getbalance and getunconfirmedbalance with unconfirmed inputs")
85+
86+
# getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions
87+
assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send
88+
assert_equal(self.nodes[1].getbalance(), Decimal('29.99')) # change from node 1's send
89+
# Same with minconf=0
90+
assert_equal(self.nodes[0].getbalance(minconf=0), Decimal('9.99'))
91+
assert_equal(self.nodes[1].getbalance(minconf=0), Decimal('29.99'))
92+
# getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago
93+
# TODO: fix getbalance tracking of coin spentness depth
94+
assert_equal(self.nodes[0].getbalance(minconf=1), Decimal('0'))
95+
assert_equal(self.nodes[1].getbalance(minconf=1), Decimal('0'))
96+
# getunconfirmedbalance
97+
assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) # output of node 1's spend
98+
assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) # Doesn't include output of node 0's send since it was spent
99+
100+
# Node 1 bumps the transaction fee and resends
101+
self.nodes[1].sendrawtransaction(txs[1]['hex'])
102+
self.sync_all()
103+
104+
self.log.info("Test getbalance and getunconfirmedbalance with conflicted unconfirmed inputs")
105+
106+
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60')) # output of node 1's send
107+
assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60'))
108+
assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('0')) # Doesn't include output of node 0's send since it was spent
109+
assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0'))
110+
111+
self.nodes[1].generatetoaddress(1, RANDOM_COINBASE_ADDRESS)
112+
self.sync_all()
113+
114+
# balances are correct after the transactions are confirmed
115+
assert_equal(self.nodes[0].getbalance(), Decimal('69.99')) # node 1's send plus change from node 0's send
116+
assert_equal(self.nodes[1].getbalance(), Decimal('29.98')) # change from node 0's send
117+
118+
# Send total balance away from node 1
119+
txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress(), Decimal('29.97'), [Decimal('0.01')])
120+
self.nodes[1].sendrawtransaction(txs[0]['hex'])
121+
self.nodes[1].generatetoaddress(2, RANDOM_COINBASE_ADDRESS)
122+
self.sync_all()
123+
124+
# getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago
125+
# TODO: fix getbalance tracking of coin spentness depth
126+
# getbalance with minconf=3 should still show the old balance
127+
assert_equal(self.nodes[1].getbalance(minconf=3), Decimal('0'))
128+
129+
# getbalance with minconf=2 will show the new balance.
130+
assert_equal(self.nodes[1].getbalance(minconf=2), Decimal('0'))
131+
132+
if __name__ == '__main__':
133+
WalletTest().main()

test/functional/wallet_basic.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,6 @@ def run_test(self):
6767
assert_equal(self.nodes[1].getbalance(), 50)
6868
assert_equal(self.nodes[2].getbalance(), 0)
6969

70-
# Check getbalance with different arguments
71-
assert_equal(self.nodes[0].getbalance("*"), 50)
72-
assert_equal(self.nodes[0].getbalance("*", 1), 50)
73-
assert_equal(self.nodes[0].getbalance("*", 1, True), 50)
74-
assert_equal(self.nodes[0].getbalance(minconf=1), 50)
75-
76-
# first argument of getbalance must be excluded or set to "*"
77-
assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[0].getbalance, "")
78-
7970
# Check that only first and second nodes have UTXOs
8071
utxos = self.nodes[0].listunspent()
8172
assert_equal(len(utxos), 1)
@@ -248,10 +239,6 @@ def run_test(self):
248239

249240
assert(txid1 in self.nodes[3].getrawmempool())
250241

251-
# Exercise balance rpcs
252-
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1)
253-
assert_equal(self.nodes[0].getunconfirmedbalance(), 1)
254-
255242
# check if we can list zero value tx as available coins
256243
# 1. create raw_tx
257244
# 2. hex-changed one output to 0.0

0 commit comments

Comments
 (0)