kernel: Add options for reindexing in C header

Adds options for wiping the chainstate and block tree indexes to the
chainstate load options. In combination and once the
`*_import_blocks(...)` function is added in a later commit, this
triggers a reindex. For now, it just wipes the existing data.
This commit is contained in:
TheCharlatan 2024-06-17 22:50:47 +02:00
parent 42c106df05
commit 57a2b40476
No known key found for this signature in database
GPG Key ID: 9B79B45691DB4173
4 changed files with 82 additions and 4 deletions

View File

@ -702,6 +702,19 @@ void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* opti
delete options;
}
int btck_chainstate_manager_options_set_wipe_dbs(btck_ChainstateManagerOptions* chainman_opts, int wipe_block_tree_db, int wipe_chainstate_db)
{
if (wipe_block_tree_db == 1 && wipe_chainstate_db != 1) {
LogError("Wiping the block tree db without also wiping the chainstate db is currently unsupported.");
return -1;
}
auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
LOCK(opts.m_mutex);
opts.m_blockman_options.block_tree_db_params.wipe_data = wipe_block_tree_db == 1;
opts.m_chainstate_load_options.wipe_chainstate_db = wipe_chainstate_db == 1;
return 0;
}
btck_ChainstateManager* btck_chainstate_manager_create(
const btck_ChainstateManagerOptions* chainman_opts)
{

View File

@ -731,6 +731,19 @@ BITCOINKERNEL_API void btck_chainstate_manager_options_set_worker_threads_num(
btck_ChainstateManagerOptions* chainstate_manager_options,
int worker_threads) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Sets wipe db in the options.
*
* @param[in] chainstate_manager_options Non-null, created by @ref btck_chainstate_manager_options_create.
* @param[in] wipe_block_tree_db Set wipe block tree db. Should only be 1 if wipe_chainstate_db is 1 too.
* @param[in] wipe_chainstate_db Set wipe chainstate db.
* @return 0 if the set was successful, non-zero if the set failed.
*/
BITCOINKERNEL_API int btck_chainstate_manager_options_set_wipe_dbs(
btck_ChainstateManagerOptions* chainstate_manager_options,
int wipe_block_tree_db,
int wipe_chainstate_db) BITCOINKERNEL_ARG_NONNULL(1);
/**
* Destroy the chainstate manager options.
*/

View File

@ -673,6 +673,11 @@ public:
btck_chainstate_manager_options_set_worker_threads_num(get(), worker_threads);
}
bool SetWipeDbs(bool wipe_block_tree, bool wipe_chainstate)
{
return btck_chainstate_manager_options_set_wipe_dbs(get(), wipe_block_tree, wipe_chainstate) == 0;
}
friend class ChainMan;
};

View File

@ -529,18 +529,34 @@ BOOST_AUTO_TEST_CASE(btck_chainman_tests)
ChainstateManagerOptions chainman_opts{context, test_directory.m_directory.string(), (test_directory.m_directory / "blocks").string()};
chainman_opts.SetWorkerThreads(4);
BOOST_CHECK(!chainman_opts.SetWipeDbs(/*wipe_block_tree=*/true, /*wipe_chainstate=*/false));
BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/true, /*wipe_chainstate=*/true));
BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/true));
BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/false));
ChainMan chainman{context, chainman_opts};
}
std::unique_ptr<ChainMan> create_chainman(TestDirectory& test_directory,
bool reindex,
bool wipe_chainstate,
Context& context)
{
auto mainnet_test_directory{TestDirectory{"mainnet_test_bitcoin_kernel"}};
ChainstateManagerOptions chainman_opts{context, test_directory.m_directory.string(), (test_directory.m_directory / "blocks").string()};
if (reindex) {
chainman_opts.SetWipeDbs(/*wipe_block_tree=*/reindex, /*wipe_chainstate=*/reindex);
}
if (wipe_chainstate) {
chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/wipe_chainstate);
}
auto chainman{std::make_unique<ChainMan>(context, chainman_opts)};
return chainman;
}
BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests)
void chainman_reindex_test(TestDirectory& test_directory)
{
btck_LoggingOptions logging_options = {
.log_timestamps = true,
@ -555,7 +571,21 @@ BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests)
auto notifications{std::make_shared<TestKernelNotifications>()};
auto context{create_context(notifications, ChainType::MAINNET)};
auto chainman{create_chainman(mainnet_test_directory, context)};
auto chainman{create_chainman(test_directory, true, false, context)};
}
void chainman_reindex_chainstate_test(TestDirectory& test_directory)
{
auto notifications{std::make_shared<TestKernelNotifications>()};
auto context{create_context(notifications, ChainType::MAINNET)};
auto chainman{create_chainman(test_directory, false, true, context)};
}
void chainman_mainnet_validation_test(TestDirectory& test_directory)
{
auto notifications{std::make_shared<TestKernelNotifications>()};
auto context{create_context(notifications, ChainType::MAINNET)};
auto chainman{create_chainman(test_directory, false, false, context)};
{
// Process an invalid block
@ -591,6 +621,23 @@ BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests)
BOOST_CHECK(!new_block);
}
BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests)
{
btck_LoggingOptions logging_options = {
.log_timestamps = true,
.log_time_micros = true,
.log_threadnames = false,
.log_sourcelocations = false,
.always_print_category_levels = true,
};
Logger logger{std::make_unique<TestLog>(TestLog{}), logging_options};
auto test_directory{TestDirectory{"mainnet_test_bitcoin_kernel"}};
chainman_mainnet_validation_test(test_directory);
chainman_reindex_test(test_directory);
chainman_reindex_chainstate_test(test_directory);
}
BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
{
auto test_directory{TestDirectory{"regtest_test_bitcoin_kernel"}};
@ -604,7 +651,7 @@ BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
const size_t mid{REGTEST_BLOCK_DATA.size() / 2};
{
auto chainman{create_chainman(test_directory, context)};
auto chainman{create_chainman(test_directory, false, false, context)};
for (size_t i{0}; i < mid; i++) {
Block block{as_bytes(REGTEST_BLOCK_DATA[i])};
bool new_block{false};
@ -613,7 +660,7 @@ BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
}
}
auto chainman{create_chainman(test_directory, context)};
auto chainman{create_chainman(test_directory, false, false, context)};
for (size_t i{mid}; i < REGTEST_BLOCK_DATA.size(); i++) {
Block block{as_bytes(REGTEST_BLOCK_DATA[i])};