kernel: Add options for reindexing in C header
What changed, and why it matters
This commit adds a new configuration option to the Bitcoin Core kernel library that lets a caller choose to delete (wipe) the block database, the chainstate database, or both when starting up. It is intended to support a future reindex feature. The change is purely additive: it exposes existing internal wipe flags through the public C API and adds tests. There is no bug fix, no reported vulnerability, and no evidence this introduces a security issue on its own.
No security action required. Treat as normal feature/API expansion. Reviewers may want to ensure the new public API documents the destructive nature of the wipe flags and that future consumers cannot accidentally trigger data loss through default option values.
Security signals we found
No security-relevant bug is fixed or introduced in the diff.
New API surface adds a destructive operation (database wipe), but it is opt-in and gated by caller-supplied options.
The unsupported wipe combination is explicitly rejected with an error log and non-zero return.
No input from untrusted sources is processed; the flags are set by the library consumer at initialization.
Evidence from the diff
The patch introduces btck_chainstate_manager_options_set_wipe_dbs() in the libbitcoinkernel C API, mapping two integer flags to the existing block_tree_db_params.wipe_data and chainstate_load_options.wipe_chainstate_db fields. It also adds a C++ wrapper SetWipeDbs() and unit tests covering the four combinations of flags. The function rejects the unsupported combination of wiping the block tree DB without wiping the chainstate DB. The commit message frames this as groundwork for a later reindex/import-blocks feature.
Changed components
src/kernel/bitcoinkernel.cppsrc/kernel/bitcoinkernel.hsrc/kernel/bitcoinkernel_wrapper.hsrc/test/kernel/test_kernel.cppInspect captured patch +70 / −5
diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp
index 7a08b6c9..23ae8128 100644
--- a/src/kernel/bitcoinkernel.cpp
+++ b/src/kernel/bitcoinkernel.cpp
@@ -706,6 +706,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)
{
diff --git a/src/kernel/bitcoinkernel.h b/src/kernel/bitcoinkernel.h
index 5486c823..49995960 100644
--- a/src/kernel/bitcoinkernel.h
+++ b/src/kernel/bitcoinkernel.h
@@ -746,6 +746,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 BITCOINKERNEL_WARN_UNUSED_RESULT 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.
*/
diff --git a/src/kernel/bitcoinkernel_wrapper.h b/src/kernel/bitcoinkernel_wrapper.h
index f0af457d..15186bbd 100644
--- a/src/kernel/bitcoinkernel_wrapper.h
+++ b/src/kernel/bitcoinkernel_wrapper.h
@@ -665,6 +665,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;
+ }
};
class ChainMan : UniqueHandle<btck_ChainstateManager, btck_chainstate_manager_destroy>
diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp
index 71325390..38879f71 100644
--- a/src/test/kernel/test_kernel.cpp
+++ b/src/test/kernel/test_kernel.cpp
@@ -514,24 +514,50 @@ 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)
{
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)
+{
+ auto notifications{std::make_shared<TestKernelNotifications>()};
+ auto context{create_context(notifications, ChainType::MAINNET)};
+ auto chainman{create_chainman(test_directory, true, false, context)};
+}
+
+void chainman_reindex_chainstate_test(TestDirectory& test_directory)
{
- auto mainnet_test_directory{TestDirectory{"mainnet_test_bitcoin_kernel"}};
+ 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(mainnet_test_directory, context)};
+ auto chainman{create_chainman(test_directory, false, false, context)};
{
// Process an invalid block
@@ -567,6 +593,14 @@ BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests)
BOOST_CHECK(!new_block);
}
+BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests)
+{
+ 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"}};
@@ -580,7 +614,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{hex_string_to_byte_vec(REGTEST_BLOCK_DATA[i])};
bool new_block{false};
@@ -589,7 +623,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{hex_string_to_byte_vec(REGTEST_BLOCK_DATA[i])};
Why this scored 18/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.