Skip to content

Commit 3270f0a

Browse files
committed
net: Favor peers from addrman over fetching seednodes
The current behavior of seednode fetching is pretty eager: we do it as the first step under `ThreadOpenNetworkConnections` even if some peers may be queryable from our addrman. This poses two potential issues: - First, if permanently set (e.g. running with seednode in a config file) we'd be signaling such seed every time we restart our node - Second, we will be giving the seed node way too much influence over our addrman, populating the latter even with data from the former even when unnecessary This changes the behavior to only add seednodes to `m_addr_fetch` if our addrman is empty, or little by little after we've spent some time trying addresses from our addrman. Also, seednodes are added to `m_addr_fetch` in random order, to avoid signaling the same node in case more than one seed is added and we happen to try them over multiple restarts
1 parent fa0b5d6 commit 3270f0a

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

src/net.cpp

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15};
6565
/** Number of DNS seeds to query when the number of connections is low. */
6666
static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
6767

68+
/** Minimum number of outbound connections under which we will keep fetching our address seeds. */
69+
static constexpr int SEED_OUTBOUND_CONNECTION_THRESHOLD = 2;
70+
6871
/** How long to delay before querying DNS seeds
6972
*
7073
* If we have more than THRESHOLD entries in addrman, then it's likely
@@ -2184,7 +2187,6 @@ void CConnman::WakeMessageHandler()
21842187

21852188
void CConnman::ThreadDNSAddressSeed()
21862189
{
2187-
constexpr int TARGET_OUTBOUND_CONNECTIONS = 2;
21882190
int outbound_connection_count = 0;
21892191

21902192
if (gArgs.IsArgSet("-seednode")) {
@@ -2203,7 +2205,7 @@ void CConnman::ThreadDNSAddressSeed()
22032205
}
22042206

22052207
outbound_connection_count = GetFullOutboundConnCount();
2206-
if (outbound_connection_count >= TARGET_OUTBOUND_CONNECTIONS) {
2208+
if (outbound_connection_count >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
22072209
LogPrintf("P2P peers available. Finished fetching data from seed nodes.\n");
22082210
break;
22092211
}
@@ -2226,7 +2228,7 @@ void CConnman::ThreadDNSAddressSeed()
22262228
}
22272229

22282230
// Proceed with dnsseeds if seednodes hasn't reached the target or if forcednsseed is set
2229-
if (outbound_connection_count < TARGET_OUTBOUND_CONNECTIONS || seeds_right_now) {
2231+
if (outbound_connection_count < SEED_OUTBOUND_CONNECTION_THRESHOLD || seeds_right_now) {
22302232
// goal: only query DNS seed if address need is acute
22312233
// * If we have a reasonable number of peers in addrman, spend
22322234
// some time trying them first. This improves user privacy by
@@ -2257,7 +2259,7 @@ void CConnman::ThreadDNSAddressSeed()
22572259
if (!interruptNet.sleep_for(w)) return;
22582260
to_wait -= w;
22592261

2260-
if (GetFullOutboundConnCount() >= TARGET_OUTBOUND_CONNECTIONS) {
2262+
if (GetFullOutboundConnCount() >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
22612263
if (found > 0) {
22622264
LogPrintf("%d addresses found from DNS seeds\n", found);
22632265
LogPrintf("P2P peers available. Finished DNS seeding.\n");
@@ -2452,7 +2454,7 @@ bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
24522454
return false;
24532455
}
24542456

2455-
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
2457+
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, Span<const std::string> seed_nodes)
24562458
{
24572459
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
24582460
AssertLockNotHeld(m_reconnections_mutex);
@@ -2492,12 +2494,28 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
24922494
bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
24932495
const bool use_seednodes{gArgs.IsArgSet("-seednode")};
24942496

2497+
auto seed_node_timer = NodeClock::now();
2498+
bool add_addr_fetch{addrman.Size() == 0 && !seed_nodes.empty()};
2499+
constexpr std::chrono::seconds ADD_NEXT_SEEDNODE = 10s;
2500+
24952501
if (!add_fixed_seeds) {
24962502
LogPrintf("Fixed seeds are disabled\n");
24972503
}
24982504

24992505
while (!interruptNet)
25002506
{
2507+
if (add_addr_fetch) {
2508+
add_addr_fetch = false;
2509+
const auto& seed{SpanPopBack(seed_nodes)};
2510+
AddAddrFetch(seed);
2511+
2512+
if (addrman.Size() == 0) {
2513+
LogInfo("Empty addrman, adding seednode (%s) to addrfetch\n", seed);
2514+
} else {
2515+
LogInfo("Couldn't connect to peers from addrman after %d seconds. Adding seednode (%s) to addrfetch\n", ADD_NEXT_SEEDNODE.count(), seed);
2516+
}
2517+
}
2518+
25012519
ProcessAddrFetch();
25022520

25032521
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
@@ -2598,6 +2616,13 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
25982616
}
25992617
}
26002618

2619+
if (!seed_nodes.empty() && nOutboundFullRelay < SEED_OUTBOUND_CONNECTION_THRESHOLD) {
2620+
if (NodeClock::now() > seed_node_timer + ADD_NEXT_SEEDNODE) {
2621+
seed_node_timer = NodeClock::now();
2622+
add_addr_fetch = true;
2623+
}
2624+
}
2625+
26012626
ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
26022627
auto now = GetTime<std::chrono::microseconds>();
26032628
bool anchor = false;
@@ -3254,8 +3279,10 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
32543279
i2p_sam, &interruptNet);
32553280
}
32563281

3257-
for (const auto& strDest : connOptions.vSeedNodes) {
3258-
AddAddrFetch(strDest);
3282+
// Randomize the order in which we may query seednode to potentially prevent connecting to the same one every restart (and signal that we have restarted)
3283+
std::vector<std::string> seed_nodes = connOptions.vSeedNodes;
3284+
if (!seed_nodes.empty()) {
3285+
std::shuffle(seed_nodes.begin(), seed_nodes.end(), FastRandomContext{});
32593286
}
32603287

32613288
if (m_use_addrman_outgoing) {
@@ -3316,7 +3343,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
33163343
if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
33173344
threadOpenConnections = std::thread(
33183345
&util::TraceThread, "opencon",
3319-
[this, connect = connOptions.m_specified_outgoing] { ThreadOpenConnections(connect); });
3346+
[this, connect = connOptions.m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });
33203347
}
33213348

33223349
// Process messages

src/net.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,7 @@ class CConnman
12721272
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex);
12731273
void AddAddrFetch(const std::string& strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex);
12741274
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_unused_i2p_sessions_mutex);
1275-
void ThreadOpenConnections(std::vector<std::string> connect) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex);
1275+
void ThreadOpenConnections(std::vector<std::string> connect, Span<const std::string> seed_nodes) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex);
12761276
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
12771277
void ThreadI2PAcceptIncoming();
12781278
void AcceptConnection(const ListenSocket& hListenSocket);

0 commit comments

Comments
 (0)