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.
This commit is contained in:
TheCharlatan 2024-05-29 13:28:05 +02:00
parent 783db175aa
commit 6b1ee82417
No known key found for this signature in database
GPG Key ID: 9B79B45691DB4173
2 changed files with 39 additions and 6 deletions

View File

@ -7,6 +7,7 @@
#include <kernel/bitcoinkernel.h>
#include <consensus/amount.h>
#include <consensus/validation.h>
#include <kernel/caches.h>
#include <kernel/chainparams.h>
#include <kernel/checks.h>
@ -16,6 +17,7 @@
#include <kernel/warning.h>
#include <logging.h>
#include <node/blockstorage.h>
#include <node/chainstate.h>
#include <primitives/transaction.h>
#include <script/interpreter.h>
#include <script/script.h>
@ -38,6 +40,7 @@
#include <memory>
#include <span>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
@ -372,6 +375,7 @@ struct ChainstateManagerOptions {
ChainstateManager::Options m_chainman_options GUARDED_BY(m_mutex);
node::BlockManager::Options m_blockman_options GUARDED_BY(m_mutex);
std::shared_ptr<const Context> m_context;
node::ChainstateLoadOptions m_chainstate_load_options GUARDED_BY(m_mutex);
ChainstateManagerOptions(const std::shared_ptr<const Context>& context, const fs::path& data_dir, const fs::path& blocks_dir)
: m_chainman_options{ChainstateManager::Options{
@ -386,7 +390,7 @@ struct ChainstateManagerOptions {
.path = data_dir / "blocks" / "index",
.cache_bytes = kernel::CacheSizes{DEFAULT_KERNEL_CACHE}.block_tree_db,
}}},
m_context{context}
m_context{context}, m_chainstate_load_options{node::ChainstateLoadOptions{}}
{
}
};
@ -699,16 +703,44 @@ void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* opti
btck_ChainstateManager* btck_chainstate_manager_create(
const btck_ChainstateManagerOptions* chainman_opts)
{
auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
std::unique_ptr<ChainstateManager> chainman;
try {
auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
LOCK(opts.m_mutex);
auto& context{opts.m_context};
auto chainman{std::make_unique<ChainstateManager>(*context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options)};
return btck_ChainstateManager::create(std::move(chainman), context);
chainman = std::make_unique<ChainstateManager>(*opts.m_context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options);
} catch (const std::exception& e) {
LogError("Failed to create chainstate manager: %s", e.what());
return nullptr;
}
try {
const auto chainstate_load_opts{WITH_LOCK(opts.m_mutex, return opts.m_chainstate_load_options)};
kernel::CacheSizes cache_sizes{DEFAULT_KERNEL_CACHE};
auto [status, chainstate_err]{node::LoadChainstate(*chainman, cache_sizes, chainstate_load_opts)};
if (status != node::ChainstateLoadStatus::SUCCESS) {
LogError("Failed to load chain state from your data directory: %s", chainstate_err.original);
return nullptr;
}
std::tie(status, chainstate_err) = node::VerifyLoadedChainstate(*chainman, chainstate_load_opts);
if (status != node::ChainstateLoadStatus::SUCCESS) {
LogError("Failed to verify loaded chain state from your datadir: %s", chainstate_err.original);
return nullptr;
}
for (Chainstate* chainstate : WITH_LOCK(chainman->GetMutex(), return chainman->GetAll())) {
BlockValidationState state;
if (!chainstate->ActivateBestChain(state, nullptr)) {
LogError("Failed to connect best block: %s", state.ToString());
return nullptr;
}
}
} catch (const std::exception& e) {
LogError("Failed to load chainstate: %s", e.what());
return nullptr;
}
return btck_ChainstateManager::create(std::move(chainman), opts.m_context);
}
void btck_chainstate_manager_destroy(btck_ChainstateManager* chainman)

View File

@ -740,7 +740,8 @@ BITCOINKERNEL_API void btck_chainstate_manager_options_destroy(btck_ChainstateMa
/**
* @brief Create a chainstate manager. This is the main object for many
* validation tasks as well as for retrieving data from the chain. *
* validation tasks as well as for retrieving data from the chain and
* interacting with its chainstate and indexes.
*
* @param[in] chainstate_manager_options Non-null, created by @ref btck_chainstate_manager_options_create.
* @return The allocated chainstate manager, or null on error.