forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge bitcoin#22098: [test, init] DNS seed querying logic
82b6f89 [style] Small style improvements to DNS parameters (Amiti Uttarwar) 4c89e24 [test] Test the delay before querying DNS seeds (Amiti Uttarwar) 6395c8e [test] Test the interactions between -forcednsseed and -dnsseed (Amiti Uttarwar) 6f6b7df [init] Disallow starting up with conflicting paramters for -dnsseed and -forcednsseed (Amiti Uttarwar) 26d0ffe [test] Test -forcednsseed causes querying DNS seeds (Amiti Uttarwar) 3585145 [test] Test the interactions between -connect and -dnsseed (Amiti Uttarwar) 75c05af [test] Test logic to query DNS seeds with block-relay-only connections (Amiti Uttarwar) 9c08719 [test] Introduce test logic to query DNS seeds (Amiti Uttarwar) Pull request description: This PR adds a DNS seed to the regtest chain params to enable testing the DNS seed querying logic of `CConnman::ThreadDNSAddressSeed` and relevant startup parameters. Adds coverage for the changes in bitcoin#22013 (and then some). The main behavioral change to bitcoind is that this PR disallows starting up with conflicting parameters for `-dnsseed` and `-forcednsseed`. The tests include: * parameter interactions of different combinations of `-connect`, `-dnsseed` and `-forcednsseed` * the delay before querying DNS seeds depending on how many addresses are in the addrman * the behavior of `-forcednsseed` * skipping DNS querying if we have outbound full relay connections & not block-relay-only connections Huge props to mzumsande for identifying the timing technique for testing successful connections before running `ThreadDNSAddressSeed` 🙌🏽 ACKs for top commit: mzumsande: ACK 82b6f89 jnewbery: reACK 82b6f89 Tree-SHA512: 9f0c29bfbf99426727e79c0a25606ae09deab91a92e3c5cee7f84c3ca7503a8ac9ab85a85c51841d40b164ef8c991326070f0b2f41d075fb7985df26f6e95d6d
- Loading branch information
1 parent
5407f5e
commit b50c039
Showing
6 changed files
with
144 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#!/usr/bin/env python3 | ||
# Copyright (c) 2021 The Bitcoin Core developers | ||
# Distributed under the MIT software license, see the accompanying | ||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
"""Test ThreadDNSAddressSeed logic for querying DNS seeds.""" | ||
|
||
import itertools | ||
|
||
from test_framework.p2p import P2PInterface | ||
from test_framework.test_framework import BitcoinTestFramework | ||
|
||
|
||
class P2PDNSSeeds(BitcoinTestFramework): | ||
def set_test_params(self): | ||
self.setup_clean_chain = True | ||
self.num_nodes = 1 | ||
self.extra_args = [["-dnsseed=1"]] | ||
|
||
def run_test(self): | ||
self.init_arg_tests() | ||
self.existing_outbound_connections_test() | ||
self.existing_block_relay_connections_test() | ||
self.force_dns_test() | ||
self.wait_time_tests() | ||
|
||
def init_arg_tests(self): | ||
fakeaddr = "fakenodeaddr.fakedomain.invalid." | ||
|
||
self.log.info("Check that setting -connect disables -dnsseed by default") | ||
self.nodes[0].stop_node() | ||
with self.nodes[0].assert_debug_log(expected_msgs=["DNS seeding disabled"]): | ||
self.start_node(0, [f"-connect={fakeaddr}"]) | ||
|
||
self.log.info("Check that running -connect and -dnsseed means DNS logic runs.") | ||
with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12): | ||
self.restart_node(0, [f"-connect={fakeaddr}", "-dnsseed=1"]) | ||
|
||
self.log.info("Check that running -forcednsseed and -dnsseed=0 throws an error.") | ||
self.nodes[0].stop_node() | ||
self.nodes[0].assert_start_raises_init_error( | ||
expected_msg="Error: Cannot set -forcednsseed to true when setting -dnsseed to false.", | ||
extra_args=["-forcednsseed=1", "-dnsseed=0"], | ||
) | ||
|
||
self.log.info("Check that running -forcednsseed and -connect throws an error.") | ||
# -connect soft sets -dnsseed to false, so throws the same error | ||
self.nodes[0].stop_node() | ||
self.nodes[0].assert_start_raises_init_error( | ||
expected_msg="Error: Cannot set -forcednsseed to true when setting -dnsseed to false.", | ||
extra_args=["-forcednsseed=1", f"-connect={fakeaddr}"], | ||
) | ||
|
||
# Restore default bitcoind settings | ||
self.restart_node(0) | ||
|
||
def existing_outbound_connections_test(self): | ||
# Make sure addrman is populated to enter the conditional where we | ||
# delay and potentially skip DNS seeding. | ||
self.nodes[0].addpeeraddress("192.0.0.8", 8333) | ||
|
||
self.log.info("Check that we *do not* query DNS seeds if we have 2 outbound connections") | ||
|
||
self.restart_node(0) | ||
with self.nodes[0].assert_debug_log(expected_msgs=["P2P peers available. Skipped DNS seeding."], timeout=12): | ||
for i in range(2): | ||
self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="outbound-full-relay") | ||
|
||
def existing_block_relay_connections_test(self): | ||
# Make sure addrman is populated to enter the conditional where we | ||
# delay and potentially skip DNS seeding. No-op when run after | ||
# existing_outbound_connections_test. | ||
self.nodes[0].addpeeraddress("192.0.0.8", 8333) | ||
|
||
self.log.info("Check that we *do* query DNS seeds if we only have 2 block-relay-only connections") | ||
|
||
self.restart_node(0) | ||
with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12): | ||
# This mimics the "anchors" logic where nodes are likely to | ||
# reconnect to block-relay-only connections on startup. | ||
# Since we do not participate in addr relay with these connections, | ||
# we still want to query the DNS seeds. | ||
for i in range(2): | ||
self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="block-relay-only") | ||
|
||
def force_dns_test(self): | ||
self.log.info("Check that we query DNS seeds if -forcednsseed param is set") | ||
|
||
with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12): | ||
# -dnsseed defaults to 1 in bitcoind, but 0 in the test framework, | ||
# so pass it explicitly here | ||
self.restart_node(0, ["-forcednsseed", "-dnsseed=1"]) | ||
|
||
# Restore default for subsequent tests | ||
self.restart_node(0) | ||
|
||
def wait_time_tests(self): | ||
self.log.info("Check the delay before querying DNS seeds") | ||
|
||
# Populate addrman with < 1000 addresses | ||
for i in range(5): | ||
a = f"192.0.0.{i}" | ||
self.nodes[0].addpeeraddress(a, 8333) | ||
|
||
# The delay should be 11 seconds | ||
with self.nodes[0].assert_debug_log(expected_msgs=["Waiting 11 seconds before querying DNS seeds.\n"]): | ||
self.restart_node(0) | ||
|
||
# Populate addrman with > 1000 addresses | ||
for i in itertools.count(): | ||
first_octet = i % 2 + 1 | ||
second_octet = i % 256 | ||
third_octet = i % 100 | ||
a = f"{first_octet}.{second_octet}.{third_octet}.1" | ||
self.nodes[0].addpeeraddress(a, 8333) | ||
if (i > 1000 and i % 100 == 0): | ||
# The addrman size is non-deterministic because new addresses | ||
# are sorted into buckets, potentially displacing existing | ||
# addresses. Periodically check if we have met the desired | ||
# threshold. | ||
if len(self.nodes[0].getnodeaddresses(0)) > 1000: | ||
break | ||
|
||
# The delay should be 5 mins | ||
with self.nodes[0].assert_debug_log(expected_msgs=["Waiting 300 seconds before querying DNS seeds.\n"]): | ||
self.restart_node(0) | ||
|
||
|
||
if __name__ == '__main__': | ||
P2PDNSSeeds().main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters