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. */
|
/** Number of DNS seeds to query when the number of connections is low. */
|
||||||
static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
|
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
|
/** How long to delay before querying DNS seeds
|
||||||
*
|
*
|
||||||
* If we have more than THRESHOLD entries in addrman, then it's likely
|
* If we have more than THRESHOLD entries in addrman, then it's likely
|
||||||
|
@ -2184,7 +2187,6 @@ void CConnman::WakeMessageHandler()
|
||||||
|
|
||||||
void CConnman::ThreadDNSAddressSeed()
|
void CConnman::ThreadDNSAddressSeed()
|
||||||
{
|
{
|
||||||
constexpr int TARGET_OUTBOUND_CONNECTIONS = 2;
|
|
||||||
int outbound_connection_count = 0;
|
int outbound_connection_count = 0;
|
||||||
|
|
||||||
if (gArgs.IsArgSet("-seednode")) {
|
if (gArgs.IsArgSet("-seednode")) {
|
||||||
|
@ -2203,7 +2205,7 @@ void CConnman::ThreadDNSAddressSeed()
|
||||||
}
|
}
|
||||||
|
|
||||||
outbound_connection_count = GetFullOutboundConnCount();
|
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");
|
LogPrintf("P2P peers available. Finished fetching data from seed nodes.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2226,7 +2228,7 @@ void CConnman::ThreadDNSAddressSeed()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proceed with dnsseeds if seednodes hasn't reached the target or if forcednsseed is set
|
// 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
|
// goal: only query DNS seed if address need is acute
|
||||||
// * If we have a reasonable number of peers in addrman, spend
|
// * If we have a reasonable number of peers in addrman, spend
|
||||||
// some time trying them first. This improves user privacy by
|
// some time trying them first. This improves user privacy by
|
||||||
|
@ -2257,7 +2259,7 @@ void CConnman::ThreadDNSAddressSeed()
|
||||||
if (!interruptNet.sleep_for(w)) return;
|
if (!interruptNet.sleep_for(w)) return;
|
||||||
to_wait -= w;
|
to_wait -= w;
|
||||||
|
|
||||||
if (GetFullOutboundConnCount() >= TARGET_OUTBOUND_CONNECTIONS) {
|
if (GetFullOutboundConnCount() >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
|
||||||
if (found > 0) {
|
if (found > 0) {
|
||||||
LogPrintf("%d addresses found from DNS seeds\n", found);
|
LogPrintf("%d addresses found from DNS seeds\n", found);
|
||||||
LogPrintf("P2P peers available. Finished DNS seeding.\n");
|
LogPrintf("P2P peers available. Finished DNS seeding.\n");
|
||||||
|
@ -2452,7 +2454,7 @@ bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
|
||||||
return false;
|
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_unused_i2p_sessions_mutex);
|
||||||
AssertLockNotHeld(m_reconnections_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);
|
bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
|
||||||
const bool use_seednodes{gArgs.IsArgSet("-seednode")};
|
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) {
|
if (!add_fixed_seeds) {
|
||||||
LogPrintf("Fixed seeds are disabled\n");
|
LogPrintf("Fixed seeds are disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!interruptNet)
|
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();
|
ProcessAddrFetch();
|
||||||
|
|
||||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
|
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;
|
ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
|
||||||
auto now = GetTime<std::chrono::microseconds>();
|
auto now = GetTime<std::chrono::microseconds>();
|
||||||
bool anchor = false;
|
bool anchor = false;
|
||||||
|
@ -3254,8 +3279,10 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
||||||
i2p_sam, &interruptNet);
|
i2p_sam, &interruptNet);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& strDest : connOptions.vSeedNodes) {
|
// 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)
|
||||||
AddAddrFetch(strDest);
|
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) {
|
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()) {
|
if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
|
||||||
threadOpenConnections = std::thread(
|
threadOpenConnections = std::thread(
|
||||||
&util::TraceThread, "opencon",
|
&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
|
// 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 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 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 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 ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
|
||||||
void ThreadI2PAcceptIncoming();
|
void ThreadI2PAcceptIncoming();
|
||||||
void AcceptConnection(const ListenSocket& hListenSocket);
|
void AcceptConnection(const ListenSocket& hListenSocket);
|
||||||
|
|
Loading…
Reference in a new issue