Skip to content

Commit cb1590b

Browse files
committed
kernel: Add chainstate loading when instantiating a ChainstateManager
The library will now internally load the chainstate when a new ChainstateManager is instantiated. Options for controlling details of loading the chainstate will be added over the next few commits.
1 parent e2c1bd3 commit cb1590b

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/kernel/bitcoinkernel.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <kernel/bitcoinkernel.h>
88

99
#include <consensus/amount.h>
10+
#include <consensus/validation.h>
1011
#include <kernel/caches.h>
1112
#include <kernel/chainparams.h>
1213
#include <kernel/checks.h>
@@ -16,6 +17,7 @@
1617
#include <kernel/warning.h>
1718
#include <logging.h>
1819
#include <node/blockstorage.h>
20+
#include <node/chainstate.h>
1921
#include <primitives/transaction.h>
2022
#include <script/interpreter.h>
2123
#include <script/script.h>
@@ -38,6 +40,7 @@
3840
#include <memory>
3941
#include <span>
4042
#include <string>
43+
#include <tuple>
4144
#include <utility>
4245
#include <vector>
4346

@@ -363,6 +366,7 @@ struct ChainstateManagerOptions {
363366
ChainstateManager::Options m_chainman_options GUARDED_BY(m_mutex);
364367
node::BlockManager::Options m_blockman_options GUARDED_BY(m_mutex);
365368
std::shared_ptr<const Context> m_context;
369+
node::ChainstateLoadOptions m_chainstate_load_options GUARDED_BY(m_mutex);
366370

367371
ChainstateManagerOptions(const std::shared_ptr<const Context>& context, const fs::path& data_dir, const fs::path& blocks_dir)
368372
: m_chainman_options{ChainstateManager::Options{
@@ -377,7 +381,7 @@ struct ChainstateManagerOptions {
377381
.path = data_dir / "blocks" / "index",
378382
.cache_bytes = kernel::CacheSizes{DEFAULT_KERNEL_CACHE}.block_tree_db,
379383
}}},
380-
m_context{context}
384+
m_context{context}, m_chainstate_load_options{node::ChainstateLoadOptions{}}
381385
{
382386
}
383387
};
@@ -703,16 +707,44 @@ void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* opti
703707
btck_ChainstateManager* btck_chainstate_manager_create(
704708
const btck_ChainstateManagerOptions* chainman_opts)
705709
{
710+
auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
711+
std::unique_ptr<ChainstateManager> chainman;
706712
try {
707-
auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
708713
LOCK(opts.m_mutex);
709-
auto& context{opts.m_context};
710-
auto chainman{std::make_unique<ChainstateManager>(*context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options)};
711-
return btck_ChainstateManager::create(std::move(chainman), context);
714+
chainman = std::make_unique<ChainstateManager>(*opts.m_context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options);
712715
} catch (const std::exception& e) {
713716
LogError("Failed to create chainstate manager: %s", e.what());
714717
return nullptr;
715718
}
719+
720+
try {
721+
const auto chainstate_load_opts{WITH_LOCK(opts.m_mutex, return opts.m_chainstate_load_options)};
722+
723+
kernel::CacheSizes cache_sizes{DEFAULT_KERNEL_CACHE};
724+
auto [status, chainstate_err]{node::LoadChainstate(*chainman, cache_sizes, chainstate_load_opts)};
725+
if (status != node::ChainstateLoadStatus::SUCCESS) {
726+
LogError("Failed to load chain state from your data directory: %s", chainstate_err.original);
727+
return nullptr;
728+
}
729+
std::tie(status, chainstate_err) = node::VerifyLoadedChainstate(*chainman, chainstate_load_opts);
730+
if (status != node::ChainstateLoadStatus::SUCCESS) {
731+
LogError("Failed to verify loaded chain state from your datadir: %s", chainstate_err.original);
732+
return nullptr;
733+
}
734+
735+
for (Chainstate* chainstate : WITH_LOCK(chainman->GetMutex(), return chainman->GetAll())) {
736+
BlockValidationState state;
737+
if (!chainstate->ActivateBestChain(state, nullptr)) {
738+
LogError("Failed to connect best block: %s", state.ToString());
739+
return nullptr;
740+
}
741+
}
742+
} catch (const std::exception& e) {
743+
LogError("Failed to load chainstate: %s", e.what());
744+
return nullptr;
745+
}
746+
747+
return btck_ChainstateManager::create(std::move(chainman), opts.m_context);
716748
}
717749

718750
void btck_chainstate_manager_destroy(btck_ChainstateManager* chainman)

src/kernel/bitcoinkernel.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,8 @@ BITCOINKERNEL_API void btck_chainstate_manager_options_destroy(btck_ChainstateMa
755755

756756
/**
757757
* @brief Create a chainstate manager. This is the main object for many
758-
* validation tasks as well as for retrieving data from the chain. *
758+
* validation tasks as well as for retrieving data from the chain and
759+
* interacting with its chainstate and indexes.
759760
*
760761
* @param[in] chainstate_manager_options Non-null, created by @ref btck_chainstate_manager_options_create.
761762
* @return The allocated chainstate manager, or null on error.

0 commit comments

Comments
 (0)