p2p_dns_seeds.py raw

   1  #!/usr/bin/env python3
   2  # Copyright (c) 2021-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 ThreadDNSAddressSeed logic for querying DNS seeds."""
   6  
   7  import itertools
   8  
   9  from test_framework.netutil import UNREACHABLE_PROXY_ARG
  10  from test_framework.p2p import P2PInterface
  11  from test_framework.test_framework import BitcoinTestFramework
  12  
  13  
  14  class P2PDNSSeeds(BitcoinTestFramework):
  15      def set_test_params(self):
  16          self.setup_clean_chain = True
  17          self.num_nodes = 1
  18          self.extra_args = [["-dnsseed=1", UNREACHABLE_PROXY_ARG]]
  19  
  20      def run_test(self):
  21          self.init_arg_tests()
  22          self.existing_outbound_connections_test()
  23          self.existing_block_relay_connections_test()
  24          self.force_dns_test()
  25          self.wait_time_tests()
  26  
  27      def init_arg_tests(self):
  28          fakeaddr = "fakenodeaddr.fakedomain.invalid."
  29  
  30          self.log.info("Check that setting -connect disables -dnsseed by default")
  31          self.nodes[0].stop_node()
  32          with self.nodes[0].assert_debug_log(expected_msgs=["DNS seeding disabled"], timeout=2):
  33              self.start_node(0, extra_args=[f"-connect={fakeaddr}", UNREACHABLE_PROXY_ARG])
  34  
  35          self.log.info("Check that running -connect and -dnsseed means DNS logic runs.")
  36          with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12):
  37              self.restart_node(0, extra_args=[f"-connect={fakeaddr}", "-dnsseed=1", UNREACHABLE_PROXY_ARG])
  38  
  39          self.log.info("Check that running -forcednsseed and -dnsseed=0 throws an error.")
  40          self.nodes[0].stop_node()
  41          self.nodes[0].assert_start_raises_init_error(
  42              expected_msg="Error: Cannot set -forcednsseed to true when setting -dnsseed to false.",
  43              extra_args=["-forcednsseed=1", "-dnsseed=0"],
  44          )
  45  
  46          self.log.info("Check that running -forcednsseed and -connect throws an error.")
  47          # -connect soft sets -dnsseed to false, so throws the same error
  48          self.nodes[0].stop_node()
  49          self.nodes[0].assert_start_raises_init_error(
  50              expected_msg="Error: Cannot set -forcednsseed to true when setting -dnsseed to false.",
  51              extra_args=["-forcednsseed=1", f"-connect={fakeaddr}"],
  52          )
  53  
  54          # Restore default bitcoind settings
  55          self.restart_node(0)
  56  
  57      def existing_outbound_connections_test(self):
  58          # Make sure addrman is populated to enter the conditional where we
  59          # delay and potentially skip DNS seeding.
  60          self.nodes[0].addpeeraddress("192.0.0.8", 8333)
  61  
  62          self.log.info("Check that we *do not* query DNS seeds if we have 2 outbound connections")
  63  
  64          self.restart_node(0)
  65          with self.nodes[0].assert_debug_log(expected_msgs=["P2P peers available. Skipped DNS seeding."], timeout=12):
  66              for i in range(2):
  67                  self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="outbound-full-relay")
  68  
  69      def existing_block_relay_connections_test(self):
  70          # Make sure addrman is populated to enter the conditional where we
  71          # delay and potentially skip DNS seeding. No-op when run after
  72          # existing_outbound_connections_test.
  73          self.nodes[0].addpeeraddress("192.0.0.8", 8333)
  74  
  75          self.log.info("Check that we *do* query DNS seeds if we only have 2 block-relay-only connections")
  76  
  77          self.restart_node(0)
  78          with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12):
  79              # This mimics the "anchors" logic where nodes are likely to
  80              # reconnect to block-relay-only connections on startup.
  81              # Since we do not participate in addr relay with these connections,
  82              # we still want to query the DNS seeds.
  83              for i in range(2):
  84                  self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="block-relay-only")
  85  
  86      def force_dns_test(self):
  87          self.log.info("Check that we query DNS seeds if -forcednsseed param is set")
  88  
  89          with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12):
  90              # -dnsseed defaults to 1 in bitcoind, but 0 in the test framework,
  91              # so pass it explicitly here
  92              self.restart_node(0, ["-forcednsseed", "-dnsseed=1", UNREACHABLE_PROXY_ARG])
  93  
  94          # Restore default for subsequent tests
  95          self.restart_node(0)
  96  
  97      def wait_time_tests(self):
  98          self.log.info("Check the delay before querying DNS seeds")
  99  
 100          # Populate addrman with < 1000 addresses
 101          for i in range(5):
 102              a = f"192.0.0.{i}"
 103              self.nodes[0].addpeeraddress(a, 8333)
 104  
 105          # The delay should be 11 seconds
 106          with self.nodes[0].assert_debug_log(expected_msgs=["Waiting 11 seconds before querying DNS seeds.\n"], timeout=2):
 107              self.restart_node(0)
 108  
 109          # Populate addrman with > 1000 addresses
 110          for i in itertools.count():
 111              first_octet = i % 2 + 1
 112              second_octet = i % 256
 113              third_octet = i % 100
 114              a = f"{first_octet}.{second_octet}.{third_octet}.1"
 115              self.nodes[0].addpeeraddress(a, 8333)
 116              if (i > 1000 and i % 100 == 0):
 117                  # The addrman size is non-deterministic because new addresses
 118                  # are sorted into buckets, potentially displacing existing
 119                  # addresses. Periodically check if we have met the desired
 120                  # threshold.
 121                  if len(self.nodes[0].getnodeaddresses(0)) > 1000:
 122                      break
 123  
 124          # The delay should be 5 mins
 125          with self.nodes[0].assert_debug_log(expected_msgs=["Waiting 300 seconds before querying DNS seeds.\n"], timeout=2):
 126              self.restart_node(0)
 127  
 128  
 129  if __name__ == '__main__':
 130      P2PDNSSeeds(__file__).main()
 131