diff --git a/include/bitcoin/database/impl/query/consensus/consensus_strong.ipp b/include/bitcoin/database/impl/query/consensus/consensus_strong.ipp index c78f9674..4545c3b6 100644 --- a/include/bitcoin/database/impl/query/consensus/consensus_strong.ipp +++ b/include/bitcoin/database/impl/query/consensus/consensus_strong.ipp @@ -72,9 +72,9 @@ height_link CLASS::find_strong_spender_height( size_t out{}; for (const auto& in: to_spenders(point)) if (const auto tx = to_input_tx(in); get_tx_height(out, tx)) - break; + return { system::possible_narrow_cast(out) }; - return { system::possible_narrow_cast(out) }; + return {}; } // find_strong (block) @@ -84,7 +84,7 @@ TEMPLATE header_link CLASS::find_strong(const tx_link& link) const NOEXCEPT { // Shortcuircuit hash-based search by testing self. - if (const auto fk = to_block(link); !link.is_terminal()) + if (const auto fk = to_block(link); !fk.is_terminal()) return fk; return find_strong(get_tx_key(link)); diff --git a/test/query/confirmed.cpp b/test/query/confirmed.cpp index 96a54282..9c9396d8 100644 --- a/test/query/confirmed.cpp +++ b/test/query/confirmed.cpp @@ -144,6 +144,89 @@ BOOST_AUTO_TEST_CASE(query_confirmed__is_confirmed_tx__confirm__expected) BOOST_REQUIRE(query.is_confirmed_tx(2)); } +BOOST_AUTO_TEST_CASE(query_confirmed__find_strong__unconfirmed_duplicate__expected) +{ + 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::tx4)); + const auto unconfirmed = query.to_tx(test::tx4.hash(false)); + + BOOST_REQUIRE(query.set(test::block_spend_1a, context{ 0, 2, 0 }, false, false)); + BOOST_REQUIRE(query.set_strong(2)); + + BOOST_REQUIRE_EQUAL(query.find_strong(unconfirmed), + query.to_header(test::block_spend_1a.hash())); +} + +BOOST_AUTO_TEST_CASE(query_confirmed__find_strong_spender_height__unspent__terminal) +{ + 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)); + + const system::chain::point point + { + test::block1a.transactions_ptr()->front()->hash(false), 0 + }; + + BOOST_REQUIRE(query.find_strong_spender_height(point).is_terminal()); +} + +BOOST_AUTO_TEST_CASE(query_confirmed__find_strong_spender_height__unconfirmed__terminal) +{ + 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::tx5)); + + const system::chain::point point + { + test::block1a.transactions_ptr()->front()->hash(false), 0 + }; + + BOOST_REQUIRE(query.find_strong_spender_height(point).is_terminal()); +} + +BOOST_AUTO_TEST_CASE(query_confirmed__find_strong_spender_height__confirmed__expected) +{ + 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)); + + const system::chain::point point + { + test::block1a.transactions_ptr()->front()->hash(false), 0 + }; + + const auto height = query.find_strong_spender_height(point); + BOOST_REQUIRE(!height.is_terminal()); + BOOST_REQUIRE_EQUAL(height.value, 2u); +} + BOOST_AUTO_TEST_CASE(query_confirmed__is_confirmed_input__genesis__true) { settings settings{};