diff --git a/src/net_processing.cpp b/src/net_processing.cpp index c01f93c21aed..53d86a91e578 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -413,6 +413,9 @@ struct Peer { * timestamp the peer sent in the version message. */ std::atomic m_time_offset{0s}; + /** Whether we've started headers synchronization with this peer. */ + std::atomic fSyncStarted{false}; + explicit Peer(NodeId id, ServiceFlags our_services, bool is_inbound) : m_id{id} , m_our_services{our_services} @@ -443,8 +446,6 @@ struct CNodeState { const CBlockIndex* pindexLastCommonBlock{nullptr}; //! The best header we have sent our peer. const CBlockIndex* pindexBestHeaderSent{nullptr}; - //! Whether we've started headers synchronization with this peer. - bool fSyncStarted{false}; //! Since when we're stalling block download progress (in microseconds), or 0. std::chrono::microseconds m_stalling_since{0us}; std::list vBlocksInFlight; @@ -830,7 +831,7 @@ class PeerManagerImpl final : public PeerManager std::map m_next_inv_to_inbounds_per_network_key GUARDED_BY(g_msgproc_mutex); /** Number of nodes with fSyncStarted. */ - int nSyncStarted GUARDED_BY(cs_main) = 0; + std::atomic nSyncStarted{0}; /** Hash of the last block we received via INV */ uint256 m_last_block_inv_triggering_headers_sync GUARDED_BY(g_msgproc_mutex){}; @@ -1699,13 +1700,12 @@ void PeerManagerImpl::FinalizeNode(const CNode& node) assert(peer != nullptr); m_wtxid_relay_peers -= peer->m_wtxid_relay; assert(m_wtxid_relay_peers >= 0); + nSyncStarted -= peer->fSyncStarted; + assert(nSyncStarted >= 0); } CNodeState *state = State(nodeid); assert(state != nullptr); - if (state->fSyncStarted) - nSyncStarted--; - for (const QueuedBlock& entry : state->vBlocksInFlight) { auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash()); while (range.first != range.second) { @@ -1737,6 +1737,7 @@ void PeerManagerImpl::FinalizeNode(const CNode& node) assert(m_peers_downloading_from == 0); assert(m_outbound_peers_with_protect_from_disconnect == 0); assert(m_wtxid_relay_peers == 0); + assert(nSyncStarted == 0); WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty()); } } // cs_main @@ -4180,14 +4181,13 @@ void PeerManagerImpl::ProcessMessage(Peer& peer, CNode& pfrom, const std::string // block to sync with as well, to sync quicker in the case where // our initial peer is unresponsive (but less bandwidth than we'd // use if we turned on sync with all peers). - CNodeState& state{*Assert(State(pfrom.GetId()))}; - if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) { + if (peer.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) { if (MaybeSendGetHeaders(pfrom, GetLocator(m_chainman.m_best_header), peer)) { LogDebug(BCLog::NET, "getheaders (%d) %s to peer=%d\n", m_chainman.m_best_header->nHeight, best_block->ToString(), pfrom.GetId()); } - if (!state.fSyncStarted) { + if (!peer.fSyncStarted) { peer.m_inv_triggered_getheaders_before_sync = true; // Update the last block hash that triggered a new headers // sync, so that we don't turn on headers sync with more @@ -5226,7 +5226,7 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seco CNodeState &state = *State(pto.GetId()); - if (!state.m_chain_sync.m_protect && pto.IsOutboundOrBlockRelayConn() && state.fSyncStarted) { + if (!state.m_chain_sync.m_protect && pto.IsOutboundOrBlockRelayConn() && peer.fSyncStarted) { // This is an outbound peer subject to disconnection if they don't // announce a block with as much work as the current tip within // CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds (note: if @@ -5874,7 +5874,7 @@ bool PeerManagerImpl::SendMessages(CNode& node) } } - if (!state.fSyncStarted && CanServeBlocks(peer) && !m_chainman.m_blockman.LoadingBlocks()) { + if (!peer.fSyncStarted && CanServeBlocks(peer) && !m_chainman.m_blockman.LoadingBlocks()) { // Only actively request headers from a single peer, unless we're close to today. if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() > NodeClock::now() - 24h) { const CBlockIndex* pindexStart = m_chainman.m_best_header; @@ -5890,7 +5890,7 @@ bool PeerManagerImpl::SendMessages(CNode& node) if (MaybeSendGetHeaders(node, GetLocator(pindexStart), peer)) { LogDebug(BCLog::NET, "initial getheaders (%d) to peer=%d", pindexStart->nHeight, node.GetId()); - state.fSyncStarted = true; + peer.fSyncStarted = true; peer.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE + ( // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling @@ -6202,7 +6202,7 @@ bool PeerManagerImpl::SendMessages(CNode& node) } } // Check for headers sync timeouts - if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) { + if (peer.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) { // Detect whether this is a stalling initial-headers-sync peer if (m_chainman.m_best_header->Time() <= NodeClock::now() - 24h) { if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) { @@ -6222,7 +6222,7 @@ bool PeerManagerImpl::SendMessages(CNode& node) // Note: this will also result in at least one more // getheaders message to be sent to // this peer (eventually). - state.fSyncStarted = false; + peer.fSyncStarted = false; nSyncStarted--; peer.m_headers_sync_timeout = 0us; }