From 42dc1725b978329e0808db5e2c3a64c038c35de3 Mon Sep 17 00:00:00 2001 From: sedited Date: Fri, 28 Nov 2025 23:05:17 +0100 Subject: [PATCH 1/4] net processing: Check if we are in ibd before processing block for txdownloadman --- src/net_processing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 51dcadad6f88..5c58efced2cd 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1967,7 +1967,7 @@ void PeerManagerImpl::BlockConnected( // The following task can be skipped since we don't maintain a mempool for // the historical chainstate. - if (role.historical) { + if (role.historical || m_chainman.IsInitialBlockDownload()) { return; } LOCK(m_tx_download_mutex); From 5953ab41ed1a39248d0e03d2e67b100b78f001ae Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 25 Jul 2025 18:14:42 -0400 Subject: [PATCH 2/4] Add m_cached_chaintip_recent and method to update it UpdateCachedChaintipRecent. On systems with sane clocks the chain tip checks can only change when the tip changes. The gap between the chain tip and the current time only grows. --- src/test/util/validation.cpp | 1 + src/validation.cpp | 11 +++++++++++ src/validation.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp index c199d912a386..79c571614aa3 100644 --- a/src/test/util/validation.cpp +++ b/src/test/util/validation.cpp @@ -25,6 +25,7 @@ void TestChainstateManager::DisableNextWrite() void TestChainstateManager::ResetIbd() { m_cached_finished_ibd = false; + m_cached_chaintip_recent = false; assert(IsInitialBlockDownload()); } diff --git a/src/validation.cpp b/src/validation.cpp index 2052748343a2..4f8d18ffefeb 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1983,6 +1983,17 @@ bool ChainstateManager::IsInitialBlockDownload() const return false; } +void ChainstateManager::UpdateCachedChaintipRecent() +{ + AssertLockHeld(cs_main); + CChain& chain{ActiveChain()}; + if (chain.Tip() == nullptr) return; + if (chain.Tip()->nChainWork < MinimumChainWork()) return; + if (chain.Tip()->Time() < Now() - m_options.max_tip_age) return; + + m_cached_chaintip_recent = true; +} + void Chainstate::CheckForkWarningConditions() { AssertLockHeld(cs_main); diff --git a/src/validation.h b/src/validation.h index 77958b53dd11..5688cd7ced35 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1035,6 +1035,7 @@ class ChainstateManager * const, which latches this for caching purposes. */ mutable std::atomic m_cached_finished_ibd{false}; + mutable std::atomic m_cached_chaintip_recent{false}; /** * Every received block is assigned a unique and increasing identifier, so we @@ -1168,6 +1169,7 @@ class ChainstateManager /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload() const; + void UpdateCachedChaintipRecent() EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */ double GuessVerificationProgress(const CBlockIndex* pindex) const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()); From 80de00d88baeab38bc461c0ec336e5867ca6f360 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 25 Jul 2025 18:22:48 -0400 Subject: [PATCH 3/4] Call UpdateCachedChaintipRecent when SetTip is moving the active chain forward. --- src/validation.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/validation.cpp b/src/validation.cpp index 4f8d18ffefeb..88db80c90ce2 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3038,6 +3038,7 @@ bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTra } m_chain.SetTip(*pindexDelete->pprev); + m_chainman.UpdateCachedChaintipRecent(); UpdateTip(pindexDelete->pprev); // Let wallets know transactions went from 1-confirmed to @@ -3168,6 +3169,7 @@ bool Chainstate::ConnectTip( } // Update m_chain & related variables. m_chain.SetTip(*pindexNew); + m_chainman.UpdateCachedChaintipRecent(); UpdateTip(pindexNew); const auto time_6{SteadyClock::now()}; @@ -4654,6 +4656,7 @@ bool Chainstate::LoadChainTip() return false; } m_chain.SetTip(*pindex); + m_chainman.UpdateCachedChaintipRecent(); tip = m_chain.Tip(); // Make sure our chain tip before shutting down scores better than any other candidate From c555abb059c9c5a37a33bc577eab57974824bb80 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 25 Jul 2025 19:32:36 -0400 Subject: [PATCH 4/4] Use m_cached_chaintip_recent in IsIBD removing the cs_main lock. --- src/validation.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 88db80c90ce2..a3dcf1d15195 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1958,26 +1958,13 @@ void Chainstate::InitCoinsCache(size_t cache_size_bytes) // bool ChainstateManager::IsInitialBlockDownload() const { - // Optimization: pre-test latch before taking the lock. - if (m_cached_finished_ibd.load(std::memory_order_relaxed)) - return false; - - LOCK(cs_main); if (m_cached_finished_ibd.load(std::memory_order_relaxed)) return false; if (m_blockman.LoadingBlocks()) { return true; } - CChain& chain{ActiveChain()}; - if (chain.Tip() == nullptr) { - return true; - } - if (chain.Tip()->nChainWork < MinimumChainWork()) { + if (!m_cached_chaintip_recent) return true; - } - if (chain.Tip()->Time() < Now() - m_options.max_tip_age) { - return true; - } LogInfo("Leaving InitialBlockDownload (latching to false)"); m_cached_finished_ibd.store(true, std::memory_order_relaxed); return false;