Skip to content

Commit

Permalink
net: peer manager, dynamically adjust 'initial sync finished' flag
Browse files Browse the repository at this point in the history
By dynamically adjusting the flag based on the node's proximity to
the tip, we ensure that the new connections desirable services flags
and the extra block relay connections stay relevant throughout the
software's lifecycle.
Unlike the previous approach, where once the validation IBD flag was
set, it remained constant forever.

This will let us recover from stalling scenarios where the node had
successfully synced, but subsequently dropped connections and remained
inactive for a duration longer than the limited peers threshold (the
timeframe within which limited peers can provide blocks). Then, upon
reconnection to the network, the node may end up only establishing
connections with limited peers, leading to an inability to synchronize
the chain.

Additionally, this change prevents the node from initiating extra block
relay connections during this type of stalling situations.
  • Loading branch information
furszy committed Aug 17, 2023
1 parent 79d7fee commit 26a9bb4
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 5 deletions.
6 changes: 6 additions & 0 deletions src/net.cpp
Expand Up @@ -1558,6 +1558,12 @@ void CConnman::StartExtraBlockRelayPeers()
m_start_extra_block_relay_peers = true;
}

void CConnman::StopExtraBlockRelayPeers()
{
LogPrint(BCLog::NET, "disabling extra block-relay-only peers\n");
m_start_extra_block_relay_peers = false;
}

// Return the number of peers we have over our outbound connection limit
// Exclude peers that are marked for disconnect, or are going to be
// disconnected soon (eg ADDR_FETCH and FEELER)
Expand Down
1 change: 1 addition & 0 deletions src/net.h
Expand Up @@ -829,6 +829,7 @@ class CConnman
bool GetTryNewOutboundPeer() const;

void StartExtraBlockRelayPeers();
void StopExtraBlockRelayPeers();

// Return the number of outbound peers we have in excess of our target (eg,
// if we previously called SetTryNewOutboundPeer(true), and have since set
Expand Down
24 changes: 19 additions & 5 deletions src/net_processing.cpp
Expand Up @@ -726,7 +726,8 @@ class PeerManagerImpl final : public PeerManager
bool RejectIncomingTxs(const CNode& peer) const;

/** Whether we've completed initial sync yet, for determining when to turn
* on extra block-relay-only peers. */
* on extra block-relay-only peers and the peer connections desirable
* services flags. */
bool m_initial_sync_finished GUARDED_BY(cs_main){false};

/** Protects m_peer_map. This mutex must not be locked while holding a lock
Expand Down Expand Up @@ -895,7 +896,7 @@ class PeerManagerImpl final : public PeerManager
*/
bool BlockRequested(NodeId nodeid, const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

bool TipMayBeStale() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool TipMayBeStale(bool& super_stale) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

/** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
* at most count entries.
Expand Down Expand Up @@ -1265,14 +1266,21 @@ void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
});
}

bool PeerManagerImpl::TipMayBeStale()
bool PeerManagerImpl::TipMayBeStale(bool& super_stale)
{
AssertLockHeld(cs_main);
const Consensus::Params& consensusParams = m_chainparams.GetConsensus();
if (m_last_tip_update.load() == 0s) {
m_last_tip_update = GetTime<std::chrono::seconds>();
}
return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.nPowTargetSpacing * 3} && mapBlocksInFlight.empty();

auto last_update_time = m_last_tip_update.load();
if (last_update_time < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.nPowTargetSpacing * 3} && mapBlocksInFlight.empty()) {
// If tip is further than NODE_NETWORK_LIMITED_MIN_BLOCKS, we are really behind and shouldn't connect to limited peers anymore.
super_stale = NodeSeconds{last_update_time} < GetAdjustedTime() - std::chrono::seconds{consensusParams.nPowTargetSpacing * NODE_NETWORK_LIMITED_MIN_BLOCKS};
return true;
}
return false;
}

bool PeerManagerImpl::CanDirectFetch()
Expand Down Expand Up @@ -5219,10 +5227,11 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()

EvictExtraOutboundPeers(now);

bool super_stale = false;
if (now > m_stale_tip_check_time) {
// Check whether our tip is stale, and if so, allow using an extra
// outbound peer
if (!m_chainman.m_blockman.LoadingBlocks() && m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() && TipMayBeStale()) {
if (!m_chainman.m_blockman.LoadingBlocks() && m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() && TipMayBeStale(super_stale)) {
LogPrintf("Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
count_seconds(now - m_last_tip_update.load()));
m_connman.SetTryNewOutboundPeer(true);
Expand All @@ -5235,6 +5244,11 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
if (!m_initial_sync_finished && CanDirectFetch()) {
m_connman.StartExtraBlockRelayPeers();
m_initial_sync_finished = true;
} else if (super_stale) {
// Disable extra block relay peers and disallow connection to limited peers.
// We need to find a full node that can help us recover.
m_connman.StopExtraBlockRelayPeers();
m_initial_sync_finished = false;
}
}

Expand Down

0 comments on commit 26a9bb4

Please sign in to comment.