From d52f3322bd6f4430f5108cc1d31d2838f49d006d Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 11:20:53 -0400 Subject: [PATCH 1/7] Declare multisig_view members in initialization order. --- include/bitcoin/database/types/multisig_view.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bitcoin/database/types/multisig_view.hpp b/include/bitcoin/database/types/multisig_view.hpp index 1de5c7fe0..f4d801fa3 100644 --- a/include/bitcoin/database/types/multisig_view.hpp +++ b/include/bitcoin/database/types/multisig_view.hpp @@ -34,9 +34,9 @@ struct BCD_API multisig_view void to_data(system::bytewriter& sink) const NOEXCEPT; private: - uint8_t pair_; const system::ec_compressed& point_; const system::ec_signature& signature_; + uint8_t pair_; }; using multisig_views = std::vector; From e036d6ebf42e47f53b970f5032b594657cfe42de Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 14:32:25 -0400 Subject: [PATCH 2/7] Add store pooling and current state tests. --- test/mocks/map_store.hpp | 10 +++++++ test/store/store.cpp | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/test/mocks/map_store.hpp b/test/mocks/map_store.hpp index 45a5d29e9..9649b9551 100644 --- a/test/mocks/map_store.hpp +++ b/test/mocks/map_store.hpp @@ -60,6 +60,16 @@ class map_store return restore([](auto, auto) {}); } + inline void set_current_(bool current) NOEXCEPT + { + return set_current(current); + } + + inline bool is_current_() const NOEXCEPT + { + return is_current(); + } + inline const settings& configuration() const NOEXCEPT { return configuration_; diff --git a/test/store/store.cpp b/test/store/store.cpp index b83f153f8..b53b57a07 100644 --- a/test/store/store.cpp +++ b/test/store/store.cpp @@ -192,4 +192,65 @@ BOOST_AUTO_TEST_CASE(store__get_transactor__always__share_locked) BOOST_REQUIRE(instance.transactor_mutex().try_lock_shared()); } +// set_pooling +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(store__set_pooling__created__pooling) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + BOOST_REQUIRE(!instance.is_pooling()); + instance.set_pooling(); + BOOST_REQUIRE(instance.is_pooling()); + BOOST_REQUIRE(!instance.close(test::events)); +} + +BOOST_AUTO_TEST_CASE(store__set_pooling__twice__remains_pooling) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + instance.set_pooling(); + instance.set_pooling(); + BOOST_REQUIRE(instance.is_pooling()); + BOOST_REQUIRE(!instance.close(test::events)); +} + +// set_current +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(store__set_current__created__not_current) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + BOOST_REQUIRE(!instance.is_current_()); + BOOST_REQUIRE(!instance.close(test::events)); +} + +BOOST_AUTO_TEST_CASE(store__set_current__changed__applied_to_heads) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + instance.set_current_(true); + instance.set_current_(false); + BOOST_REQUIRE(!instance.close(test::events)); +} + +BOOST_AUTO_TEST_CASE(store__set_current__unchanged__no_effect) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + instance.set_current_(false); + BOOST_REQUIRE(!instance.close(test::events)); +} + BOOST_AUTO_TEST_SUITE_END() From 6f360cda306af346b6a611bd6d368850492c8a36 Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 14:41:15 -0400 Subject: [PATCH 3/7] Add multi-transaction block fixture and consensus prevouts tests. --- test/mocks/blocks.cpp | 69 +++++++++++++++ test/mocks/blocks.hpp | 1 + test/query/consensus/consensus_prevouts.cpp | 97 +++++++++++++++++++++ 3 files changed, 167 insertions(+) diff --git a/test/mocks/blocks.cpp b/test/mocks/blocks.cpp index dc1c35d18..0f791d492 100644 --- a/test/mocks/blocks.cpp +++ b/test/mocks/blocks.cpp @@ -691,6 +691,75 @@ const block block_spend_genesis tx_spend_genesis } }; +// Coinbase and one spending tx, so to_spending_txs is non-empty. +const block block_coinbase_spend_1a +{ + header + { + 0x31323334, // version + block1a.hash(), // previous_block_hash + hash_digest{ 0x4a },// merkle_root + 0x41424344, // timestamp + 0x51525354, // bits + 0x61626364 // nonce + }, + transactions + { + transaction // coinbase + { + 0x01, + inputs + { + input + { + point{}, + script{}, + witness{}, + 0xffffffff + } + }, + outputs + { + output + { + 0x10, + script{ { { opcode::pick } } } + } + }, + 0x00 + }, + transaction // spends both block1a outputs + { + 0x02, + inputs + { + input + { + point{ block1a.transactions_ptr()->front()->hash(false), 0x00 }, + script{ { { opcode::pick } } }, + witness{}, + 0xffffffff + }, + input + { + point{ block1a.transactions_ptr()->front()->hash(false), 0x01 }, + script{ { { opcode::roll } } }, + witness{}, + 0xffffffff + } + }, + outputs + { + output + { + 0x20, + script{ { { opcode::pick } } } + } + }, + 0x00 + } + } +}; const block block_spend_internal_2b { header diff --git a/test/mocks/blocks.hpp b/test/mocks/blocks.hpp index e1e6aca2f..b462c9ed3 100644 --- a/test/mocks/blocks.hpp +++ b/test/mocks/blocks.hpp @@ -105,6 +105,7 @@ extern const system::chain::transaction tx2b; extern const system::chain::block block_spend_1a; extern const system::chain::transaction tx_spend_genesis; extern const system::chain::block block_spend_genesis; +extern const system::chain::block block_coinbase_spend_1a; extern const system::chain::block block_spend_internal_2b; extern const system::chain::block block_missing_prevout_2b; extern const system::chain::block block_valid_spend_internal_2b; diff --git a/test/query/consensus/consensus_prevouts.cpp b/test/query/consensus/consensus_prevouts.cpp index f0854c909..35af9ca34 100644 --- a/test/query/consensus/consensus_prevouts.cpp +++ b/test/query/consensus/consensus_prevouts.cpp @@ -22,4 +22,101 @@ BOOST_FIXTURE_TEST_SUITE(query_consensus_tests, test::directory_setup_fixture) +// set_prevouts +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_consensus__set_prevouts__coinbase_only__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE(query.set_prevouts(1, test::block1)); +} + +BOOST_AUTO_TEST_CASE(query_consensus__set_prevouts__spending_block__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1a, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(1)); + BOOST_REQUIRE(query.set(test::block_spend_1a, context{ 0, 2, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(2)); + BOOST_REQUIRE(query.set_prevouts(2, test::block_spend_1a)); +} + +BOOST_AUTO_TEST_CASE(query_consensus__set_prevouts__coinbase_and_spend__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1a, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(1)); + BOOST_REQUIRE(query.set(test::block_coinbase_spend_1a, context{ 0, 2, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(2)); + BOOST_REQUIRE(!query.to_spending_txs(2).empty()); + BOOST_REQUIRE(query.set_prevouts(2, test::block_coinbase_spend_1a)); +} + +// get_prevouts (via block_confirmable) +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_consensus__get_prevouts__cached__success) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1a, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(1)); + BOOST_REQUIRE(query.set(test::block_coinbase_spend_1a, context{ 0, 2, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(2)); + BOOST_REQUIRE(query.set_prevouts(2, test::block_coinbase_spend_1a)); + BOOST_REQUIRE_EQUAL(query.block_confirmable(2), error::success); +} + +BOOST_AUTO_TEST_CASE(query_consensus__get_prevouts__populated_metadata__success) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1a, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(1)); + BOOST_REQUIRE(query.set(test::block_coinbase_spend_1a, context{ 0, 2, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(2)); + BOOST_REQUIRE(query.populate_with_metadata(test::block_coinbase_spend_1a)); + BOOST_REQUIRE(query.set_prevouts(2, test::block_coinbase_spend_1a)); + BOOST_REQUIRE_EQUAL(query.block_confirmable(2), error::success); +} + +BOOST_AUTO_TEST_CASE(query_consensus__get_prevouts__not_cached__integrity_get_prevouts) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1a, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(1)); + BOOST_REQUIRE(query.set(test::block_coinbase_spend_1a, context{ 0, 2, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(2)); + BOOST_REQUIRE_EQUAL(query.block_confirmable(2), error::integrity_get_prevouts); +} + BOOST_AUTO_TEST_SUITE_END() From ad2985bafd2877183a1e74070a2a63c2289f7db7 Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 14:57:05 -0400 Subject: [PATCH 4/7] Add extent aggregate size and filter table tests. --- test/query/extent.cpp | 86 +++++++++++++++++++++++++++++++ test/query/filters.cpp | 114 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+) diff --git a/test/query/extent.cpp b/test/query/extent.cpp index d6a75c1c1..eb7cac27a 100644 --- a/test/query/extent.cpp +++ b/test/query/extent.cpp @@ -169,4 +169,90 @@ BOOST_AUTO_TEST_CASE(query_extent__filter_enabled__disabled__false) BOOST_REQUIRE(!query.filter_enabled()); } +// aggregate sizes +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_extent__archive_head_size__genesis__sum_of_tables) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + const auto expected = query.header_head_size() + query.output_head_size() + query.input_head_size() + query.ins_head_size() + query.outs_head_size() + query.txs_head_size() + query.tx_head_size(); + BOOST_REQUIRE_EQUAL(query.archive_head_size(), expected); +} + +BOOST_AUTO_TEST_CASE(query_extent__archive_body_size__genesis__sum_of_tables) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + const auto expected = query.header_body_size() + query.output_body_size() + query.input_body_size() + query.ins_body_size() + query.outs_body_size() + query.txs_body_size() + query.tx_body_size(); + BOOST_REQUIRE_EQUAL(query.archive_body_size(), expected); +} + +BOOST_AUTO_TEST_CASE(query_extent__archive_size__genesis__head_plus_body) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE_EQUAL(query.archive_size(), query.archive_head_size() + query.archive_body_size()); +} + +BOOST_AUTO_TEST_CASE(query_extent__store_head_size__genesis__archive_plus_indexes) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + const auto indexes = query.candidate_head_size() + query.confirmed_head_size() + query.strong_tx_head_size() + query.ecdsa_head_size() + query.schnorr_head_size() + query.silent_head_size() + query.duplicate_head_size() + query.prevalid_head_size() + query.prevout_head_size() + query.validated_bk_head_size() + query.validated_tx_head_size() + query.filter_bk_head_size() + query.filter_tx_head_size(); + BOOST_REQUIRE_EQUAL(query.store_head_size(), query.archive_head_size() + indexes); +} + +BOOST_AUTO_TEST_CASE(query_extent__store_body_size__genesis__archive_plus_indexes) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + const auto indexes = query.candidate_body_size() + query.confirmed_body_size() + query.strong_tx_body_size() + query.ecdsa_body_size() + query.schnorr_body_size() + query.silent_body_size() + query.duplicate_body_size() + query.prevalid_body_size() + query.prevout_body_size() + query.validated_bk_body_size() + query.validated_tx_body_size() + query.filter_bk_body_size() + query.filter_tx_body_size(); + BOOST_REQUIRE_EQUAL(query.store_body_size(), query.archive_body_size() + indexes); +} + +BOOST_AUTO_TEST_CASE(query_extent__store_size__genesis__head_plus_body) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE_EQUAL(query.store_size(), query.store_head_size() + query.store_body_size()); +} + +BOOST_AUTO_TEST_CASE(query_extent__store_size__archived_block__increases) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + const auto initial = query.store_body_size(); + BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); + BOOST_REQUIRE_GT(query.store_body_size(), initial); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/query/filters.cpp b/test/query/filters.cpp index f8d3d6c7e..0bc8e7eab 100644 --- a/test/query/filters.cpp +++ b/test/query/filters.cpp @@ -22,4 +22,118 @@ BOOST_FIXTURE_TEST_SUITE(query_filters_tests, test::directory_setup_fixture) + +// filter_tx +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_filters__is_filtered_body__genesis__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.filter_enabled()); + BOOST_REQUIRE(query.is_filtered_body(0)); +} + +BOOST_AUTO_TEST_CASE(query_filters__is_filtered_body__unarchived__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(!query.is_filtered_body(1)); +} + +BOOST_AUTO_TEST_CASE(query_filters__get_filter_body__unarchived__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + system::data_chunk out{}; + BOOST_REQUIRE(!query.get_filter_body(out, 1)); +} + +BOOST_AUTO_TEST_CASE(query_filters__set_filter_body__filter__round_trips) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); + const auto expected = system::base16_chunk("00010203"); + BOOST_REQUIRE(query.set_filter_body(1, expected)); + BOOST_REQUIRE(query.is_filtered_body(1)); + system::data_chunk out{}; + BOOST_REQUIRE(query.get_filter_body(out, 1)); + BOOST_REQUIRE_EQUAL(out, expected); +} + +// filter_bk +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_filters__is_filtered_head__genesis__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.is_filtered_head(0)); +} + +BOOST_AUTO_TEST_CASE(query_filters__is_filtered_head__unarchived__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(!query.is_filtered_head(1)); +} + +BOOST_AUTO_TEST_CASE(query_filters__get_filter_head__unarchived__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + system::hash_digest out{}; + BOOST_REQUIRE(!query.get_filter_head(out, 1)); +} + +BOOST_AUTO_TEST_CASE(query_filters__set_filter_head__head_and_hash__round_trips) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); + const auto head = system::base16_hash("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"); + const auto hash = system::base16_hash("2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40"); + BOOST_REQUIRE(query.set_filter_head(1, head, hash)); + BOOST_REQUIRE(query.is_filtered_head(1)); + system::hash_digest out{}; + BOOST_REQUIRE(query.get_filter_head(out, 1)); + BOOST_REQUIRE_EQUAL(out, head); + system::hash_digest out_hash{}; + BOOST_REQUIRE(query.get_filter_hash(out_hash, 1)); + BOOST_REQUIRE_EQUAL(out_hash, hash); +} + BOOST_AUTO_TEST_SUITE_END() From c1004bed6001aa5deacea4fc97229ead3e1c3dab Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 14:59:09 -0400 Subject: [PATCH 5/7] Add hashmap enumeration and fork work tests. --- test/query/consensus/consensus_work.cpp | 88 ++++++++++++++++++++++++ test/query/navigate/navigate_hashmap.cpp | 66 ++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/test/query/consensus/consensus_work.cpp b/test/query/consensus/consensus_work.cpp index f0854c909..bb2b7cae7 100644 --- a/test/query/consensus/consensus_work.cpp +++ b/test/query/consensus/consensus_work.cpp @@ -22,4 +22,92 @@ BOOST_FIXTURE_TEST_SUITE(query_consensus_tests, test::directory_setup_fixture) +// get_work +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_consensus__get_work__empty_states__zero) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + uint256_t work{}; + const header_states states{}; + BOOST_REQUIRE(query.get_work(work, states)); + BOOST_REQUIRE_EQUAL(work, 0u); +} + +BOOST_AUTO_TEST_CASE(query_consensus__get_work__genesis__proof_of_bits) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + uint32_t bits{}; + BOOST_REQUIRE(query.get_bits(bits, 0)); + const header_states states{ { 0, code{} } }; + uint256_t work{}; + BOOST_REQUIRE(query.get_work(work, states)); + BOOST_REQUIRE_EQUAL(work, system::chain::header::proof(bits)); +} + +BOOST_AUTO_TEST_CASE(query_consensus__get_work__terminal_link__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + uint256_t work{}; + const header_states states{ { header_link::terminal, code{} } }; + BOOST_REQUIRE(!query.get_work(work, states)); +} + +// get_branch +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_consensus__get_branch__candidate_hash__empty_branch) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + header_states branch{}; + BOOST_REQUIRE(query.get_branch(branch, test::genesis.hash())); + BOOST_REQUIRE(branch.empty()); +} + +BOOST_AUTO_TEST_CASE(query_consensus__get_branch__unknown_hash__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + header_states branch{}; + BOOST_REQUIRE(!query.get_branch(branch, test::block1.hash())); +} + +BOOST_AUTO_TEST_CASE(query_consensus__get_branch__uncandidate_header__branch_of_one) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); + header_states branch{}; + BOOST_REQUIRE(query.get_branch(branch, test::block1.hash())); + BOOST_REQUIRE_EQUAL(branch.size(), 1u); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/query/navigate/navigate_hashmap.cpp b/test/query/navigate/navigate_hashmap.cpp index 8f2185ebd..e102afe74 100644 --- a/test/query/navigate/navigate_hashmap.cpp +++ b/test/query/navigate/navigate_hashmap.cpp @@ -22,4 +22,70 @@ BOOST_FIXTURE_TEST_SUITE(query_navigate_tests, test::directory_setup_fixture) +// top_header +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_navigate__top_header__genesis_bucket__genesis_link) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + settings.header.buckets = 1; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE_EQUAL(query.top_header(0), 0u); +} + +BOOST_AUTO_TEST_CASE(query_navigate__top_header__empty_bucket__terminal) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + settings.header.buckets = 8; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.top_header(7).is_terminal()); +} + +// top_tx +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_navigate__top_tx__empty_bucket__terminal) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + settings.tx.buckets = 8; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.top_tx(7).is_terminal()); +} + +BOOST_AUTO_TEST_CASE(query_navigate__top_tx__genesis_bucket__genesis_tx) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + settings.tx.buckets = 1; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE_EQUAL(query.top_tx(0), 0u); +} + +// top_point +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_navigate__top_point__empty_bucket__terminal) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + settings.ins.buckets = 8; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.top_point(7).is_terminal()); +} + BOOST_AUTO_TEST_SUITE_END() From 5c04a19a0174c5a33a6a6bf6340530c164b819a6 Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 15:02:08 -0400 Subject: [PATCH 6/7] Add silent setter, store report and reload tests. --- test/query/batch/silent.cpp | 25 +++++++++++++++++++++ test/store/store_reload.cpp | 22 +++++++++++++++++++ test/store/store_report.cpp | 44 +++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/test/query/batch/silent.cpp b/test/query/batch/silent.cpp index d627a8900..97c555f28 100644 --- a/test/query/batch/silent.cpp +++ b/test/query/batch/silent.cpp @@ -22,4 +22,29 @@ BOOST_FIXTURE_TEST_SUITE(query_batch_silent_tests, test::directory_setup_fixture) +// set_silent +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(query_batch_silent__set_silent__coinbase_only__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set_silent(0, test::genesis)); +} + +BOOST_AUTO_TEST_CASE(query_batch_silent__set_silent__unarchived_block__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(!query.set_silent(1, test::block_coinbase_spend_1a)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/store/store_reload.cpp b/test/store/store_reload.cpp index a5f2382a3..daa8e4186 100644 --- a/test/store/store_reload.cpp +++ b/test/store/store_reload.cpp @@ -17,7 +17,29 @@ * along with this program. If not, see . */ #include "../test.hpp" +#include "../mocks/map_store.hpp" BOOST_FIXTURE_TEST_SUITE(store_tests, test::directory_setup_fixture) +// reload +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(store__reload__created__success) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + BOOST_REQUIRE(!instance.reload(test::events)); + BOOST_REQUIRE(!instance.close(test::events)); +} + +BOOST_AUTO_TEST_CASE(store__reload__unloaded__error) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(instance.reload(test::events)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/store/store_report.cpp b/test/store/store_report.cpp index a5f2382a3..d28eb02af 100644 --- a/test/store/store_report.cpp +++ b/test/store/store_report.cpp @@ -17,7 +17,51 @@ * along with this program. If not, see . */ #include "../test.hpp" +#include "../mocks/map_store.hpp" BOOST_FIXTURE_TEST_SUITE(store_tests, test::directory_setup_fixture) +// report +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(store__report__created__reports_all_tables_without_fault) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + size_t calls{}; + size_t faults{}; + instance.report([&](const code& ec, auto) NOEXCEPT { ++calls; faults += static_cast(static_cast(ec)); }); + BOOST_REQUIRE_NE(calls, 0u); + BOOST_REQUIRE_EQUAL(faults, 0u); + BOOST_REQUIRE(!instance.close(test::events)); +} + +// get_fault +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(store__get_fault__created__success) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + BOOST_REQUIRE(!instance.get_fault()); + BOOST_REQUIRE(!instance.close(test::events)); +} + +// get_space +// ---------------------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(store__get_space__created__zero) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + test::map_store instance{ configuration }; + BOOST_REQUIRE(!instance.create(test::events)); + BOOST_REQUIRE_EQUAL(instance.get_space(), 0u); + BOOST_REQUIRE(!instance.close(test::events)); +} + BOOST_AUTO_TEST_SUITE_END() From 9529098b86fb701c1db89e8656276677117d7c17 Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Tue, 22 Sep 2026 15:12:47 -0400 Subject: [PATCH 7/7] Style. --- test/mocks/blocks.cpp | 3 +-- test/query/filters.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/mocks/blocks.cpp b/test/mocks/blocks.cpp index 0f791d492..edba7d279 100644 --- a/test/mocks/blocks.cpp +++ b/test/mocks/blocks.cpp @@ -517,7 +517,6 @@ const block block1b } } }; - const block block1c { header @@ -691,9 +690,9 @@ const block block_spend_genesis tx_spend_genesis } }; -// Coinbase and one spending tx, so to_spending_txs is non-empty. const block block_coinbase_spend_1a { + // Coinbase and one spending tx, so to_spending_txs is non-empty. header { 0x31323334, // version diff --git a/test/query/filters.cpp b/test/query/filters.cpp index 0bc8e7eab..676999c87 100644 --- a/test/query/filters.cpp +++ b/test/query/filters.cpp @@ -22,7 +22,6 @@ BOOST_FIXTURE_TEST_SUITE(query_filters_tests, test::directory_setup_fixture) - // filter_tx // ----------------------------------------------------------------------------