@@ -2172,7 +2172,30 @@ void CConnman::ThreadDNSAddressSeed()
21722172 std::vector<std::string> seeds = m_params.DNSSeeds ();
21732173 Shuffle (seeds.begin (), seeds.end (), rng);
21742174 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+ }
21762199
21772200 if (gArgs .GetBoolArg (" -forcednsseed" , DEFAULT_FORCEDNSSEED)) {
21782201 // When -forcednsseed is provided, query all.
@@ -2184,102 +2207,101 @@ void CConnman::ThreadDNSAddressSeed()
21842207 seeds_right_now = seeds.size ();
21852208 }
21862209
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 ;
22212250 }
22222251 }
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- }
22322252 }
22332253 }
2234- }
2235-
2236- if (interruptNet) return ;
22372254
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 ;
22452256
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 );
22582263 }
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 ()) {
22772269 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+ }
22782298 }
2299+ --seeds_right_now;
22792300 }
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 " );
22812304 }
2282- LogPrintf (" %d addresses found from DNS seeds\n " , found);
22832305}
22842306
22852307void CConnman::DumpAddresses ()
@@ -2330,6 +2352,19 @@ void CConnman::StartExtraBlockRelayPeers()
23302352 m_start_extra_block_relay_peers = true ;
23312353}
23322354
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+
23332368// Return the number of peers we have over our outbound connection limit
23342369// Exclude peers that are marked for disconnect, or are going to be
23352370// disconnected soon (eg ADDR_FETCH and FEELER)
0 commit comments