diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp index 7a08b6c9008..23ae8128227 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 5486c823be3..49995960a17 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 f0af457d42a..15186bbdf39 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 diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp index 71325390457..38879f71bb7 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 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(context, chainman_opts)}; return chainman; } -BOOST_AUTO_TEST_CASE(btck_chainman_mainnet_tests) +void chainman_reindex_test(TestDirectory& test_directory) { - auto mainnet_test_directory{TestDirectory{"mainnet_test_bitcoin_kernel"}}; - auto notifications{std::make_shared()}; 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()}; + 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()}; + auto context{create_context(notifications, ChainType::MAINNET)}; + 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])};