Skip to content

Commit fe3e993

Browse files
committed
[p2p] No delay in adding fixed seeds if -dnsseed=0 and peers.dat is empty. Add -fixedseeds arg.
1 parent 6c61408 commit fe3e993

File tree

4 files changed

+96
-14
lines changed

4 files changed

+96
-14
lines changed

src/init.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,9 @@ void SetupServerArgs(NodeContext& node)
434434
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
435435
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
436436
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
437-
argsman.AddArg("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
437+
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);
438438
argsman.AddArg("-externalip=<ip>", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
439+
argsman.AddArg("-fixedseeds", strprintf("Allow fixed seeds if DNS seeds don't provide peers (default: %u)", DEFAULT_FIXEDSEEDS), ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
439440
argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
440441
argsman.AddArg("-listen", "Accept connections from outside (default: 1 if no -proxy or -connect)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
441442
argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);

src/net.cpp

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,11 +1769,19 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
17691769
}
17701770

17711771
// Initiate network connections
1772-
int64_t nStart = GetTime();
1772+
auto start = GetTime<std::chrono::seconds>();
17731773

17741774
// Minimum time before next feeler connection (in microseconds).
1775-
int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
1776-
int64_t nNextExtraBlockRelay = PoissonNextSend(nStart*1000*1000, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
1775+
1776+
int64_t nNextFeeler = PoissonNextSend(count_microseconds(start), FEELER_INTERVAL);
1777+
int64_t nNextExtraBlockRelay = PoissonNextSend(count_microseconds(start), EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
1778+
const bool dnsseed = gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED);
1779+
bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
1780+
1781+
if (!add_fixed_seeds) {
1782+
LogPrintf("Fixed seeds are disabled\n");
1783+
}
1784+
17771785
while (!interruptNet)
17781786
{
17791787
ProcessAddrFetch();
@@ -1785,18 +1793,32 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
17851793
if (interruptNet)
17861794
return;
17871795

1788-
// Add seed nodes if DNS seeds are all down (an infrastructure attack?).
1789-
// Note that we only do this if we started with an empty peers.dat,
1790-
// (in which case we will query DNS seeds immediately) *and* the DNS
1791-
// seeds have not returned any results.
1792-
if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
1793-
static bool done = false;
1794-
if (!done) {
1795-
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
1796+
if (add_fixed_seeds && addrman.size() == 0) {
1797+
// When the node starts with an empty peers.dat, there are a few other sources of peers before
1798+
// we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
1799+
// If none of those are available, we fallback on to fixed seeds immediately, else we allow
1800+
// 60 seconds for any of those sources to populate addrman.
1801+
bool add_fixed_seeds_now = false;
1802+
// It is cheapest to check if enough time has passed first.
1803+
if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
1804+
add_fixed_seeds_now = true;
1805+
LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty\n");
1806+
}
1807+
1808+
// Checking !dnsseed is cheaper before locking 2 mutexes.
1809+
if (!add_fixed_seeds_now && !dnsseed) {
1810+
LOCK2(m_addr_fetches_mutex, cs_vAddedNodes);
1811+
if (m_addr_fetches.empty() && vAddedNodes.empty()) {
1812+
add_fixed_seeds_now = true;
1813+
LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and and all -seednode(s) attempted\n");
1814+
}
1815+
}
1816+
1817+
if (add_fixed_seeds_now) {
17961818
CNetAddr local;
17971819
local.SetInternal("fixedseeds");
17981820
addrman.Add(convertSeed6(Params().FixedSeeds()), local);
1799-
done = true;
1821+
add_fixed_seeds = false;
18001822
}
18011823
}
18021824

@@ -2434,7 +2456,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
24342456
// Send and receive from sockets, accept connections
24352457
threadSocketHandler = std::thread(&TraceThread<std::function<void()> >, "net", std::function<void()>(std::bind(&CConnman::ThreadSocketHandler, this)));
24362458

2437-
if (!gArgs.GetBoolArg("-dnsseed", true))
2459+
if (!gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED))
24382460
LogPrintf("DNS seeding disabled\n");
24392461
else
24402462
threadDNSAddressSeed = std::thread(&TraceThread<std::function<void()> >, "dnsseed", std::function<void()>(std::bind(&CConnman::ThreadDNSAddressSeed, this)));

src/net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ static const int64_t DEFAULT_PEER_CONNECT_TIMEOUT = 60;
8080
static const int NUM_FDS_MESSAGE_CAPTURE = 1;
8181

8282
static const bool DEFAULT_FORCEDNSSEED = false;
83+
static const bool DEFAULT_DNSSEED = true;
84+
static const bool DEFAULT_FIXEDSEEDS = true;
8385
static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000;
8486
static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000;
8587

test/functional/feature_config_args.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""Test various command line arguments and configuration file parameters."""
66

77
import os
8+
import time
89

910
from test_framework.test_framework import BitcoinTestFramework
1011
from test_framework import util
@@ -147,11 +148,67 @@ def test_networkactive(self):
147148
self.start_node(0, extra_args=['-nonetworkactive=1'])
148149
self.stop_node(0)
149150

151+
def test_seed_peers(self):
152+
self.log.info('Test seed peers, this will take about 2 minutes')
153+
default_data_dir = self.nodes[0].datadir
154+
155+
# No peers.dat exists and -dnsseed=1
156+
# We expect the node will use DNS Seeds, but Regtest mode has 0 DNS seeds
157+
# So after 60 seconds, the node should fallback to fixed seeds (this is a slow test)
158+
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
159+
start = time.time()
160+
with self.nodes[0].assert_debug_log(expected_msgs=[
161+
"Loaded 0 addresses from peers.dat",
162+
"0 addresses found from DNS seeds",
163+
"Adding fixed seeds as 60 seconds have passed and addrman is empty"], timeout=80):
164+
self.start_node(0, extra_args=['-dnsseed=1'])
165+
assert time.time() - start >= 60
166+
self.stop_node(0)
167+
168+
# No peers.dat exists and -dnsseed=0
169+
# We expect the node will fallback immediately to fixed seeds
170+
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
171+
start = time.time()
172+
with self.nodes[0].assert_debug_log(expected_msgs=[
173+
"Loaded 0 addresses from peers.dat",
174+
"DNS seeding disabled",
175+
"Adding fixed seeds as -dnsseed=0, -addnode is not provided and and all -seednode(s) attempted\n"]):
176+
self.start_node(0, extra_args=['-dnsseed=0'])
177+
assert time.time() - start < 60
178+
self.stop_node(0)
179+
180+
# No peers.dat exists and dns seeds are disabled.
181+
# We expect the node will not add fixed seeds when explicitly disabled.
182+
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
183+
start = time.time()
184+
with self.nodes[0].assert_debug_log(expected_msgs=[
185+
"Loaded 0 addresses from peers.dat",
186+
"DNS seeding disabled",
187+
"Fixed seeds are disabled"]):
188+
self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=0'])
189+
assert time.time() - start < 60
190+
self.stop_node(0)
191+
192+
# No peers.dat exists and -dnsseed=0, but a -addnode is provided
193+
# We expect the node will allow 60 seconds prior to using fixed seeds
194+
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
195+
start = time.time()
196+
with self.nodes[0].assert_debug_log(expected_msgs=[
197+
"Loaded 0 addresses from peers.dat",
198+
"DNS seeding disabled",
199+
"Adding fixed seeds as 60 seconds have passed and addrman is empty"],
200+
timeout=80):
201+
self.start_node(0, extra_args=['-dnsseed=0', '-addnode=fakenodeaddr'])
202+
assert time.time() - start >= 60
203+
self.stop_node(0)
204+
205+
150206
def run_test(self):
151207
self.stop_node(0)
152208

153209
self.test_log_buffer()
154210
self.test_args_log()
211+
self.test_seed_peers()
155212
self.test_networkactive()
156213

157214
self.test_config_file_parser()

0 commit comments

Comments
 (0)