diff --git a/include/bitcoin/database/error.hpp b/include/bitcoin/database/error.hpp index 3568c57d..7758eb22 100644 --- a/include/bitcoin/database/error.hpp +++ b/include/bitcoin/database/error.hpp @@ -87,10 +87,9 @@ enum error_t : uint8_t /// validation/confirmation tx_connected, - tx_preconnected, tx_disconnected, - block_confirmable, block_valid, + block_confirmable, block_unconfirmable, unassociated, unvalidated, diff --git a/include/bitcoin/database/impl/query/confirm.ipp b/include/bitcoin/database/impl/query/confirm.ipp index 7c43c902..44245670 100644 --- a/include/bitcoin/database/impl/query/confirm.ipp +++ b/include/bitcoin/database/impl/query/confirm.ipp @@ -283,14 +283,18 @@ error::error_t CLASS::spent_prevout(const point_link& link, index index, // The upside is half the prevout size (read/write/page) and store increase. // Iterate points by point hash (of output tx) because may be conflicts. - auto point = store_.point.it(get_point_key(link)); + // Search key must be passed as an l-value as it is held by reference. + const auto point_sk = get_point_key(link); + auto point = store_.point.it(point_sk); if (!point) return error::integrity; do { // Iterate all spends of the point to find double spends. - auto it = store_.spend.it(table::spend::compose(point.self(), index)); + // Search key must be passed as an l-value as it is held by reference. + const auto spend_sk = table::spend::compose(point.self(), index); + auto it = store_.spend.it(spend_sk); if (!it) return error::success; @@ -494,12 +498,14 @@ spend_sets CLASS::to_spend_sets(const header_link& link) const NOEXCEPT // Coinbase tx does not spend so is not retrieved. const auto txs = to_spending_transactions(link); + // Empty here is normal. if (txs.empty()) return {}; spend_sets sets{ txs.size() }; const auto to_set = [this](const auto& tx) NOEXCEPT { + // Empty here implies integrity fault. return to_spend_set(tx); }; @@ -540,6 +546,7 @@ code CLASS::block_confirmable(const header_link& link) const NOEXCEPT if ((ec = unspent_duplicates(link, ctx))) return ec; + // Empty here could imply integrity fault. const auto sets = to_spend_sets(link); if (sets.empty()) return ec; @@ -753,6 +760,8 @@ bool CLASS::initialize(const block& genesis) NOEXCEPT BC_ASSERT(!is_initialized()); BC_ASSERT(is_one(genesis.transactions_ptr()->size())); + // TODO: add genesis block neutrino head and body when neutrino is enabled. + // ======================================================================== const auto scope = store_.get_transactor(); diff --git a/include/bitcoin/database/impl/query/validate.ipp b/include/bitcoin/database/impl/query/validate.ipp index 97ac3bb6..0ee877df 100644 --- a/include/bitcoin/database/impl/query/validate.ipp +++ b/include/bitcoin/database/impl/query/validate.ipp @@ -36,16 +36,16 @@ inline code CLASS::to_block_code( { switch (value) { - // Block satisfies validation rules (prevouts unverified). + // Transitional: Satisfies validation rules (prevouts unverified). case schema::block_state::valid: return error::block_valid; - // Final: Block satisfies confirmation rules (prevouts). + // Final: Satisfies confirmation rules (prevouts confirmable). case schema::block_state::confirmable: return error::block_confirmable; - // Final: Block does not satisfy validation/confirmation rules. + // Final: Does not satisfy either validation or confirmation rules. case schema::block_state::unconfirmable: return error::block_unconfirmable; - // Block has no recorded state, may be under checkpoint or milestone. + // Fault: Has no state, should not happen when read from store. default: return error::unknown_state; } @@ -61,16 +61,13 @@ inline code CLASS::to_tx_code( // All states below are relevant only to the associated validation context. switch (value) { - // Tx is valid in the case where standard prevouts are matched. - case schema::tx_state::preconnected: - return error::tx_preconnected; - // Final: Tx is valid (passed check, accept, and connect). + // Final: Is valid (passed check, accept, and connect). case schema::tx_state::connected: return error::tx_connected; - // Final: Tx is not valid (failed check, accept, or connect). + // Final: Is not valid (failed check, accept, or connect). case schema::tx_state::disconnected: return error::tx_disconnected; - // Tx has no recorded state, may be under checkpoint or milestone. + // Fault: Has no state, should not happen when read from store. default: return error::unknown_state; } @@ -307,25 +304,6 @@ bool CLASS::set_block_unconfirmable(const header_link& link) NOEXCEPT // ======================================================================== } -TEMPLATE -bool CLASS::set_tx_preconnected(const tx_link& link, - const context& ctx) NOEXCEPT -{ - // ======================================================================== - const auto scope = store_.get_transactor(); - - // Clean single allocation failure (e.g. disk full). - return store_.validated_tx.put(link, table::validated_tx::slab - { - {}, - ctx, - schema::tx_state::preconnected, - 0, // fee - 0 // sigops - }); - // ======================================================================== -} - TEMPLATE bool CLASS::set_tx_disconnected(const tx_link& link, const context& ctx) NOEXCEPT @@ -367,40 +345,40 @@ bool CLASS::set_tx_connected(const tx_link& link, const context& ctx, // ======================================================================== } -TEMPLATE -bool CLASS::set_txs_connected(const header_link& link) NOEXCEPT -{ - context ctx{}; - if (!get_context(ctx, link)) - return false; - - const auto txs = to_transactions(link); - if (txs.empty()) - return false; - - // FOR PERFORMANCE EVALUATION ONLY. - constexpr uint64_t fee = 99; - constexpr size_t sigops = 42; - using sigs = linkage; - - // ======================================================================== - const auto scope = store_.get_transactor(); - - // Clean single allocation failure (e.g. disk full). - return std_all_of(bc::seq, txs.begin(), txs.end(), - [&](const tx_link& fk) NOEXCEPT - { - return store_.validated_tx.put(fk, table::validated_tx::slab - { - {}, - ctx, - schema::tx_state::connected, - fee, - system::possible_narrow_cast(sigops) - }); - }); - // ======================================================================== -} +////TEMPLATE +////bool CLASS::set_txs_connected(const header_link& link) NOEXCEPT +////{ +//// context ctx{}; +//// if (!get_context(ctx, link)) +//// return false; +//// +//// const auto txs = to_transactions(link); +//// if (txs.empty()) +//// return false; +//// +//// // FOR PERFORMANCE EVALUATION ONLY. +//// constexpr uint64_t fee = 99; +//// constexpr size_t sigops = 42; +//// using sigs = linkage; +//// +//// // ======================================================================== +//// const auto scope = store_.get_transactor(); +//// +//// // Clean single allocation failure (e.g. disk full). +//// return std_all_of(bc::seq, txs.begin(), txs.end(), +//// [&](const tx_link& fk) NOEXCEPT +//// { +//// return store_.validated_tx.put(fk, table::validated_tx::slab +//// { +//// {}, +//// ctx, +//// schema::tx_state::connected, +//// fee, +//// system::possible_narrow_cast(sigops) +//// }); +//// }); +//// // ======================================================================== +////} } // namespace database } // namespace libbitcoin diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index bf7e5ed6..5c4bdff7 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -478,10 +478,6 @@ class query bool set_block_valid(const header_link& link, uint64_t fees) NOEXCEPT; bool set_block_unconfirmable(const header_link& link) NOEXCEPT; bool set_block_confirmable(const header_link& link) NOEXCEPT; - - // set_txs_connected is FOR PERFORMANCE EVALUATION ONLY. - bool set_txs_connected(const header_link& link) NOEXCEPT; - bool set_tx_preconnected(const tx_link& link, const context& ctx) NOEXCEPT; bool set_tx_disconnected(const tx_link& link, const context& ctx) NOEXCEPT; bool set_tx_connected(const tx_link& link, const context& ctx, uint64_t fee, size_t sigops) NOEXCEPT; @@ -547,13 +543,14 @@ class query bool set_filter_head(const header_link& link, const hash_digest& head) NOEXCEPT; +// TODO: protected + spend_set to_spend_set(const tx_link& link) const NOEXCEPT; + spend_sets to_spend_sets(const header_link& link) const NOEXCEPT; + protected: /// Translate. /// ----------------------------------------------------------------------- - spend_set to_spend_set(const tx_link& link) const NOEXCEPT; - spend_sets to_spend_sets(const header_link& link) const NOEXCEPT; - uint32_t to_spend_index(const tx_link& parent_fk, const spend_link& input_fk) const NOEXCEPT; uint32_t to_output_index(const tx_link& parent_fk, diff --git a/include/bitcoin/database/tables/schema.hpp b/include/bitcoin/database/tables/schema.hpp index 08be2035..4ed738c2 100644 --- a/include/bitcoin/database/tables/schema.hpp +++ b/include/bitcoin/database/tables/schema.hpp @@ -58,7 +58,6 @@ namespace schema constexpr auto candidate = "candidate"; constexpr auto confirmed = "confirmed"; constexpr auto strong_tx = "strong_tx"; - ////constexpr auto spent_out = "spent_out"; } namespace caches @@ -89,16 +88,15 @@ namespace schema enum block_state : uint8_t { - confirmable = 0, // final - valid = 1, // transitional - unconfirmable = 2 // final + confirmable = 0, // final + valid = 1, // transitional + unconfirmable = 2 // final }; enum tx_state : uint8_t { - connected = 0, // final - preconnected = 1, // transitional - disconnected = 2 // final + connected = 0, // final + disconnected = 1 // final }; /// Values. diff --git a/src/error.cpp b/src/error.cpp index 190e6a63..047dc161 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -79,10 +79,9 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) // states { tx_connected, "transaction connected" }, - { tx_preconnected, "transaction preconnected" }, { tx_disconnected, "transaction disconnected" }, - { block_confirmable, "block confirmable" }, { block_valid, "block valid" }, + { block_confirmable, "block confirmable" }, { block_unconfirmable, "block unconfirmable" }, { unassociated, "unassociated" }, { unvalidated, "unvalidated" }, diff --git a/test/error.cpp b/test/error.cpp index 9b9a81e2..dc7b18b1 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -365,15 +365,6 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_connected__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "transaction connected"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_preconnected__true_exected_message) -{ - constexpr auto value = error::tx_preconnected; - const auto ec = code(value); - BOOST_REQUIRE(ec); - BOOST_REQUIRE(ec == value); - BOOST_REQUIRE_EQUAL(ec.message(), "transaction preconnected"); -} - BOOST_AUTO_TEST_CASE(error_t__code__tx_disconnected__true_exected_message) { constexpr auto value = error::tx_disconnected; @@ -383,22 +374,22 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_disconnected__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "transaction disconnected"); } -BOOST_AUTO_TEST_CASE(error_t__code__block_confirmable__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__block_valid__true_exected_message) { - constexpr auto value = error::block_confirmable; + constexpr auto value = error::block_valid; const auto ec = code(value); BOOST_REQUIRE(ec); BOOST_REQUIRE(ec == value); - BOOST_REQUIRE_EQUAL(ec.message(), "block confirmable"); + BOOST_REQUIRE_EQUAL(ec.message(), "block valid"); } -BOOST_AUTO_TEST_CASE(error_t__code__block_valid__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__block_confirmable__true_exected_message) { - constexpr auto value = error::block_valid; + constexpr auto value = error::block_confirmable; const auto ec = code(value); BOOST_REQUIRE(ec); BOOST_REQUIRE(ec == value); - BOOST_REQUIRE_EQUAL(ec.message(), "block valid"); + BOOST_REQUIRE_EQUAL(ec.message(), "block confirmable"); } BOOST_AUTO_TEST_CASE(error_t__code__block_unconfirmable__true_exected_message) diff --git a/test/query/validate.cpp b/test/query/validate.cpp index 086fb837..e927bc2a 100644 --- a/test/query/validate.cpp +++ b/test/query/validate.cpp @@ -349,28 +349,6 @@ BOOST_AUTO_TEST_CASE(query_validate__get_tx_state__connected_in_context__tx_conn BOOST_REQUIRE_EQUAL(sigops, expected_sigops); } -BOOST_AUTO_TEST_CASE(query_validate__get_tx_state__connected_in_context__tx_preconnected) -{ - 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{}, false, false)); - BOOST_REQUIRE(query.set(test::block2, context{}, false, false)); - BOOST_REQUIRE(query.set(test::block3, context{}, false, false)); - - uint64_t fee{}; - size_t sigops{}; - constexpr context ctx{ 7, 8, 9 }; - BOOST_REQUIRE(query.set_tx_preconnected(3, ctx)); - BOOST_REQUIRE_EQUAL(query.get_tx_state(3, ctx), error::tx_preconnected); - BOOST_REQUIRE_EQUAL(query.get_tx_state(fee, sigops, 3, ctx), error::tx_preconnected); - BOOST_REQUIRE_EQUAL(fee, 0u); - BOOST_REQUIRE_EQUAL(sigops, 0u); -} - BOOST_AUTO_TEST_CASE(query_validate__get_tx_state__connected_in_context__tx_disconnected) { settings settings{};