chain: add `CChain::IsTipRecent` helper
What changed, and why it matters
This commit is a routine code cleanup in Bitcoin Core. It pulls out a small, existing check ('is the chain tip recent enough?') from one function into a reusable helper, and slightly tidies a nearby block-import wrapper. There is no security-relevant behavior change.
No action required; this is a non-functional refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors ChainstateManager::IsInitialBlockDownload() by extracting the tip existence/work/recency test into a new CChain::IsTipRecent() method in src/chain.h, annotated with EXCLUSIVE_LOCKS_REQUIRED(::cs_main). It also introduces a local chainman_ref in the kernel import-blocks wrapper and unifies return formatting. The logic and lock usage remain unchanged.
Changed components
src/chain.hsrc/kernel/bitcoinkernel.cppsrc/validation.cppInspect captured patch +15 / −18
diff --git a/src/chain.h b/src/chain.h
index 466276c0..e94308aa 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -420,6 +420,15 @@ public:
return int(vChain.size()) - 1;
}
+ /** Check whether this chain's tip exists, has enough work, and is recent. */
+ bool IsTipRecent(const arith_uint256& min_chain_work, std::chrono::seconds max_tip_age) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
+ {
+ const auto tip{Tip()};
+ return tip &&
+ tip->nChainWork >= min_chain_work &&
+ tip->Time() >= Now<NodeSeconds>() - max_tip_age;
+ }
+
/** Set/initialize a chain with a given tip. */
void SetTip(CBlockIndex& block);
diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp
index bbcfd66b..b061a185 100644
--- a/src/kernel/bitcoinkernel.cpp
+++ b/src/kernel/bitcoinkernel.cpp
@@ -1054,7 +1054,8 @@ int btck_chainstate_manager_import_blocks(btck_ChainstateManager* chainman, cons
import_files.emplace_back(std::string{block_file_paths_data[i], block_file_paths_lens[i]}.c_str());
}
}
- node::ImportBlocks(*btck_ChainstateManager::get(chainman).m_chainman, import_files);
+ auto& chainman_ref{*btck_ChainstateManager::get(chainman).m_chainman};
+ node::ImportBlocks(chainman_ref, import_files);
} catch (const std::exception& e) {
LogError("Failed to import blocks: %s", e.what());
return -1;
diff --git a/src/validation.cpp b/src/validation.cpp
index 3b10237e..1b3b09cb 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1947,25 +1947,12 @@ void Chainstate::InitCoinsCache(size_t cache_size_bytes)
bool ChainstateManager::IsInitialBlockDownload() const
{
// Optimization: pre-test latch before taking the lock.
- if (!m_cached_is_ibd.load(std::memory_order_relaxed))
- return false;
+ if (!m_cached_is_ibd.load(std::memory_order_relaxed)) return false;
LOCK(cs_main);
- if (!m_cached_is_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()) {
- return true;
- }
- if (chain.Tip()->Time() < Now<NodeSeconds>() - m_options.max_tip_age) {
- return true;
- }
+ if (!m_cached_is_ibd.load(std::memory_order_relaxed)) return false;
+ if (m_blockman.LoadingBlocks()) return true;
+ if (!ActiveChain().IsTipRecent(MinimumChainWork(), m_options.max_tip_age)) return true;
LogInfo("Leaving InitialBlockDownload (latching to false)");
m_cached_is_ibd.store(false, std::memory_order_relaxed);
return false;
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.