diff --git a/include/bitcoin/database/impl/query/confirm.ipp b/include/bitcoin/database/impl/query/confirm.ipp index 89a13848..598dfc53 100644 --- a/include/bitcoin/database/impl/query/confirm.ipp +++ b/include/bitcoin/database/impl/query/confirm.ipp @@ -130,7 +130,7 @@ bool CLASS::is_spent(const spend_link& link) const NOEXCEPT // unused TEMPLATE -bool CLASS::is_strong(const spend_link& link) const NOEXCEPT +bool CLASS::is_strong_spend(const spend_link& link) const NOEXCEPT { return !to_block(to_spend_tx(link)).is_terminal(); } @@ -284,6 +284,7 @@ inline error::error_t CLASS::unspendable_prevout(const point_link& link, return error::success; } + TEMPLATE inline error::error_t CLASS::unspent_duplicates(const tx_link& link, const context& ctx) const NOEXCEPT @@ -291,6 +292,7 @@ inline error::error_t CLASS::unspent_duplicates(const tx_link& link, if (!ctx.is_enabled(system::chain::flags::bip30_rule)) return error::success; + // This will be empty if current block is not set_strong. const auto coinbases = to_strongs(get_tx_key(link)); if (coinbases.empty()) return error::integrity; @@ -319,7 +321,7 @@ code CLASS::block_confirmable(const header_link& link) const NOEXCEPT if (txs.empty()) return error::success; - code ec{}; + code ec{}; if ((ec = unspent_duplicates(txs.front(), ctx))) return ec; @@ -363,6 +365,12 @@ bool CLASS::set_strong(const header_link& link, const tx_links& txs, }); } +TEMPLATE +bool CLASS::is_strong(const header_link& link) const NOEXCEPT +{ + return !to_block(to_coinbase(link)).is_terminal(); +} + TEMPLATE bool CLASS::set_strong(const header_link& link) NOEXCEPT { diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index 18d98021..040ff264 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -416,7 +416,8 @@ class query /// These are not used in confirmation. /// These rely on strong (use only for confirmation process). bool is_spent(const spend_link& link) const NOEXCEPT; - bool is_strong(const spend_link& link) const NOEXCEPT; + bool is_strong(const header_link& link) const NOEXCEPT; + bool is_strong_spend(const spend_link& link) const NOEXCEPT; bool is_mature(const spend_link& link, size_t height) const NOEXCEPT; bool is_locked(const spend_link& link, uint32_t sequence, const context& ctx) const NOEXCEPT; diff --git a/test/query/confirm.cpp b/test/query/confirm.cpp index 5719755a..b32a2e07 100644 --- a/test/query/confirm.cpp +++ b/test/query/confirm.cpp @@ -238,6 +238,32 @@ BOOST_AUTO_TEST_CASE(query_confirm__is_spent_output__strong_confirmed__true) BOOST_REQUIRE(query.is_spent_output(query.to_output(1, 1))); // block1a } +BOOST_AUTO_TEST_CASE(query_confirm__is_strong_spend__strong__true) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.is_strong_spend(query.to_spend(0, 0))); +} + +BOOST_AUTO_TEST_CASE(query_confirm__is_strong_spend__weak__false) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, context{})); + BOOST_REQUIRE(!query.is_strong_spend(query.to_spend(1, 0))); + BOOST_REQUIRE(query.set_strong(1)); + BOOST_REQUIRE(query.is_strong_spend(query.to_spend(1, 0))); +} + +// The coinbase tx is strong. BOOST_AUTO_TEST_CASE(query_confirm__is_strong__strong__true) { settings settings{}; @@ -246,7 +272,7 @@ BOOST_AUTO_TEST_CASE(query_confirm__is_strong__strong__true) test::query_accessor query{ store }; BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); BOOST_REQUIRE(query.initialize(test::genesis)); - BOOST_REQUIRE(query.is_strong(query.to_spend(0, 0))); + BOOST_REQUIRE(query.is_strong(0)); } BOOST_AUTO_TEST_CASE(query_confirm__is_strong__weak__false) @@ -258,9 +284,9 @@ BOOST_AUTO_TEST_CASE(query_confirm__is_strong__weak__false) BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); BOOST_REQUIRE(query.initialize(test::genesis)); BOOST_REQUIRE(query.set(test::block1, context{})); - BOOST_REQUIRE(!query.is_strong(query.to_spend(1, 0))); + BOOST_REQUIRE(!query.is_strong(1)); BOOST_REQUIRE(query.set_strong(1)); - BOOST_REQUIRE(query.is_strong(query.to_spend(1, 0))); + BOOST_REQUIRE(query.is_strong(1)); } BOOST_AUTO_TEST_CASE(query_confirm__is_spent__unspent__false) diff --git a/test/query/translate.cpp b/test/query/translate.cpp index ba023d78..5c129629 100644 --- a/test/query/translate.cpp +++ b/test/query/translate.cpp @@ -140,6 +140,21 @@ BOOST_AUTO_TEST_CASE(query_translate__to_header__always__expected) BOOST_REQUIRE_EQUAL(query.to_header(test::block1.hash()), 1u); } +BOOST_AUTO_TEST_CASE(query_translate__to_coinbase__always__expected) +{ + settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); + BOOST_REQUIRE_EQUAL(query.to_header(test::genesis.hash()), header_link::terminal); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE_EQUAL(query.to_coinbase(0), 0u); + BOOST_REQUIRE(query.to_coinbase(1).is_terminal()); + BOOST_REQUIRE(query.set(test::block1, test::context)); + BOOST_REQUIRE_EQUAL(query.to_coinbase(1), 1u); +} + // to_point BOOST_AUTO_TEST_CASE(query_translate__to_point__null_points__empty_points_table)