mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 03:47:29 -03:00
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
This commit is contained in:
parent
fa0b5d6882
commit
3270f0adad
2 changed files with 36 additions and 9 deletions
43
src/net.cpp
43
src/net.cpp
|
@ -65,6 +65,9 @@ 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;
|
||||
|
||||
/** Minimum number of outbound connections under which we will keep fetching our address seeds. */
|
||||
static constexpr int SEED_OUTBOUND_CONNECTION_THRESHOLD = 2;
|
||||
|
||||
/** How long to delay before querying DNS seeds
|
||||
*
|
||||
* If we have more than THRESHOLD entries in addrman, then it's likely
|
||||
|
@ -2184,7 +2187,6 @@ void CConnman::WakeMessageHandler()
|
|||
|
||||
void CConnman::ThreadDNSAddressSeed()
|
||||
{
|
||||
constexpr int TARGET_OUTBOUND_CONNECTIONS = 2;
|
||||
int outbound_connection_count = 0;
|
||||
|
||||
if (gArgs.IsArgSet("-seednode")) {
|
||||
|
@ -2203,7 +2205,7 @@ void CConnman::ThreadDNSAddressSeed()
|
|||
}
|
||||
|
||||
outbound_connection_count = GetFullOutboundConnCount();
|
||||
if (outbound_connection_count >= TARGET_OUTBOUND_CONNECTIONS) {
|
||||
if (outbound_connection_count >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
|
||||
LogPrintf("P2P peers available. Finished fetching data from seed nodes.\n");
|
||||
break;
|
||||
}
|
||||
|
@ -2226,7 +2228,7 @@ void CConnman::ThreadDNSAddressSeed()
|
|||
}
|
||||
|
||||
// Proceed with dnsseeds if seednodes hasn't reached the target or if forcednsseed is set
|
||||
if (outbound_connection_count < TARGET_OUTBOUND_CONNECTIONS || seeds_right_now) {
|
||||
if (outbound_connection_count < SEED_OUTBOUND_CONNECTION_THRESHOLD || seeds_right_now) {
|
||||
// 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
|
||||
|
@ -2257,7 +2259,7 @@ void CConnman::ThreadDNSAddressSeed()
|
|||
if (!interruptNet.sleep_for(w)) return;
|
||||
to_wait -= w;
|
||||
|
||||
if (GetFullOutboundConnCount() >= TARGET_OUTBOUND_CONNECTIONS) {
|
||||
if (GetFullOutboundConnCount() >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
|
||||
if (found > 0) {
|
||||
LogPrintf("%d addresses found from DNS seeds\n", found);
|
||||
LogPrintf("P2P peers available. Finished DNS seeding.\n");
|
||||
|
@ -2452,7 +2454,7 @@ bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
|
|||
return false;
|
||||
}
|
||||
|
||||
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
||||
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, Span<const std::string> seed_nodes)
|
||||
{
|
||||
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
|
||||
AssertLockNotHeld(m_reconnections_mutex);
|
||||
|
@ -2492,12 +2494,28 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||
bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
|
||||
const bool use_seednodes{gArgs.IsArgSet("-seednode")};
|
||||
|
||||
auto seed_node_timer = NodeClock::now();
|
||||
bool add_addr_fetch{addrman.Size() == 0 && !seed_nodes.empty()};
|
||||
constexpr std::chrono::seconds ADD_NEXT_SEEDNODE = 10s;
|
||||
|
||||
if (!add_fixed_seeds) {
|
||||
LogPrintf("Fixed seeds are disabled\n");
|
||||
}
|
||||
|
||||
while (!interruptNet)
|
||||
{
|
||||
if (add_addr_fetch) {
|
||||
add_addr_fetch = false;
|
||||
const auto& seed{SpanPopBack(seed_nodes)};
|
||||
AddAddrFetch(seed);
|
||||
|
||||
if (addrman.Size() == 0) {
|
||||
LogInfo("Empty addrman, adding seednode (%s) to addrfetch\n", seed);
|
||||
} else {
|
||||
LogInfo("Couldn't connect to peers from addrman after %d seconds. Adding seednode (%s) to addrfetch\n", ADD_NEXT_SEEDNODE.count(), seed);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessAddrFetch();
|
||||
|
||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
|
||||
|
@ -2598,6 +2616,13 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||
}
|
||||
}
|
||||
|
||||
if (!seed_nodes.empty() && nOutboundFullRelay < SEED_OUTBOUND_CONNECTION_THRESHOLD) {
|
||||
if (NodeClock::now() > seed_node_timer + ADD_NEXT_SEEDNODE) {
|
||||
seed_node_timer = NodeClock::now();
|
||||
add_addr_fetch = true;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
|
||||
auto now = GetTime<std::chrono::microseconds>();
|
||||
bool anchor = false;
|
||||
|
@ -3254,8 +3279,10 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
|||
i2p_sam, &interruptNet);
|
||||
}
|
||||
|
||||
for (const auto& strDest : connOptions.vSeedNodes) {
|
||||
AddAddrFetch(strDest);
|
||||
// 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)
|
||||
std::vector<std::string> seed_nodes = connOptions.vSeedNodes;
|
||||
if (!seed_nodes.empty()) {
|
||||
std::shuffle(seed_nodes.begin(), seed_nodes.end(), FastRandomContext{});
|
||||
}
|
||||
|
||||
if (m_use_addrman_outgoing) {
|
||||
|
@ -3316,7 +3343,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
|||
if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
|
||||
threadOpenConnections = std::thread(
|
||||
&util::TraceThread, "opencon",
|
||||
[this, connect = connOptions.m_specified_outgoing] { ThreadOpenConnections(connect); });
|
||||
[this, connect = connOptions.m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });
|
||||
}
|
||||
|
||||
// Process messages
|
||||
|
|
|
@ -1272,7 +1272,7 @@ private:
|
|||
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex);
|
||||
void AddAddrFetch(const std::string& strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex);
|
||||
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_unused_i2p_sessions_mutex);
|
||||
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);
|
||||
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);
|
||||
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
|
||||
void ThreadI2PAcceptIncoming();
|
||||
void AcceptConnection(const ListenSocket& hListenSocket);
|
||||
|
|
Loading…
Reference in a new issue