@@ -2172,7 +2172,30 @@ void CConnman::ThreadDNSAddressSeed()
2172
2172
std::vector<std::string> seeds = m_params.DNSSeeds ();
2173
2173
Shuffle (seeds.begin (), seeds.end (), rng);
2174
2174
int seeds_right_now = 0 ; // Number of seeds left before testing if we have enough connections
2175
- int found = 0 ;
2175
+ int target_outbound_connections = 2 ;
2176
+ int outbound_connection_count = 0 ;
2177
+
2178
+ auto start = NodeClock::now ();
2179
+ if (gArgs .IsArgSet (" -seednode" )) {
2180
+ LogPrintf (" -seednode enabled. Trying the provided seeds before defaulting to the dnsseeds.\n " );
2181
+ while (!interruptNet) {
2182
+ if (!interruptNet.sleep_for (std::chrono::milliseconds (500 )))
2183
+ return ;
2184
+
2185
+ // Abort if we have spent enough time without reaching our target.
2186
+ // Giving seed nodes 30 seconds so this does not become a race against fixedseeds (which triggers after 1 min)
2187
+ if (NodeClock::now () > start + 30s) {
2188
+ LogPrintf (" Couldn't connect to enough peers via seed nodes. Handing fetch logic to the DNS seeds.\n " );
2189
+ break ;
2190
+ }
2191
+
2192
+ outbound_connection_count = GetFullOutboundConnCount ();
2193
+ if (outbound_connection_count >= target_outbound_connections) {
2194
+ LogPrintf (" P2P peers available. Finished fetching data from seed nodes.\n " );
2195
+ break ;
2196
+ }
2197
+ }
2198
+ }
2176
2199
2177
2200
if (gArgs .GetBoolArg (" -forcednsseed" , DEFAULT_FORCEDNSSEED)) {
2178
2201
// When -forcednsseed is provided, query all.
@@ -2184,102 +2207,101 @@ void CConnman::ThreadDNSAddressSeed()
2184
2207
seeds_right_now = seeds.size ();
2185
2208
}
2186
2209
2187
- // goal: only query DNS seed if address need is acute
2188
- // * If we have a reasonable number of peers in addrman, spend
2189
- // some time trying them first. This improves user privacy by
2190
- // creating fewer identifying DNS requests, reduces trust by
2191
- // giving seeds less influence on the network topology, and
2192
- // reduces traffic to the seeds.
2193
- // * When querying DNS seeds query a few at once, this ensures
2194
- // that we don't give DNS seeds the ability to eclipse nodes
2195
- // that query them.
2196
- // * If we continue having problems, eventually query all the
2197
- // DNS seeds, and if that fails too, also try the fixed seeds.
2198
- // (done in ThreadOpenConnections)
2199
- const std::chrono::seconds seeds_wait_time = (addrman.Size () >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
2200
-
2201
- for (const std::string& seed : seeds) {
2202
- if (seeds_right_now == 0 ) {
2203
- seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
2204
-
2205
- if (addrman.Size () > 0 ) {
2206
- LogPrintf (" Waiting %d seconds before querying DNS seeds.\n " , seeds_wait_time.count ());
2207
- std::chrono::seconds to_wait = seeds_wait_time;
2208
- while (to_wait.count () > 0 ) {
2209
- // if sleeping for the MANY_PEERS interval, wake up
2210
- // early to see if we have enough peers and can stop
2211
- // this thread entirely freeing up its resources
2212
- std::chrono::seconds w = std::min (DNSSEEDS_DELAY_FEW_PEERS, to_wait);
2213
- if (!interruptNet.sleep_for (w)) return ;
2214
- to_wait -= w;
2215
-
2216
- int nRelevant = 0 ;
2217
- {
2218
- LOCK (m_nodes_mutex);
2219
- for (const CNode* pnode : m_nodes) {
2220
- if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn ()) ++nRelevant;
2210
+ // Proceed with dnsseeds if seednodes hasn't reached the target or if forcednsseed is set
2211
+ if (outbound_connection_count < target_outbound_connections || seeds_right_now) {
2212
+ // goal: only query DNS seed if address need is acute
2213
+ // * If we have a reasonable number of peers in addrman, spend
2214
+ // some time trying them first. This improves user privacy by
2215
+ // creating fewer identifying DNS requests, reduces trust by
2216
+ // giving seeds less influence on the network topology, and
2217
+ // reduces traffic to the seeds.
2218
+ // * When querying DNS seeds query a few at once, this ensures
2219
+ // that we don't give DNS seeds the ability to eclipse nodes
2220
+ // that query them.
2221
+ // * If we continue having problems, eventually query all the
2222
+ // DNS seeds, and if that fails too, also try the fixed seeds.
2223
+ // (done in ThreadOpenConnections)
2224
+ int found = 0 ;
2225
+ const std::chrono::seconds seeds_wait_time = (addrman.Size () >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
2226
+
2227
+ for (const std::string& seed : seeds) {
2228
+ if (seeds_right_now == 0 ) {
2229
+ seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
2230
+
2231
+ if (addrman.Size () > 0 ) {
2232
+ LogPrintf (" Waiting %d seconds before querying DNS seeds.\n " , seeds_wait_time.count ());
2233
+ std::chrono::seconds to_wait = seeds_wait_time;
2234
+ while (to_wait.count () > 0 ) {
2235
+ // if sleeping for the MANY_PEERS interval, wake up
2236
+ // early to see if we have enough peers and can stop
2237
+ // this thread entirely freeing up its resources
2238
+ std::chrono::seconds w = std::min (DNSSEEDS_DELAY_FEW_PEERS, to_wait);
2239
+ if (!interruptNet.sleep_for (w)) return ;
2240
+ to_wait -= w;
2241
+
2242
+ if (GetFullOutboundConnCount () >= target_outbound_connections) {
2243
+ if (found > 0 ) {
2244
+ LogPrintf (" %d addresses found from DNS seeds\n " , found);
2245
+ LogPrintf (" P2P peers available. Finished DNS seeding.\n " );
2246
+ } else {
2247
+ LogPrintf (" P2P peers available. Skipped DNS seeding.\n " );
2248
+ }
2249
+ return ;
2221
2250
}
2222
2251
}
2223
- if (nRelevant >= 2 ) {
2224
- if (found > 0 ) {
2225
- LogPrintf (" %d addresses found from DNS seeds\n " , found);
2226
- LogPrintf (" P2P peers available. Finished DNS seeding.\n " );
2227
- } else {
2228
- LogPrintf (" P2P peers available. Skipped DNS seeding.\n " );
2229
- }
2230
- return ;
2231
- }
2232
2252
}
2233
2253
}
2234
- }
2235
-
2236
- if (interruptNet) return ;
2237
2254
2238
- // hold off on querying seeds if P2P network deactivated
2239
- if (!fNetworkActive ) {
2240
- LogPrintf (" Waiting for network to be reactivated before querying DNS seeds.\n " );
2241
- do {
2242
- if (!interruptNet.sleep_for (std::chrono::seconds{1 })) return ;
2243
- } while (!fNetworkActive );
2244
- }
2255
+ if (interruptNet) return ;
2245
2256
2246
- LogPrintf (" Loading addresses from DNS seed %s\n " , seed);
2247
- // If -proxy is in use, we make an ADDR_FETCH connection to the DNS resolved peer address
2248
- // for the base dns seed domain in chainparams
2249
- if (HaveNameProxy ()) {
2250
- AddAddrFetch (seed);
2251
- } else {
2252
- std::vector<CAddress> vAdd;
2253
- constexpr ServiceFlags requiredServiceBits{SeedsServiceFlags ()};
2254
- std::string host = strprintf (" x%x.%s" , requiredServiceBits, seed);
2255
- CNetAddr resolveSource;
2256
- if (!resolveSource.SetInternal (host)) {
2257
- continue ;
2257
+ // hold off on querying seeds if P2P network deactivated
2258
+ if (!fNetworkActive ) {
2259
+ LogPrintf (" Waiting for network to be reactivated before querying DNS seeds.\n " );
2260
+ do {
2261
+ if (!interruptNet.sleep_for (std::chrono::seconds{1 })) return ;
2262
+ } while (!fNetworkActive );
2258
2263
}
2259
- // Limit number of IPs learned from a single DNS seed. This limit exists to prevent the results from
2260
- // one DNS seed from dominating AddrMan. Note that the number of results from a UDP DNS query is
2261
- // bounded to 33 already, but it is possible for it to use TCP where a larger number of results can be
2262
- // returned.
2263
- unsigned int nMaxIPs = 32 ;
2264
- const auto addresses{LookupHost (host, nMaxIPs, true )};
2265
- if (!addresses.empty ()) {
2266
- for (const CNetAddr& ip : addresses) {
2267
- CAddress addr = CAddress (CService (ip, m_params.GetDefaultPort ()), requiredServiceBits);
2268
- addr.nTime = rng.rand_uniform_delay (Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
2269
- vAdd.push_back (addr);
2270
- found++;
2271
- }
2272
- addrman.Add (vAdd, resolveSource);
2273
- } else {
2274
- // If the seed does not support a subdomain with our desired service bits,
2275
- // we make an ADDR_FETCH connection to the DNS resolved peer address for the
2276
- // base dns seed domain in chainparams
2264
+
2265
+ LogPrintf (" Loading addresses from DNS seed %s\n " , seed);
2266
+ // If -proxy is in use, we make an ADDR_FETCH connection to the DNS resolved peer address
2267
+ // for the base dns seed domain in chainparams
2268
+ if (HaveNameProxy ()) {
2277
2269
AddAddrFetch (seed);
2270
+ } else {
2271
+ std::vector<CAddress> vAdd;
2272
+ constexpr ServiceFlags requiredServiceBits{SeedsServiceFlags ()};
2273
+ std::string host = strprintf (" x%x.%s" , requiredServiceBits, seed);
2274
+ CNetAddr resolveSource;
2275
+ if (!resolveSource.SetInternal (host)) {
2276
+ continue ;
2277
+ }
2278
+ // Limit number of IPs learned from a single DNS seed. This limit exists to prevent the results from
2279
+ // one DNS seed from dominating AddrMan. Note that the number of results from a UDP DNS query is
2280
+ // bounded to 33 already, but it is possible for it to use TCP where a larger number of results can be
2281
+ // returned.
2282
+ unsigned int nMaxIPs = 32 ;
2283
+ const auto addresses{LookupHost (host, nMaxIPs, true )};
2284
+ if (!addresses.empty ()) {
2285
+ for (const CNetAddr& ip : addresses) {
2286
+ CAddress addr = CAddress (CService (ip, m_params.GetDefaultPort ()), requiredServiceBits);
2287
+ addr.nTime = rng.rand_uniform_delay (Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
2288
+ vAdd.push_back (addr);
2289
+ found++;
2290
+ }
2291
+ addrman.Add (vAdd, resolveSource);
2292
+ } else {
2293
+ // If the seed does not support a subdomain with our desired service bits,
2294
+ // we make an ADDR_FETCH connection to the DNS resolved peer address for the
2295
+ // base dns seed domain in chainparams
2296
+ AddAddrFetch (seed);
2297
+ }
2278
2298
}
2299
+ --seeds_right_now;
2279
2300
}
2280
- --seeds_right_now;
2301
+ LogPrintf (" %d addresses found from DNS seeds\n " , found);
2302
+ } else {
2303
+ LogPrintf (" Skipping DNS seeds. Enough peers have been found\n " );
2281
2304
}
2282
- LogPrintf (" %d addresses found from DNS seeds\n " , found);
2283
2305
}
2284
2306
2285
2307
void CConnman::DumpAddresses ()
@@ -2330,6 +2352,19 @@ void CConnman::StartExtraBlockRelayPeers()
2330
2352
m_start_extra_block_relay_peers = true ;
2331
2353
}
2332
2354
2355
+ // Return the number of outbound connections that are full relay (not blocks only)
2356
+ int CConnman::GetFullOutboundConnCount () const
2357
+ {
2358
+ int nRelevant = 0 ;
2359
+ {
2360
+ LOCK (m_nodes_mutex);
2361
+ for (const CNode* pnode : m_nodes) {
2362
+ if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn ()) ++nRelevant;
2363
+ }
2364
+ }
2365
+ return nRelevant;
2366
+ }
2367
+
2333
2368
// Return the number of peers we have over our outbound connection limit
2334
2369
// Exclude peers that are marked for disconnect, or are going to be
2335
2370
// disconnected soon (eg ADDR_FETCH and FEELER)
0 commit comments