Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,8 @@ class CRegTestParams : public CChainParams {
assert(genesis.hashMerkleRoot == uint256S("0xe0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7"));

vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds.
vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds.
vSeeds.clear();
vSeeds.emplace_back("dummySeed.invalid.");

fDefaultConsistencyChecks = true;
fRequireStandard = true;
Expand Down
7 changes: 6 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-dnsseed", strprintf("Query for peer addresses via DNS lookup, if low on addresses (default: %u unless -connect used)", DEFAULT_DNSSEED), ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
argsman.AddArg("-externalip=<ip>", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-fixedseeds", strprintf("Allow fixed seeds if DNS seeds don't provide peers (default: %u)", DEFAULT_FIXEDSEEDS), ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
argsman.AddArg("-listen", "Accept connections from outside (default: 1 if no -proxy or -connect)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> connections to peers (temporary service connections excluded) (default: %u)", DEFAULT_MAX_PEER_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
Expand Down Expand Up @@ -1250,6 +1250,11 @@ bool AppInitParameterInteraction(const ArgsManager& args)

fAllowPrivateNet = args.GetBoolArg("-allowprivatenet", DEFAULT_ALLOWPRIVATENET);

// If -forcednsseed is set to true, ensure -dnsseed has not been set to false
if (args.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED) && !args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED)){
return InitError(_("Cannot set -forcednsseed to true when setting -dnsseed to false."));
}

// -bind and -whitebind can't be set when not listening
size_t nUserBind = args.GetArgs("-bind").size() + args.GetArgs("-whitebind").size();
if (nUserBind != 0 && !args.GetBoolArg("-listen", DEFAULT_LISTEN)) {
Expand Down
6 changes: 3 additions & 3 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ static const int64_t DEFAULT_PEER_CONNECT_TIMEOUT = 60;
/** Number of file descriptors required for message capture **/
static const int NUM_FDS_MESSAGE_CAPTURE = 1;

static const bool DEFAULT_FORCEDNSSEED = false;
static const bool DEFAULT_DNSSEED = true;
static const bool DEFAULT_FIXEDSEEDS = true;
static constexpr bool DEFAULT_FORCEDNSSEED{false};
static constexpr bool DEFAULT_DNSSEED{true};
static constexpr bool DEFAULT_FIXEDSEEDS{true};
static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000;
static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000;

Expand Down
5 changes: 3 additions & 2 deletions test/functional/feature_config_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,9 @@ def test_seed_peers(self):
self.stop_node(0)

# No peers.dat exists and -dnsseed=1
# We expect the node will use DNS Seeds, but Regtest mode has 0 DNS seeds
# So after 60 seconds, the node should fallback to fixed seeds (this is a slow test)
# We expect the node will use DNS Seeds, but Regtest mode does not have
# any valid DNS seeds. So after 60 seconds, the node should fallback to
# fixed seeds
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
start = int(time.time())
with self.nodes[0].assert_debug_log(expected_msgs=[
Expand Down
129 changes: 129 additions & 0 deletions test/functional/p2p_dns_seeds.py
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()
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
'wallet_listreceivedby.py --legacy-wallet',
'wallet_listreceivedby.py --descriptors',
'wallet_abandonconflict.py --legacy-wallet',
'p2p_dns_seeds.py',
'wallet_abandonconflict.py --descriptors',
'feature_csv_activation.py',
'rpc_rawtransaction.py --legacy-wallet',
Expand Down