validation: make IsInitialBlockDownload() lock-free

`ChainstateManager::IsInitialBlockDownload()` is queried on hot paths and previously acquired `cs_main` internally, contributing to lock contention.

Cache the IBD status in `m_cached_is_ibd`, and introduce `ChainstateManager::UpdateIBDStatus()` to latch it once block loading has finished and the current chain tip has enough work and is recent.
Call the updater after tip updates and after `ImportBlocks()` completes.

Since `IsInitialBlockDownload()` no longer updates the cache, drop `mutable` from `m_cached_is_ibd` and only update it from `UpdateIBDStatus()` under `cs_main`.

Update the new unit test to showcase the new `UpdateIBDStatus()`.

Co-authored-by: Patrick Strateman <patrick.strateman@gmail.com>
Co-authored-by: Martin Zumsande <mzumsande@gmail.com>
This commit is contained in:
Lőrinc
2026-01-11 23:57:13 +01:00
parent b9c0ab3b75
commit 557b41a38c
5 changed files with 38 additions and 16 deletions

View File

@@ -1056,6 +1056,7 @@ int btck_chainstate_manager_import_blocks(btck_ChainstateManager* chainman, cons
}
auto& chainman_ref{*btck_ChainstateManager::get(chainman).m_chainman};
node::ImportBlocks(chainman_ref, import_files);
WITH_LOCK(::cs_main, chainman_ref.UpdateIBDStatus());
} catch (const std::exception& e) {
LogError("Failed to import blocks: %s", e.what());
return -1;