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