Skip to content

Commit 3120a46

Browse files
committed
Gives seednode priority over dnsseed if both are provided
1 parent 3310a96 commit 3120a46

File tree

2 files changed

+123
-86
lines changed

2 files changed

+123
-86
lines changed

src/net.cpp

Lines changed: 121 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -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

22852307
void 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)

src/net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,8 @@ class CConnman
11751175

11761176
void StartExtraBlockRelayPeers();
11771177

1178+
// Count the number of full-relay peer we have.
1179+
int GetFullOutboundConnCount() const;
11781180
// Return the number of outbound peers we have in excess of our target (eg,
11791181
// if we previously called SetTryNewOutboundPeer(true), and have since set
11801182
// to false, we may have extra peers that we wish to disconnect). This may

0 commit comments

Comments
 (0)