wallet_listreceivedby.py
1 #!/usr/bin/env python3 2 # Copyright (c) 2014-2022 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 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 BitcoinTestFramework 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(BitcoinTestFramework): 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().main()