wallet_listreceivedby.py raw

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