diff options
author | fanquake <fanquake@gmail.com> | 2020-05-29 17:26:47 +0800 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2020-05-29 18:24:09 +0800 |
commit | 73407ff65cefa29ce522cb3cb43898497e8afa30 (patch) | |
tree | c53a3ad8551b61bb5065a567ffc4af4ee6ccb17a | |
parent | d7f5e01e30938c586c3279c91914add94eeb239c (diff) | |
parent | 96954d17948662672cababc940e453dff08e8cbb (diff) |
Merge #16939: p2p: Delay querying DNS seeds
96954d17948662672cababc940e453dff08e8cbb DNS seeds: don't query DNS while network is inactive (Anthony Towns)
fa5894f7f581718ea28bb34b52fcd3b33ff3e644 DNS seeds: wait for 5m instead of 11s if 1000+ peers are known (Anthony Towns)
Pull request description:
Changes the logic for querying DNS seeds: after this PR, if there's less than 1000 entries in addrman, it will still usually query DNS seeds after 11s (unless the first few peers tried mostly succeed), but if there's more than 1000 entries it won't try DNS seeds until 5 minutes have passed without getting multiple outbound peers. (If there's 0 entries in addrman, it will still immediately query the DNS seeds). Additionally, delays querying DNS seeds while the p2p network is not active.
Fixes #15434
ACKs for top commit:
fanquake:
ACK 96954d17948662672cababc940e453dff08e8cbb - Ran some tests of different scenarios. More documentation is being added in #19084.
ariard:
Tested ACK 96954d1, on Debian 9.1. Both MANY_PEERS/FEW_PEERS cases work.
Sjors:
tACK 96954d1 (rebased on master) on macOS 10.15.4. It found it useful to run with `-debug=addrman` and change `DNSSEEDS_DELAY_MANY_PEERS` to something lower to test the behaviour, as well as renaming `peers.dat` to test the peer threshold.
naumenkogs:
utACK 96954d17948662672cababc940e453dff08e8cbb
Tree-SHA512: 73693db3da73bf8e76c3df9e9c82f0a7fb08049187356eac2575c4ffa455f76548dd1c86a11fc6beea8a3baf0ba020e047bebe927883c731383ec72442356005
-rw-r--r-- | src/net.cpp | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/src/net.cpp b/src/net.cpp index c9cfb67ec8..707412bb32 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -52,6 +52,12 @@ static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15}; /** Number of DNS seeds to query when the number of connections is low. */ static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3; +/** How long to delay before querying DNS seeds + */ +static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11}; // 11sec +static constexpr std::chrono::seconds DNSSEEDS_DELAY_MANY_PEERS{300}; // 5min +static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers -- you should only get this many if you've been on the live network + // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. #define FEELER_SLEEP_WINDOW 1 @@ -1587,31 +1593,67 @@ void CConnman::ThreadDNSAddressSeed() if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) { // When -forcednsseed is provided, query all. seeds_right_now = seeds.size(); + } else if (addrman.size() == 0) { + // If we have no known peers, query all. + seeds_right_now = seeds.size(); } + // goal: only query DNS seed if address need is acute + // * If we have a reasonable number of peers in addrman, spend + // some time trying them first. This improves user privacy by + // creating fewer identifying DNS requests, reduces trust by + // giving seeds less influence on the network topology, and + // reduces traffic to the seeds. + // * When querying DNS seeds query a few at once, this ensures + // that we don't give DNS seeds the ability to eclipse nodes + // that query them. + // * If we continue having problems, eventually query all the + // DNS seeds, and if that fails too, also try the fixed seeds. + // (done in ThreadOpenConnections) + const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS); + for (const std::string& seed : seeds) { - // goal: only query DNS seed if address need is acute - // Avoiding DNS seeds when we don't need them improves user privacy by - // creating fewer identifying DNS requests, reduces trust by giving seeds - // less influence on the network topology, and reduces traffic to the seeds. - if (addrman.size() > 0 && seeds_right_now == 0) { - if (!interruptNet.sleep_for(std::chrono::seconds(11))) return; + if (seeds_right_now == 0) { + seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE; - LOCK(cs_vNodes); - int nRelevant = 0; - for (const CNode* pnode : vNodes) { - nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound; - } - if (nRelevant >= 2) { - LogPrintf("P2P peers available. Skipped DNS seeding.\n"); - return; + if (addrman.size() > 0) { + LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count()); + std::chrono::seconds to_wait = seeds_wait_time; + while (to_wait.count() > 0) { + std::chrono::seconds w = std::min(DNSSEEDS_DELAY_FEW_PEERS, to_wait); + if (!interruptNet.sleep_for(w)) return; + to_wait -= w; + + int nRelevant = 0; + { + LOCK(cs_vNodes); + for (const CNode* pnode : vNodes) { + nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound; + } + } + if (nRelevant >= 2) { + if (found > 0) { + LogPrintf("%d addresses found from DNS seeds\n", found); + LogPrintf("P2P peers available. Finished DNS seeding.\n"); + } else { + LogPrintf("P2P peers available. Skipped DNS seeding.\n"); + } + return; + } + } } - seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE; } - if (interruptNet) { - return; + if (interruptNet) return; + + // hold off on querying seeds if p2p network deactivated + if (!fNetworkActive) { + LogPrintf("Waiting for network to be reactivated before querying DNS seeds.\n"); + do { + if (!interruptNet.sleep_for(std::chrono::seconds{1})) return; + } while (!fNetworkActive); } + LogPrintf("Loading addresses from DNS seed %s\n", seed); if (HaveNameProxy()) { AddOneShot(seed); |