wallet_listreceivedby.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2014-2022 The Limenka 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 listreceivedbyaddress, listreceivedbylabel, getreceivedybaddress, and getreceivedbylabel RPCs."""
6 from decimal import Decimal
7
8 from test_framework.blocktools import COINBASE_MATURITY
9 from test_framework.test_framework import LimenkaTestFramework
10 from test_framework.util import (
11 assert_array_result,
12 assert_equal,
13 assert_raises_rpc_error,
14 )
15 from test_framework.wallet_util import test_address
16
17
18 class ReceivedByTest(LimenkaTestFramework):
19 def add_options(self, parser):
20 self.add_wallet_options(parser)
21
22 def set_test_params(self):
23 self.num_nodes = 2
24 # whitelist peers to speed up tx relay / mempool sync
25 self.noban_tx_relay = True
26
27 def skip_test_if_missing_module(self):
28 self.skip_if_no_wallet()
29 self.skip_if_no_cli()
30
31 def run_test(self):
32 # save the number of coinbase reward addresses so far
33 num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))
34
35 self.log.info("listreceivedbyaddress Test")
36
37 # Send from node 0 to 1
38 addr = self.nodes[1].getnewaddress()
39 txid = self.nodes[0].sendtoaddress(addr, 0.1)
40 self.sync_all()
41
42 # Check not listed in listreceivedbyaddress because has 0 confirmations
43 assert_array_result(self.nodes[1].listreceivedbyaddress(),
44 {"address": addr},
45 {},
46 True)
47 # Bury Tx under 10 block so it will be returned by listreceivedbyaddress
48 self.generate(self.nodes[1], 10)
49 assert_array_result(self.nodes[1].listreceivedbyaddress(),
50 {"address": addr},
51 {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
52 # With min confidence < 10
53 assert_array_result(self.nodes[1].listreceivedbyaddress(5),
54 {"address": addr},
55 {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
56 # With min confidence > 10, should not find Tx
57 assert_array_result(self.nodes[1].listreceivedbyaddress(11), {"address": addr}, {}, True)
58
59 # Empty Tx
60 empty_addr = self.nodes[1].getnewaddress()
61 assert_array_result(self.nodes[1].listreceivedbyaddress(0, True),
62 {"address": empty_addr},
63 {"address": empty_addr, "label": "", "amount": 0, "confirmations": 0, "txids": []})
64
65 # No returned addy should be a change addr
66 for node in self.nodes:
67 for addr_obj in node.listreceivedbyaddress():
68 assert_equal(node.getaddressinfo(addr_obj["address"])["ischange"], False)
69
70 # Test Address filtering
71 # Only on addr
72 expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}
73 res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr)
74 assert_array_result(res, {"address": addr}, expected)
75 assert_equal(len(res), 1)
76 # Test for regression on CLI calls with address string (#14173)
77 cli_res = self.nodes[1].cli.listreceivedbyaddress(0, True, True, addr)
78 assert_array_result(cli_res, {"address": addr}, expected)
79 assert_equal(len(cli_res), 1)
80 # Error on invalid address
81 assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling")
82 # Another address receive money
83 res = self.nodes[1].listreceivedbyaddress(0, True, True)
84 assert_equal(len(res), 2 + num_cb_reward_addresses) # Right now 2 entries
85 other_addr = self.nodes[1].getnewaddress()
86 txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
87 self.generate(self.nodes[0], 1)
88 # Same test as above should still pass
89 expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 11, "txids": [txid, ]}
90 res = self.nodes[1].listreceivedbyaddress(0, True, True, addr)
91 assert_array_result(res, {"address": addr}, expected)
92 assert_equal(len(res), 1)
93 # Same test as above but with other_addr should still pass
94 expected = {"address": other_addr, "label": "", "amount": Decimal("0.1"), "confirmations": 1, "txids": [txid2, ]}
95 res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
96 assert_array_result(res, {"address": other_addr}, expected)
97 assert_equal(len(res), 1)
98 # Should be two entries though without filter
99 res = self.nodes[1].listreceivedbyaddress(0, True, True)
100 assert_equal(len(res), 3 + num_cb_reward_addresses) # Became 3 entries
101
102 # Not on random addr
103 other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr
104 res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
105 assert_equal(len(res), 0)
106
107 self.log.info("getreceivedbyaddress Test")
108
109 # Send from node 0 to 1
110 addr = self.nodes[1].getnewaddress()
111 txid = self.nodes[0].sendtoaddress(addr, 0.1)
112 self.sync_all()
113
114 # Check balance is 0 because of 0 confirmations
115 balance = self.nodes[1].getreceivedbyaddress(addr)
116 assert_equal(balance, Decimal("0.0"))
117
118 # Check balance is 0.1
119 balance = self.nodes[1].getreceivedbyaddress(addr, 0)
120 assert_equal(balance, Decimal("0.1"))
121
122 # Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
123 self.generate(self.nodes[1], 10)
124 balance = self.nodes[1].getreceivedbyaddress(addr)
125 assert_equal(balance, Decimal("0.1"))
126
127 # Trying to getreceivedby for an address the wallet doesn't own should return an error
128 assert_raises_rpc_error(-4, "Address not found in wallet", self.nodes[0].getreceivedbyaddress, addr)
129
130 self.log.info("listreceivedbylabel + getreceivedbylabel Test")
131
132 # set pre-state
133 label = ''
134 address = self.nodes[1].getnewaddress()
135 test_address(self.nodes[1], address, labels=[label])
136 received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
137 balance_by_label = self.nodes[1].getreceivedbylabel(label)
138
139 txid = self.nodes[0].sendtoaddress(addr, 0.1)
140 self.sync_all()
141
142 # getreceivedbylabel returns an error if the wallet doesn't own the label
143 assert_raises_rpc_error(-4, "Label not found in wallet", self.nodes[0].getreceivedbylabel, "dummy")
144
145 # listreceivedbylabel should return received_by_label_json because of 0 confirmations
146 assert_array_result(self.nodes[1].listreceivedbylabel(),
147 {"label": label},
148 received_by_label_json)
149
150 # getreceivedbyaddress should return same balance because of 0 confirmations
151 balance = self.nodes[1].getreceivedbylabel(label)
152 assert_equal(balance, balance_by_label)
153
154 self.generate(self.nodes[1], 10)
155 # listreceivedbylabel should return updated received list
156 assert_array_result(self.nodes[1].listreceivedbylabel(),
157 {"label": label},
158 {"label": received_by_label_json["label"], "amount": (received_by_label_json["amount"] + Decimal("0.1"))})
159
160 # getreceivedbylabel should return updated receive total
161 balance = self.nodes[1].getreceivedbylabel(label)
162 assert_equal(balance, balance_by_label + Decimal("0.1"))
163
164 # Create a new label named "mynewlabel" that has a 0 balance
165 address = self.nodes[1].getnewaddress()
166 self.nodes[1].setlabel(address, "mynewlabel")
167 received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(0, True) if r["label"] == "mynewlabel"][0]
168
169 # Test includeempty of listreceivedbylabel
170 assert_equal(received_by_label_json["amount"], Decimal("0.0"))
171
172 # Test getreceivedbylabel for 0 amount labels
173 balance = self.nodes[1].getreceivedbylabel("mynewlabel")
174 assert_equal(balance, Decimal("0.0"))
175
176 self.log.info("Tests for including coinbase outputs")
177
178 # Generate block reward to address with label
179 label = "label"
180 address = self.nodes[0].getnewaddress(label)
181
182 reward = Decimal("25")
183 self.generatetoaddress(self.nodes[0], 1, address)
184 hash = self.nodes[0].getbestblockhash()
185
186 self.log.info("getreceivedbyaddress returns nothing with defaults")
187 balance = self.nodes[0].getreceivedbyaddress(address)
188 assert_equal(balance, 0)
189
190 self.log.info("getreceivedbyaddress returns block reward when including immature coinbase")
191 balance = self.nodes[0].getreceivedbyaddress(address=address, include_immature_coinbase=True)
192 assert_equal(balance, reward)
193
194 self.log.info("getreceivedbylabel returns nothing with defaults")
195 balance = self.nodes[0].getreceivedbylabel("label")
196 assert_equal(balance, 0)
197
198 self.log.info("getreceivedbylabel returns block reward when including immature coinbase")
199 balance = self.nodes[0].getreceivedbylabel(label="label", include_immature_coinbase=True)
200 assert_equal(balance, reward)
201
202 self.log.info("listreceivedbyaddress does not include address with defaults")
203 assert_array_result(self.nodes[0].listreceivedbyaddress(),
204 {"address": address},
205 {}, True)
206
207 self.log.info("listreceivedbyaddress includes address when including immature coinbase")
208 assert_array_result(self.nodes[0].listreceivedbyaddress(minconf=1, include_immature_coinbase=True),
209 {"address": address},
210 {"address": address, "amount": reward})
211
212 self.log.info("listreceivedbylabel does not include label with defaults")
213 assert_array_result(self.nodes[0].listreceivedbylabel(),
214 {"label": label},
215 {}, True)
216
217 self.log.info("listreceivedbylabel includes label when including immature coinbase")
218 assert_array_result(self.nodes[0].listreceivedbylabel(minconf=1, include_immature_coinbase=True),
219 {"label": label},
220 {"label": label, "amount": reward})
221
222 self.log.info("Generate 100 more blocks")
223 self.generate(self.nodes[0], COINBASE_MATURITY)
224
225 self.log.info("getreceivedbyaddress returns reward with defaults")
226 balance = self.nodes[0].getreceivedbyaddress(address)
227 assert_equal(balance, reward)
228
229 self.log.info("getreceivedbylabel returns reward with defaults")
230 balance = self.nodes[0].getreceivedbylabel("label")
231 assert_equal(balance, reward)
232
233 self.log.info("listreceivedbyaddress includes address with defaults")
234 assert_array_result(self.nodes[0].listreceivedbyaddress(),
235 {"address": address},
236 {"address": address, "amount": reward})
237
238 self.log.info("listreceivedbylabel includes label with defaults")
239 assert_array_result(self.nodes[0].listreceivedbylabel(),
240 {"label": label},
241 {"label": label, "amount": reward})
242
243 self.log.info("Invalidate block that paid to address")
244 self.nodes[0].invalidateblock(hash)
245
246 self.log.info("getreceivedbyaddress does not include invalidated block when minconf is 0 when including immature coinbase")
247 balance = self.nodes[0].getreceivedbyaddress(address=address, minconf=0, include_immature_coinbase=True)
248 assert_equal(balance, 0)
249
250 self.log.info("getreceivedbylabel does not include invalidated block when minconf is 0 when including immature coinbase")
251 balance = self.nodes[0].getreceivedbylabel(label="label", minconf=0, include_immature_coinbase=True)
252 assert_equal(balance, 0)
253
254 self.log.info("listreceivedbyaddress does not include invalidated block when minconf is 0 when including immature coinbase")
255 assert_array_result(self.nodes[0].listreceivedbyaddress(minconf=0, include_immature_coinbase=True),
256 {"address": address},
257 {}, True)
258
259 self.log.info("listreceivedbylabel does not include invalidated block when minconf is 0 when including immature coinbase")
260 assert_array_result(self.nodes[0].listreceivedbylabel(minconf=0, include_immature_coinbase=True),
261 {"label": label},
262 {}, True)
263
264
265 if __name__ == '__main__':
266 ReceivedByTest(__file__).main()
267