diff --git a/builds/gnu/Makefile.am b/builds/gnu/Makefile.am index 026a50572..7d4081cdd 100644 --- a/builds/gnu/Makefile.am +++ b/builds/gnu/Makefile.am @@ -272,7 +272,6 @@ include_bitcoin_database_tables_archives_HEADERS = \ ${srcdir}/../../include/bitcoin/database/tables/archives/ins.hpp \ ${srcdir}/../../include/bitcoin/database/tables/archives/output.hpp \ ${srcdir}/../../include/bitcoin/database/tables/archives/outs.hpp \ - ${srcdir}/../../include/bitcoin/database/tables/archives/point.hpp \ ${srcdir}/../../include/bitcoin/database/tables/archives/transaction.hpp \ ${srcdir}/../../include/bitcoin/database/tables/archives/txs.hpp @@ -432,7 +431,6 @@ test_libbitcoin_database_test_SOURCES = \ ${srcdir}/../../test/tables/archives/ins.cpp \ ${srcdir}/../../test/tables/archives/output.cpp \ ${srcdir}/../../test/tables/archives/outs.cpp \ - ${srcdir}/../../test/tables/archives/point.cpp \ ${srcdir}/../../test/tables/archives/transaction.cpp \ ${srcdir}/../../test/tables/archives/txs.cpp \ ${srcdir}/../../test/tables/caches/duplicate.cpp \ diff --git a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj index eaf2976b4..c2876a2ba 100644 --- a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj @@ -215,7 +215,6 @@ - diff --git a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters index 5bfd4c327..7e98fb279 100644 --- a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters @@ -315,9 +315,6 @@ src\tables\archives - - src\tables\archives - src\tables\archives diff --git a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj index 1af418049..f6378c742 100644 --- a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj @@ -183,7 +183,6 @@ - diff --git a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters index 7f4bd2660..caaa85efe 100644 --- a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters @@ -266,9 +266,6 @@ include\bitcoin\database\tables\archives - - include\bitcoin\database\tables\archives - include\bitcoin\database\tables\archives diff --git a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj index fca7a62c5..e85df954e 100644 --- a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj @@ -215,7 +215,6 @@ - diff --git a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters index 5bfd4c327..7e98fb279 100644 --- a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters +++ b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters @@ -315,9 +315,6 @@ src\tables\archives - - src\tables\archives - src\tables\archives diff --git a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj index 2158ade4c..402da38c1 100644 --- a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj @@ -183,7 +183,6 @@ - diff --git a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters index 7f4bd2660..caaa85efe 100644 --- a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters +++ b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters @@ -266,9 +266,6 @@ include\bitcoin\database\tables\archives - - include\bitcoin\database\tables\archives - include\bitcoin\database\tables\archives diff --git a/include/bitcoin/database.hpp b/include/bitcoin/database.hpp index 895881585..8770fb51c 100644 --- a/include/bitcoin/database.hpp +++ b/include/bitcoin/database.hpp @@ -64,7 +64,6 @@ #include #include #include -#include #include #include #include diff --git a/include/bitcoin/database/impl/primitives/hashmaps.ipp b/include/bitcoin/database/impl/primitives/hashmaps.ipp index e69c11660..73ff1988e 100644 --- a/include/bitcoin/database/impl/primitives/hashmaps.ipp +++ b/include/bitcoin/database/impl/primitives/hashmaps.ipp @@ -108,6 +108,21 @@ Link CLASS::count() const NOEXCEPT return body_.count(); } +// diagnostic counters +// ---------------------------------------------------------------------------- + +TEMPLATE +size_t CLASS::positive_search_count() const NOEXCEPT +{ + return positive_.load(std::memory_order_relaxed); +} + +TEMPLATE +size_t CLASS::negative_search_count() const NOEXCEPT +{ + return negative_.load(std::memory_order_relaxed); +} + // error condition // ---------------------------------------------------------------------------- @@ -382,11 +397,13 @@ inline bool CLASS::put(bool& duplicate, const memory& ptr, if (previous.is_terminal()) { duplicate = false; + ////negative_.fetch_add(one, std::memory_order_relaxed); } else { // Search the previous conflicts to determine if actual duplicate. duplicate = !first(ptr, previous, key).is_terminal(); + ////positive_.fetch_add(one, std::memory_order_relaxed); } return true; diff --git a/include/bitcoin/database/impl/query/archive/chain_reader.ipp b/include/bitcoin/database/impl/query/archive/chain_reader.ipp index 15c0b3115..557fa15ce 100644 --- a/include/bitcoin/database/impl/query/archive/chain_reader.ipp +++ b/include/bitcoin/database/impl/query/archive/chain_reader.ipp @@ -191,45 +191,45 @@ typename CLASS::transaction::cptr CLASS::get_transaction(const tx_link& link, return ptr; } -// point_link->point +// ins_link->point // ---------------------------------------------------------------------------- TEMPLATE typename CLASS::point CLASS::get_point( - const point_link& link) const NOEXCEPT + const ins_link& link) const NOEXCEPT { - table::point::record point{}; - if (!store_.point.get(link, point)) + table::ins_point::record point{}; + if (!store_.ins.get(link, point)) return {}; return { point.hash, point.index }; } -// point_link->witness +// ins_link->witness // ---------------------------------------------------------------------------- TEMPLATE typename CLASS::witness::cptr CLASS::get_witness( - const point_link& link) const NOEXCEPT + const ins_link& link) const NOEXCEPT { table::input::get_witness in{}; - table::ins::get_input ins{}; - if (!store_.ins.get(link, ins) || + table::ins_sequence::get_input ins{}; + if (!store_.ins.sequence.get(link, ins) || !store_.input.get(ins.input_fk, in)) return {}; return in.witness; } -// point_link->input_script +// ins_link->input_script // ---------------------------------------------------------------------------- TEMPLATE typename CLASS::script::cptr CLASS::get_input_script( - const point_link& link) const NOEXCEPT + const ins_link& link) const NOEXCEPT { table::input::get_script in{}; - table::ins::get_input ins{}; - if (!store_.ins.get(link, ins) || + table::ins_sequence::get_input ins{}; + if (!store_.ins.sequence.get(link, ins) || !store_.input.get(ins.input_fk, in)) return {}; @@ -246,19 +246,19 @@ typename CLASS::input::cptr CLASS::get_input(const tx_link& link, return get_input(to_point(link, index), witness); } -// point_link->input +// ins_link->input // ---------------------------------------------------------------------------- TEMPLATE -typename CLASS::input::cptr CLASS::get_input(const point_link& link, +typename CLASS::input::cptr CLASS::get_input(const ins_link& link, bool witness) const NOEXCEPT { using namespace system; table::input::get_ptrs in{ {}, witness }; - table::ins::get_input ins{}; - table::point::record point{}; - if (!store_.ins.get(link, ins) || - !store_.point.get(link, point) || + table::ins_sequence::get_input ins{}; + table::ins_point::record point{}; + if (!store_.ins.sequence.get(link, ins) || + !store_.ins.get(link, point) || !store_.input.get(ins.input_fk, in)) return {}; @@ -350,11 +350,11 @@ inpoints CLASS::get_spenders(const point& point) const NOEXCEPT return ins; } -// point_link->inpoint[spender] +// ins_link->inpoint[spender] // ---------------------------------------------------------------------------- TEMPLATE -inpoint CLASS::get_spender(const point_link& link) const NOEXCEPT +inpoint CLASS::get_spender(const ins_link& link) const NOEXCEPT { const auto tx_fk = to_input_tx(link); if (tx_fk.is_terminal()) diff --git a/include/bitcoin/database/impl/query/archive/chain_writer.ipp b/include/bitcoin/database/impl/query/archive/chain_writer.ipp index bb02736cd..77ce7acdf 100644 --- a/include/bitcoin/database/impl/query/archive/chain_writer.ipp +++ b/include/bitcoin/database/impl/query/archive/chain_writer.ipp @@ -118,12 +118,20 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction& tx, table::output::put_ref{ {}, tx_fk, tx })) return error::tx_output_put; - // Allocate and contiguously store input links. - ins_link ins_fk{}; - if (!store_.ins.put_link(ins_fk, - table::ins::put_ref{ {}, in_fk, tx_fk, tx })) + // Allocate ins/point rows and contiguously store input links. + // Point elements are set into the same rows following tx set, below. + auto ins_fk = store_.ins.allocate(inputs); + if (ins_fk.is_terminal()) return error::tx_ins_put; + // Ins put is unguarded, the accessor guards its rows against remap. + auto insert = store_.ins.get_memory(); + if (!insert || !store_.ins.sequence.put(ins_fk, + table::ins_sequence::put_ref{ {}, in_fk, tx_fk, tx })) + return error::tx_ins_put; + + insert.reset(); + // Allocate and contiguously store output links. outs_link outs_fk{}; if (!store_.outs.put_link(outs_fk, @@ -149,21 +157,13 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction& tx, if (coinbase) { // Should only be one input, but generalized anyway. - if (!store_.point.expand(ins_fk + inputs)) - return error::tx_point_allocate; - for (const auto& in: *ins) - if (!store_.point.put(ins_fk++, in->point(), - table::point::record{})) + if (!store_.ins.put(ins_fk++, in->point(), + table::ins_point::record{})) return error::tx_null_point_put; } else { - // Expand synchronizes keys with ins_fk, entries set into same offset. - // Allocate contiguous points (at sequential keys matching ins_fk). - if (!store_.point.expand(ins_fk + inputs)) - return error::tx_point_allocate; - // If dirty we must guard against duplicates. Dirty is caused by disk, // full, disorganized or reorganized block, and tx pooling. It is set // to true at runtime by any of these and in case of duplicate table @@ -174,12 +174,12 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction& tx, { // Collect duplicates to store in duplicate table. std::vector twins{}; - auto ptr = store_.point.get_memory(); + auto ptr = store_.ins.get_memory(); for (const auto& in: *ins) { bool duplicate{}; - if (!store_.point.put(duplicate, ptr, ins_fk++, in->point(), - table::point::record{})) + if (!store_.ins.put(duplicate, ptr, ins_fk++, in->point(), + table::ins_point::record{})) return error::tx_point_put; if (duplicate) @@ -197,10 +197,10 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction& tx, } else { - auto ptr = store_.point.get_memory(); + auto ptr = store_.ins.get_memory(); for (const auto& in: *ins) - if (!store_.point.put(ptr, ins_fk++, in->point(), - table::point::record{})) + if (!store_.ins.put(ptr, ins_fk++, in->point(), + table::ins_point::record{})) return error::tx_point_put; ptr.reset(); diff --git a/include/bitcoin/database/impl/query/archive/wire_reader.ipp b/include/bitcoin/database/impl/query/archive/wire_reader.ipp index 5f95ce497..6ca94f1ad 100644 --- a/include/bitcoin/database/impl/query/archive/wire_reader.ipp +++ b/include/bitcoin/database/impl/query/archive/wire_reader.ipp @@ -44,15 +44,15 @@ bool CLASS::get_wire_header(bytewriter& sink, TEMPLATE bool CLASS::get_wire_input(bytewriter& sink, - const point_link& link) const NOEXCEPT + const ins_link& link) const NOEXCEPT { - table::point::wire_point point{ {}, sink }; - if (!store_.point.get(link, point)) + table::ins_point::wire_point point{ {}, sink }; + if (!store_.ins.get(link, point)) return false; - table::ins::get_input ins{}; + table::ins_sequence::get_input ins{}; table::input::wire_script script{ {}, sink }; - if (!store_.ins.get(link, ins) || + if (!store_.ins.sequence.get(link, ins) || !store_.input.get(ins.input_fk, script)) return false; @@ -70,11 +70,11 @@ bool CLASS::get_wire_output(bytewriter& sink, TEMPLATE bool CLASS::get_wire_witness(bytewriter& sink, - const point_link& link) const NOEXCEPT + const ins_link& link) const NOEXCEPT { - table::ins::get_input ins{}; + table::ins_sequence::get_input ins{}; table::input::wire_witness wire{ {}, sink }; - return store_.ins.get(link, ins) + return store_.ins.sequence.get(link, ins) && store_.input.get(ins.input_fk, wire); } diff --git a/include/bitcoin/database/impl/query/archive/wire_writer.ipp b/include/bitcoin/database/impl/query/archive/wire_writer.ipp index dade2b230..61c40f930 100644 --- a/include/bitcoin/database/impl/query/archive/wire_writer.ipp +++ b/include/bitcoin/database/impl/query/archive/wire_writer.ipp @@ -59,12 +59,20 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction_view& tx, table::output::put_view{ {}, tx_fk, tx })) return error::tx_output_put; - // Allocate and contiguously store input links. - ins_link ins_fk{}; - if (!store_.ins.put_link(ins_fk, - table::ins::put_view{ {}, in_fk, tx_fk, tx })) + // Allocate ins/point rows and contiguously store input links. + // Point elements are set into the same rows following tx set, below. + auto ins_fk = store_.ins.allocate(inputs); + if (ins_fk.is_terminal()) return error::tx_ins_put; + // Ins put is unguarded, the accessor guards its rows against remap. + auto insert = store_.ins.get_memory(); + if (!insert || !store_.ins.sequence.put(ins_fk, + table::ins_sequence::put_view{ {}, in_fk, tx_fk, tx })) + return error::tx_ins_put; + + insert.reset(); + // Allocate and contiguously store output links. outs_link outs_fk{}; if (!store_.outs.put_link(outs_fk, @@ -93,14 +101,11 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction_view& tx, if (coinbase) { // Should only be one input, but generalized anyway. - if (!store_.point.expand(ins_fk + inputs)) - return error::tx_point_allocate; - for (size_t in{}; in < inputs; ++in) { // Should always be a null point - but could be invalid. - if (!store_.point.put(ins_fk++, chain::point(isource), - table::point::record{})) + if (!store_.ins.put(ins_fk++, chain::point(isource), + table::ins_point::record{})) return error::tx_null_point_put; // Skip script and sequence. @@ -110,22 +115,17 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction_view& tx, } else { - // Expand synchronizes keys with ins_fk, entries set into same offset. - // Allocate contiguous points (at sequential keys matching ins_fk). - if (!store_.point.expand(ins_fk + inputs)) - return error::tx_point_allocate; - if (store_.is_dirty() || !bypass) { // Collect duplicates to store in duplicate table. std::vector twins{}; - auto ptr = store_.point.get_memory(); + auto ptr = store_.ins.get_memory(); for (size_t in{}; in < inputs; ++in) { bool duplicate{}; - if (!store_.point.put(duplicate, ptr, ins_fk++, - chain::point(isource), table::point::record{})) + if (!store_.ins.put(duplicate, ptr, ins_fk++, + chain::point(isource), table::ins_point::record{})) return error::tx_point_put; if (duplicate) @@ -150,12 +150,12 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction_view& tx, } else { - auto ptr = store_.point.get_memory(); + auto ptr = store_.ins.get_memory(); for (size_t in{}; in < inputs; ++in) { - if (!store_.point.put(ptr, ins_fk++, chain::point(isource), - table::point::record{})) + if (!store_.ins.put(ptr, ins_fk++, chain::point(isource), + table::ins_point::record{})) return error::tx_point_put; // Skip script and sequence. diff --git a/include/bitcoin/database/impl/query/confirmed.ipp b/include/bitcoin/database/impl/query/confirmed.ipp index bcf870c66..98e30175d 100644 --- a/include/bitcoin/database/impl/query/confirmed.ipp +++ b/include/bitcoin/database/impl/query/confirmed.ipp @@ -51,7 +51,7 @@ header_link CLASS::find_confirmed_block( } TEMPLATE -point_link CLASS::find_confirmed_spender(const point& prevout) const NOEXCEPT +ins_link CLASS::find_confirmed_spender(const point& prevout) const NOEXCEPT { for (const auto& in: to_spenders(prevout)) if (is_confirmed_input(in)) @@ -105,7 +105,7 @@ bool CLASS::is_confirmed_tx(const tx_link& link) const NOEXCEPT } TEMPLATE -bool CLASS::is_confirmed_input(const point_link& link) const NOEXCEPT +bool CLASS::is_confirmed_input(const ins_link& link) const NOEXCEPT { // The spend.tx is strong *and* its block is confirmed (by height). const auto fk = to_input_tx(link); @@ -168,7 +168,7 @@ bool CLASS::is_spent(const output_link& link) const NOEXCEPT { // *Any* tx spends the output. Note that this could even be a tx that is in // conflict with another long-confirmed tx, or a valid tx in invalid block. - return store_.point.exists(get_outpoint(link).point()); + return store_.ins.exists(get_outpoint(link).point()); } } // namespace database diff --git a/include/bitcoin/database/impl/query/consensus/consensus_compact.ipp b/include/bitcoin/database/impl/query/consensus/consensus_compact.ipp index 1b116ed4b..c18bd15ac 100644 --- a/include/bitcoin/database/impl/query/consensus/consensus_compact.ipp +++ b/include/bitcoin/database/impl/query/consensus/consensus_compact.ipp @@ -34,20 +34,20 @@ namespace database { TEMPLATE bool CLASS::get_double_spenders(tx_links& out, const point& point, - const point_link& self) const NOEXCEPT + const ins_link& self) const NOEXCEPT { // This is most of the expense of compact block confirmation. // It is not mitigated by the point table filter, since self always exists. - point_links points{}; - for (auto it = store_.point.it(point); it; ++it) + ins_links points{}; + for (auto it = store_.ins.it(point); it; ++it) if (*it != self) points.push_back(*it); for (auto point: points) { - table::ins::get_parent get{}; - if (!store_.ins.get(point, get)) + table::ins_sequence::get_parent get{}; + if (!store_.ins.sequence.get(point, get)) return false; out.push_back(get.parent_fk); diff --git a/include/bitcoin/database/impl/query/extent.ipp b/include/bitcoin/database/impl/query/extent.ipp index 1adbe4759..b09922498 100644 --- a/include/bitcoin/database/impl/query/extent.ipp +++ b/include/bitcoin/database/impl/query/extent.ipp @@ -77,7 +77,6 @@ size_t CLASS::archive_body_size() const NOEXCEPT return header_body_size() + output_body_size() + input_body_size() - + point_body_size() + ins_body_size() + outs_body_size() + txs_body_size() @@ -110,7 +109,6 @@ size_t CLASS::archive_head_size() const NOEXCEPT return header_head_size() + output_head_size() + input_head_size() - + point_head_size() + ins_head_size() + outs_head_size() + txs_head_size() @@ -143,7 +141,6 @@ size_t CLASS::store_head_size() const NOEXCEPT DEFINE_SIZES(header) DEFINE_SIZES(output) DEFINE_SIZES(input) -DEFINE_SIZES(point) DEFINE_SIZES(ins) DEFINE_SIZES(outs) DEFINE_SIZES(txs) @@ -168,7 +165,7 @@ DEFINE_SIZES(address) // ---------------------------------------------------------------------------- DEFINE_BUCKETS(header) -DEFINE_BUCKETS(point) +DEFINE_BUCKETS(ins) DEFINE_BUCKETS(txs) DEFINE_BUCKETS(tx) @@ -185,7 +182,6 @@ DEFINE_BUCKETS(address) // ---------------------------------------------------------------------------- DEFINE_RECORDS(header) -DEFINE_RECORDS(point) DEFINE_RECORDS(ins) DEFINE_RECORDS(outs) DEFINE_RECORDS(tx) diff --git a/include/bitcoin/database/impl/query/navigate/navigate_forward.ipp b/include/bitcoin/database/impl/query/navigate/navigate_forward.ipp index d931208e1..0a0edd5f2 100644 --- a/include/bitcoin/database/impl/query/navigate/navigate_forward.ipp +++ b/include/bitcoin/database/impl/query/navigate/navigate_forward.ipp @@ -30,7 +30,7 @@ namespace database { // ---------------------------------------------------------------------------- TEMPLATE -point_link CLASS::to_point(const tx_link& link, +ins_link CLASS::to_point(const tx_link& link, uint32_t input_index) const NOEXCEPT { table::transaction::get_point tx{ {}, input_index }; @@ -56,7 +56,7 @@ output_link CLASS::to_output(const tx_link& link, } TEMPLATE -output_link CLASS::to_previous_output(const point_link& link) const NOEXCEPT +output_link CLASS::to_previous_output(const ins_link& link) const NOEXCEPT { return to_output(get_point_key(link)); } @@ -65,14 +65,14 @@ output_link CLASS::to_previous_output(const point_link& link) const NOEXCEPT // ---------------------------------------------------------------------------- TEMPLATE -point_links CLASS::to_points(const tx_link& link) const NOEXCEPT +ins_links CLASS::to_points(const tx_link& link) const NOEXCEPT { table::transaction::get_point tx{}; if (!store_.tx.get(link, tx)) return {}; // Transaction points are stored in a contiguous array of records. - point_links points(tx.number); + ins_links points(tx.number); for (auto& point: points) point = tx.points_fk++; @@ -114,9 +114,9 @@ output_links CLASS::to_prevouts(const tx_link& link) const NOEXCEPT // to_ins() TEMPLATE -point_links CLASS::to_points(const tx_links& txs) const NOEXCEPT +ins_links CLASS::to_points(const tx_links& txs) const NOEXCEPT { - point_links points{}; + ins_links points{}; for (const auto& tx: txs) { const auto tx_points = to_points(tx); @@ -159,7 +159,7 @@ output_links CLASS::to_prevouts(const tx_links& txs) const NOEXCEPT // ---------------------------------------------------------------------------- TEMPLATE -point_links CLASS::to_block_points(const header_link& link) const NOEXCEPT +ins_links CLASS::to_block_points(const header_link& link) const NOEXCEPT { return to_points(to_spending_txs(link)); } diff --git a/include/bitcoin/database/impl/query/navigate/navigate_hashmap.ipp b/include/bitcoin/database/impl/query/navigate/navigate_hashmap.ipp index 818d513c1..66e72b667 100644 --- a/include/bitcoin/database/impl/query/navigate/navigate_hashmap.ipp +++ b/include/bitcoin/database/impl/query/navigate/navigate_hashmap.ipp @@ -35,10 +35,10 @@ header_link CLASS::top_header(size_t bucket) const NOEXCEPT } TEMPLATE -point_link CLASS::top_point(size_t bucket) const NOEXCEPT +ins_link CLASS::top_point(size_t bucket) const NOEXCEPT { using namespace system; - return store_.point.top(possible_narrow_cast(bucket)); + return store_.ins.top(possible_narrow_cast(bucket)); } TEMPLATE diff --git a/include/bitcoin/database/impl/query/navigate/navigate_natural.ipp b/include/bitcoin/database/impl/query/navigate/navigate_natural.ipp index 8e34188dd..216d6867a 100644 --- a/include/bitcoin/database/impl/query/navigate/navigate_natural.ipp +++ b/include/bitcoin/database/impl/query/navigate/navigate_natural.ipp @@ -106,20 +106,20 @@ inline hash_digest CLASS::get_tx_key(const tx_link& link) const NOEXCEPT } TEMPLATE -inline point_key CLASS::get_point_key(const point_link& link) const NOEXCEPT +inline ins_key CLASS::get_point_key(const ins_link& link) const NOEXCEPT { - table::point::get_composed point{}; - if (!store_.point.get(link, point)) + table::ins_point::get_composed point{}; + if (!store_.ins.get(link, point)) return {}; return point.key; } TEMPLATE -inline hash_digest CLASS::get_point_hash(const point_link& link) const NOEXCEPT +inline hash_digest CLASS::get_point_hash(const ins_link& link) const NOEXCEPT { - table::point::record point{}; - if (!store_.point.get(link, point)) + table::ins_point::record point{}; + if (!store_.ins.get(link, point)) return {}; return point.hash; diff --git a/include/bitcoin/database/impl/query/navigate/navigate_reverse.ipp b/include/bitcoin/database/impl/query/navigate/navigate_reverse.ipp index ba3e570ec..c5f648ffb 100644 --- a/include/bitcoin/database/impl/query/navigate/navigate_reverse.ipp +++ b/include/bitcoin/database/impl/query/navigate/navigate_reverse.ipp @@ -135,10 +135,10 @@ code CLASS::to_address_outputs(const stopper& cancel, address_link& cursor, // ---------------------------------------------------------------------------- TEMPLATE -tx_link CLASS::to_input_tx(const point_link& link) const NOEXCEPT +tx_link CLASS::to_input_tx(const ins_link& link) const NOEXCEPT { - table::ins::get_parent ins{}; - if (!store_.ins.get(link, ins)) + table::ins_sequence::get_parent ins{}; + if (!store_.ins.sequence.get(link, ins)) return {}; return ins.parent_fk; @@ -155,7 +155,7 @@ tx_link CLASS::to_output_tx(const output_link& link) const NOEXCEPT } TEMPLATE -tx_link CLASS::to_prevout_tx(const point_link& link) const NOEXCEPT +tx_link CLASS::to_prevout_tx(const ins_link& link) const NOEXCEPT { return to_tx(get_point_hash(link)); } @@ -167,7 +167,7 @@ tx_link CLASS::to_prevout_tx(const point_link& link) const NOEXCEPT // This allows result to be navigated via to_block() to find any strong spend. TEMPLATE -point_links CLASS::to_spenders(const output_link& link) const NOEXCEPT +ins_links CLASS::to_spenders(const output_link& link) const NOEXCEPT { table::output::get_parent out{}; if (!store_.output.get(link, out)) @@ -178,28 +178,28 @@ point_links CLASS::to_spenders(const output_link& link) const NOEXCEPT } TEMPLATE -point_links CLASS::to_spenders(const tx_link& output_tx, +ins_links CLASS::to_spenders(const tx_link& output_tx, uint32_t output_index) const NOEXCEPT { return to_spenders(get_tx_key(output_tx), output_index); } TEMPLATE -point_links CLASS::to_spenders(const hash_digest& point_hash, +ins_links CLASS::to_spenders(const hash_digest& point_hash, uint32_t output_index) const NOEXCEPT { return to_spenders({ point_hash, output_index }); } TEMPLATE -point_links CLASS::to_spenders(const point& point) const NOEXCEPT +ins_links CLASS::to_spenders(const point& point) const NOEXCEPT { // Avoid returning spend links for coinbase inputs (not spenders). if (point.is_null()) return {}; - point_links points{}; - for (auto it = store_.point.it(point); it; ++it) + ins_links points{}; + for (auto it = store_.ins.it(point); it; ++it) points.push_back(*it); return points; @@ -243,7 +243,7 @@ header_link CLASS::to_block(const tx_link& link) const NOEXCEPT TEMPLATE uint32_t CLASS::to_input_index(const tx_link& parent_fk, - const point_link& point_fk) const NOEXCEPT + const ins_link& point_fk) const NOEXCEPT { uint32_t index{}; for (const auto& in_fk: to_points(parent_fk)) diff --git a/include/bitcoin/database/impl/query/query.ipp b/include/bitcoin/database/impl/query/query.ipp index d6ed272f1..416cdd38f 100644 --- a/include/bitcoin/database/impl/query/query.ipp +++ b/include/bitcoin/database/impl/query/query.ipp @@ -136,13 +136,13 @@ code CLASS::snapshot(const typename Store::event_handler& handler) const NOEXCEP TEMPLATE size_t CLASS::positive_search_count() const NOEXCEPT { - return store_.point.positive_search_count(); + return store_.ins.positive_search_count(); } TEMPLATE size_t CLASS::negative_search_count() const NOEXCEPT { - return store_.point.negative_search_count(); + return store_.ins.negative_search_count(); } } // namespace database diff --git a/include/bitcoin/database/impl/store/store.ipp b/include/bitcoin/database/impl/store/store.ipp index 3e4edab3a..24fb42d4a 100644 --- a/include/bitcoin/database/impl/store/store.ipp +++ b/include/bitcoin/database/impl/store/store.ipp @@ -40,10 +40,7 @@ CLASS::store(const settings& config) NOEXCEPT output_head_(head(config.path / schema::dir::heads, schema::archive::output), 1, 0, sequential), output_body_(body(config.path, schema::archive::output), config.output_size, config.output_rate, sequential), - point_head_(head(config.path / schema::dir::heads, schema::archive::point), 1, 0, random), - point_body_(body(config.path, schema::archive::point), config.point_size, config.point_rate, sequential), - - ins_head_(head(config.path / schema::dir::heads, schema::archive::ins), 1, 0, sequential), + ins_head_(head(config.path / schema::dir::heads, schema::archive::ins), 1, 0, random), ins_body_(body(config.path, schema::archive::ins), config.ins_size, config.ins_rate, sequential), outs_head_(head(config.path / schema::dir::heads, schema::archive::outs), 1, 0, sequential), @@ -120,8 +117,7 @@ CLASS::store(const settings& config) NOEXCEPT header(header_head_, header_body_, config.header_buckets), input(input_head_, input_body_), output(output_head_, output_body_), - point(point_head_, point_body_, config.point_buckets), - ins(ins_head_, ins_body_), + ins(ins_head_, ins_body_, config.ins_buckets), outs(outs_head_, outs_body_), tx(tx_head_, tx_body_, config.tx_buckets), txs(txs_head_, txs_body_, config.txs_buckets), diff --git a/include/bitcoin/database/impl/store/store_backup.ipp b/include/bitcoin/database/impl/store/store_backup.ipp index ebabd6971..fc7cc95c2 100644 --- a/include/bitcoin/database/impl/store/store_backup.ipp +++ b/include/bitcoin/database/impl/store/store_backup.ipp @@ -45,7 +45,6 @@ code CLASS::backup(const event_handler& handler, bool prune) NOEXCEPT backup(ec, header, table_t::header_table); backup(ec, input, table_t::input_table); backup(ec, output, table_t::output_table); - backup(ec, point, table_t::point_table); backup(ec, ins, table_t::ins_table); backup(ec, outs, table_t::outs_table); backup(ec, tx, table_t::tx_table); diff --git a/include/bitcoin/database/impl/store/store_close.ipp b/include/bitcoin/database/impl/store/store_close.ipp index e760cd0aa..4f037c08d 100644 --- a/include/bitcoin/database/impl/store/store_close.ipp +++ b/include/bitcoin/database/impl/store/store_close.ipp @@ -49,7 +49,6 @@ code CLASS::close(const event_handler& handler) NOEXCEPT close(ec, header, table_t::header_table); close(ec, input, table_t::input_table); close(ec, output, table_t::output_table); - close(ec, point, table_t::point_table); close(ec, ins, table_t::ins_table); close(ec, outs, table_t::outs_table); close(ec, tx, table_t::tx_table); diff --git a/include/bitcoin/database/impl/store/store_create.ipp b/include/bitcoin/database/impl/store/store_create.ipp index 80f9e0b5b..e03604d7e 100644 --- a/include/bitcoin/database/impl/store/store_create.ipp +++ b/include/bitcoin/database/impl/store/store_create.ipp @@ -63,8 +63,6 @@ code CLASS::create(const event_handler& handler) NOEXCEPT create(ec, input_body_, table_t::input_body); create(ec, output_head_, table_t::output_head); create(ec, output_body_, table_t::output_body); - create(ec, point_head_, table_t::point_head); - create(ec, point_body_, table_t::point_body); create(ec, ins_head_, table_t::ins_head); create(ec, ins_body_, table_t::ins_body); create(ec, outs_head_, table_t::outs_head); @@ -122,7 +120,6 @@ code CLASS::create(const event_handler& handler) NOEXCEPT populate(ec, header, table_t::header_table); populate(ec, input, table_t::input_table); populate(ec, output, table_t::output_table); - populate(ec, point, table_t::point_table); populate(ec, ins, table_t::ins_table); populate(ec, outs, table_t::outs_table); populate(ec, tx, table_t::tx_table); diff --git a/include/bitcoin/database/impl/store/store_dump.ipp b/include/bitcoin/database/impl/store/store_dump.ipp index 7c95e1fac..eec74f678 100644 --- a/include/bitcoin/database/impl/store/store_dump.ipp +++ b/include/bitcoin/database/impl/store/store_dump.ipp @@ -45,7 +45,6 @@ code CLASS::dump(const path& folder, dump(ec, header_head_, schema::archive::header, table_t::header_head); dump(ec, input_head_, schema::archive::input, table_t::input_head); dump(ec, output_head_, schema::archive::output, table_t::output_head); - dump(ec, point_head_, schema::archive::point, table_t::point_head); dump(ec, ins_head_, schema::archive::ins, table_t::ins_head); dump(ec, outs_head_, schema::archive::outs, table_t::outs_head); dump(ec, tx_head_, schema::archive::tx, table_t::tx_head); diff --git a/include/bitcoin/database/impl/store/store_open.ipp b/include/bitcoin/database/impl/store/store_open.ipp index ba98dc607..f6a2fd824 100644 --- a/include/bitcoin/database/impl/store/store_open.ipp +++ b/include/bitcoin/database/impl/store/store_open.ipp @@ -63,7 +63,6 @@ code CLASS::open(const event_handler& handler) NOEXCEPT verify(ec, header, table_t::header_table); verify(ec, input, table_t::input_table); verify(ec, output, table_t::output_table); - verify(ec, point, table_t::point_table); verify(ec, ins, table_t::ins_table); verify(ec, outs, table_t::outs_table); verify(ec, tx, table_t::tx_table); diff --git a/include/bitcoin/database/impl/store/store_open_load.ipp b/include/bitcoin/database/impl/store/store_open_load.ipp index 2c29065e0..c41b0cbd8 100644 --- a/include/bitcoin/database/impl/store/store_open_load.ipp +++ b/include/bitcoin/database/impl/store/store_open_load.ipp @@ -44,8 +44,6 @@ code CLASS::open_load(const event_handler& handler) NOEXCEPT open(ec, input_body_, table_t::input_body); open(ec, output_head_, table_t::output_head); open(ec, output_body_, table_t::output_body); - open(ec, point_head_, table_t::point_head); - open(ec, point_body_, table_t::point_body); open(ec, ins_head_, table_t::ins_head); open(ec, ins_body_, table_t::ins_body); open(ec, outs_head_, table_t::outs_head); @@ -101,8 +99,6 @@ code CLASS::open_load(const event_handler& handler) NOEXCEPT load(ec, input_body_, table_t::input_body); load(ec, output_head_, table_t::output_head); load(ec, output_body_, table_t::output_body); - load(ec, point_head_, table_t::point_head); - load(ec, point_body_, table_t::point_body); load(ec, ins_head_, table_t::ins_head); load(ec, ins_body_, table_t::ins_body); load(ec, outs_head_, table_t::outs_head); diff --git a/include/bitcoin/database/impl/store/store_reload.ipp b/include/bitcoin/database/impl/store/store_reload.ipp index 7c9d86bc1..3d2002d15 100644 --- a/include/bitcoin/database/impl/store/store_reload.ipp +++ b/include/bitcoin/database/impl/store/store_reload.ipp @@ -56,8 +56,6 @@ code CLASS::reload(const event_handler& handler) NOEXCEPT reload(ec, input_body_, table_t::input_body); reload(ec, output_head_, table_t::output_head); reload(ec, output_body_, table_t::output_body); - reload(ec, point_head_, table_t::point_head); - reload(ec, point_body_, table_t::point_body); reload(ec, ins_head_, table_t::ins_head); reload(ec, ins_body_, table_t::ins_body); reload(ec, outs_head_, table_t::outs_head); diff --git a/include/bitcoin/database/impl/store/store_report.ipp b/include/bitcoin/database/impl/store/store_report.ipp index 3d7d784d3..de7c9cf83 100644 --- a/include/bitcoin/database/impl/store/store_report.ipp +++ b/include/bitcoin/database/impl/store/store_report.ipp @@ -44,7 +44,6 @@ void CLASS::report(const error_handler& handler) const NOEXCEPT report(header_body_, table_t::header_body); report(input_body_, table_t::input_body); report(output_body_, table_t::output_body); - report(point_body_, table_t::point_body); report(ins_body_, table_t::ins_body); report(outs_body_, table_t::outs_body); report(tx_body_, table_t::tx_body); @@ -73,7 +72,6 @@ code CLASS::get_fault() const NOEXCEPT if ((ec = header_body_.get_fault())) return ec; if ((ec = input_body_.get_fault())) return ec; if ((ec = output_body_.get_fault())) return ec; - if ((ec = point_body_.get_fault())) return ec; if ((ec = ins_body_.get_fault())) return ec; if ((ec = outs_body_.get_fault())) return ec; if ((ec = tx_body_.get_fault())) return ec; @@ -108,7 +106,6 @@ size_t CLASS::get_space() const NOEXCEPT space(header_body_); space(input_body_); space(output_body_); - space(point_body_); space(ins_body_); space(outs_body_); space(tx_body_); diff --git a/include/bitcoin/database/impl/store/store_restore.ipp b/include/bitcoin/database/impl/store/store_restore.ipp index c4af8cc9c..bc077c917 100644 --- a/include/bitcoin/database/impl/store/store_restore.ipp +++ b/include/bitcoin/database/impl/store/store_restore.ipp @@ -116,7 +116,6 @@ code CLASS::restore(const event_handler& handler) NOEXCEPT restore(ec, header, table_t::header_table); restore(ec, input, table_t::input_table); restore(ec, output, table_t::output_table); - restore(ec, point, table_t::point_table); restore(ec, ins, table_t::ins_table); restore(ec, outs, table_t::outs_table); restore(ec, tx, table_t::tx_table); diff --git a/include/bitcoin/database/impl/store/store_snapshot.ipp b/include/bitcoin/database/impl/store/store_snapshot.ipp index 5b8c04861..47fd0f2ae 100644 --- a/include/bitcoin/database/impl/store/store_snapshot.ipp +++ b/include/bitcoin/database/impl/store/store_snapshot.ipp @@ -48,7 +48,6 @@ code CLASS::snapshot(const event_handler& handler, bool prune) NOEXCEPT flush(ec, header_body_, table_t::header_body); flush(ec, input_body_, table_t::input_body); flush(ec, output_body_, table_t::output_body); - flush(ec, point_body_, table_t::point_body); flush(ec, ins_body_, table_t::ins_body); flush(ec, outs_body_, table_t::outs_body); flush(ec, tx_body_, table_t::tx_body); diff --git a/include/bitcoin/database/impl/store/store_tables.ipp b/include/bitcoin/database/impl/store/store_tables.ipp index e185bfbbe..5e390968e 100644 --- a/include/bitcoin/database/impl/store/store_tables.ipp +++ b/include/bitcoin/database/impl/store/store_tables.ipp @@ -39,9 +39,6 @@ const CLASS::table_map CLASS::tables { table_t::output_table, "output_table" }, { table_t::output_head, "output_head" }, { table_t::output_body, "output_body" }, - { table_t::point_table, "point_table" }, - { table_t::point_head, "point_head" }, - { table_t::point_body, "point_body" }, { table_t::ins_table, "ins_table" }, { table_t::ins_head, "ins_head" }, { table_t::ins_body, "ins_body" }, diff --git a/include/bitcoin/database/impl/store/store_unload_close.ipp b/include/bitcoin/database/impl/store/store_unload_close.ipp index b7db86fc8..ef46b7c0b 100644 --- a/include/bitcoin/database/impl/store/store_unload_close.ipp +++ b/include/bitcoin/database/impl/store/store_unload_close.ipp @@ -44,8 +44,6 @@ code CLASS::unload_close(const event_handler& handler) NOEXCEPT unload(ec, input_body_, table_t::input_body); unload(ec, output_head_, table_t::output_head); unload(ec, output_body_, table_t::output_body); - unload(ec, point_head_, table_t::point_head); - unload(ec, point_body_, table_t::point_body); unload(ec, ins_head_, table_t::ins_head); unload(ec, ins_body_, table_t::ins_body); unload(ec, outs_head_, table_t::outs_head); @@ -101,8 +99,6 @@ code CLASS::unload_close(const event_handler& handler) NOEXCEPT close(ec, input_body_, table_t::input_body); close(ec, output_head_, table_t::output_head); close(ec, output_body_, table_t::output_body); - close(ec, point_head_, table_t::point_head); - close(ec, point_body_, table_t::point_body); close(ec, ins_head_, table_t::ins_head); close(ec, ins_body_, table_t::ins_body); close(ec, outs_head_, table_t::outs_head); diff --git a/include/bitcoin/database/primitives/hashmaps.hpp b/include/bitcoin/database/primitives/hashmaps.hpp index f7e508d06..6a44b7031 100644 --- a/include/bitcoin/database/primitives/hashmaps.hpp +++ b/include/bitcoin/database/primitives/hashmaps.hpp @@ -19,6 +19,7 @@ #ifndef LIBBITCOIN_DATABASE_PRIMITIVES_HASHMAPS_HPP #define LIBBITCOIN_DATABASE_PRIMITIVES_HASHMAPS_HPP +#include #include #include #include @@ -86,6 +87,15 @@ class hashmaps /// Count of body records (common across columns). Link count() const NOEXCEPT; + /// Diagnostic counters. + /// ----------------------------------------------------------------------- + + /// Count of puts resulting in table body search to detect duplication. + size_t positive_search_count() const NOEXCEPT; + + /// Count of puts not resulting in table body search to detect duplication. + size_t negative_search_count() const NOEXCEPT; + /// Errors. /// ----------------------------------------------------------------------- @@ -258,6 +268,8 @@ class hashmaps // Thread safe. body body_; + std::atomic negative_{}; + std::atomic positive_{}; }; /// Spine is the keyed spine schema; Columns are satellite column tables. diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index 28fa256f7..7d8d46404 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -123,7 +123,6 @@ class query size_t header_head_size() const NOEXCEPT; size_t output_head_size() const NOEXCEPT; size_t input_head_size() const NOEXCEPT; - size_t point_head_size() const NOEXCEPT; size_t ins_head_size() const NOEXCEPT; size_t outs_head_size() const NOEXCEPT; size_t txs_head_size() const NOEXCEPT; @@ -148,7 +147,6 @@ class query size_t header_body_size() const NOEXCEPT; size_t output_body_size() const NOEXCEPT; size_t input_body_size() const NOEXCEPT; - size_t point_body_size() const NOEXCEPT; size_t ins_body_size() const NOEXCEPT; size_t outs_body_size() const NOEXCEPT; size_t txs_body_size() const NOEXCEPT; @@ -173,7 +171,6 @@ class query size_t header_size() const NOEXCEPT; size_t output_size() const NOEXCEPT; size_t input_size() const NOEXCEPT; - size_t point_size() const NOEXCEPT; size_t ins_size() const NOEXCEPT; size_t outs_size() const NOEXCEPT; size_t txs_size() const NOEXCEPT; @@ -196,7 +193,7 @@ class query /// Buckets (hashmap + arraymap). size_t header_buckets() const NOEXCEPT; - size_t point_buckets() const NOEXCEPT; + size_t ins_buckets() const NOEXCEPT; size_t txs_buckets() const NOEXCEPT; size_t tx_buckets() const NOEXCEPT; @@ -211,7 +208,6 @@ class query /// Records. size_t header_records() const NOEXCEPT; - size_t point_records() const NOEXCEPT; size_t ins_records() const NOEXCEPT; size_t outs_records() const NOEXCEPT; size_t tx_records() const NOEXCEPT; @@ -277,15 +273,15 @@ class query /// put to tx (reverse navigation) tx_link to_output_tx(const output_link& link) const NOEXCEPT; - tx_link to_prevout_tx(const point_link& link) const NOEXCEPT; - tx_link to_input_tx(const point_link& link) const NOEXCEPT; + tx_link to_prevout_tx(const ins_link& link) const NOEXCEPT; + tx_link to_input_tx(const ins_link& link) const NOEXCEPT; /// point to put (forward navigation) - point_link to_point(const tx_link& link, + ins_link to_point(const tx_link& link, uint32_t input_index) const NOEXCEPT; output_link to_output(const tx_link& link, uint32_t output_index) const NOEXCEPT; - output_link to_previous_output(const point_link& link) const NOEXCEPT; + output_link to_previous_output(const ins_link& link) const NOEXCEPT; /// block/tx to block (reverse navigation) tx_link find_strong_tx(const tx_link& link) const NOEXCEPT; @@ -300,28 +296,28 @@ class query /// find confirmed objects (reverse navigation) header_link find_confirmed_block(const hash_digest& tx_hash) const NOEXCEPT; header_link find_confirmed_block(const tx_link& link) const NOEXCEPT; - point_link find_confirmed_spender(const point& prevout) const NOEXCEPT; + ins_link find_confirmed_spender(const point& prevout) const NOEXCEPT; /// output to spenders (reverse navigation) - point_links to_spenders(const point& prevout) const NOEXCEPT; - point_links to_spenders(const output_link& link) const NOEXCEPT; - point_links to_spenders(const hash_digest& point_hash, + ins_links to_spenders(const point& prevout) const NOEXCEPT; + ins_links to_spenders(const output_link& link) const NOEXCEPT; + ins_links to_spenders(const hash_digest& point_hash, uint32_t output_index) const NOEXCEPT; - point_links to_spenders(const tx_link& output_tx, + ins_links to_spenders(const tx_link& output_tx, uint32_t output_index) const NOEXCEPT; /// tx to puts (forward navigation) - point_links to_points(const tx_link& link) const NOEXCEPT; + ins_links to_points(const tx_link& link) const NOEXCEPT; output_links to_outputs(const tx_link& link) const NOEXCEPT; output_links to_prevouts(const tx_link& link) const NOEXCEPT; /// txs to puts (forward navigation) - point_links to_points(const tx_links& txs) const NOEXCEPT; + ins_links to_points(const tx_links& txs) const NOEXCEPT; output_links to_outputs(const tx_links& txs) const NOEXCEPT; output_links to_prevouts(const tx_links& txs) const NOEXCEPT; /// block to puts (forward navigation) - point_links to_block_points(const header_link& link) const NOEXCEPT; + ins_links to_block_points(const header_link& link) const NOEXCEPT; output_links to_block_outputs(const header_link& link) const NOEXCEPT; output_links to_block_prevouts(const header_link& link) const NOEXCEPT; @@ -341,7 +337,7 @@ class query /// hashmap enumeration header_link top_header(size_t bucket) const NOEXCEPT; - point_link top_point(size_t bucket) const NOEXCEPT; + ins_link top_point(size_t bucket) const NOEXCEPT; tx_link top_tx(size_t bucket) const NOEXCEPT; /// address outputs enumeration (reverse navigation) @@ -381,8 +377,8 @@ class query size_t get_tx_count(const header_link& link) const NOEXCEPT; inline hash_digest get_header_key(const header_link& link) const NOEXCEPT; inline hash_digest get_tx_key(const tx_link& link) const NOEXCEPT; - inline point_key get_point_key(const point_link& link) const NOEXCEPT; - inline hash_digest get_point_hash(const point_link& link) const NOEXCEPT; + inline ins_key get_point_key(const ins_link& link) const NOEXCEPT; + inline hash_digest get_point_hash(const ins_link& link) const NOEXCEPT; /// False position implies not confirmed (or fault). bool get_tx_height(size_t& out, const tx_link& link) const NOEXCEPT; @@ -416,9 +412,9 @@ class query /// Wire. /// ----------------------------------------------------------------------- - bool get_wire_input(bytewriter& sink, const point_link& link) const NOEXCEPT; + bool get_wire_input(bytewriter& sink, const ins_link& link) const NOEXCEPT; bool get_wire_output(bytewriter& sink, const output_link& link) const NOEXCEPT; - bool get_wire_witness(bytewriter& sink, const point_link& link) const NOEXCEPT; + bool get_wire_witness(bytewriter& sink, const ins_link& link) const NOEXCEPT; bool get_wire_header(bytewriter& sink, const header_link& link) const NOEXCEPT; bool get_wire_tx(bytewriter& sink, const tx_link& link, bool witness) const NOEXCEPT; @@ -442,10 +438,10 @@ class query transaction::cptr get_transaction(const tx_link& link, bool witness) const NOEXCEPT; - point get_point(const point_link& link) const NOEXCEPT; - witness::cptr get_witness(const point_link& link) const NOEXCEPT; - script::cptr get_input_script(const point_link& link) const NOEXCEPT; - input::cptr get_input(const point_link& link, bool witness) const NOEXCEPT; + point get_point(const ins_link& link) const NOEXCEPT; + witness::cptr get_witness(const ins_link& link) const NOEXCEPT; + script::cptr get_input_script(const ins_link& link) const NOEXCEPT; + input::cptr get_input(const ins_link& link, bool witness) const NOEXCEPT; input::cptr get_input(const tx_link& link, uint32_t index, bool witness) const NOEXCEPT; @@ -457,7 +453,7 @@ class query /// Inpoint and outpoint result sets. outpoint get_outpoint(const output_link& link) const NOEXCEPT; - inpoint get_spender(const point_link& link) const NOEXCEPT; + inpoint get_spender(const ins_link& link) const NOEXCEPT; inpoints get_spenders(const point& point) const NOEXCEPT; /// False implies missing prevouts, input.metadata is not populated. @@ -643,7 +639,7 @@ class query bool is_candidate_header(const header_link& link) const NOEXCEPT; bool is_confirmed_block(const header_link& link) const NOEXCEPT; bool is_confirmed_tx(const tx_link& link) const NOEXCEPT; - bool is_confirmed_input(const point_link& link) const NOEXCEPT; + bool is_confirmed_input(const ins_link& link) const NOEXCEPT; bool is_confirmed_output(const output_link& link) const NOEXCEPT; bool is_confirmed_all_prevouts(const tx_link& link) const NOEXCEPT; bool is_unconfirmed_spent(const output_link& link) const NOEXCEPT; @@ -803,7 +799,7 @@ class query /// ----------------------------------------------------------------------- header_link to_block(const tx_link& link) const NOEXCEPT; uint32_t to_input_index(const tx_link& parent_fk, - const point_link& point_fk) const NOEXCEPT; + const ins_link& point_fk) const NOEXCEPT; uint32_t to_output_index(const tx_link& parent_fk, const output_link& output_fk) const NOEXCEPT; @@ -850,7 +846,7 @@ class query /// TODO: compact blocks confirmation. bool get_double_spenders(tx_links& out, const block& block) const NOEXCEPT; bool get_double_spenders(tx_links& out, const point& point, - const point_link& self) const NOEXCEPT; + const ins_link& self) const NOEXCEPT; /// Support set_strong and set_unstrong writers. bool set_strong(const header_link& link, size_t count, diff --git a/include/bitcoin/database/settings.hpp b/include/bitcoin/database/settings.hpp index 407e59ba9..7f2b29240 100644 --- a/include/bitcoin/database/settings.hpp +++ b/include/bitcoin/database/settings.hpp @@ -67,10 +67,7 @@ struct BCD_API settings uint64_t output_size; uint16_t output_rate; - uint32_t point_buckets; - uint64_t point_size; - uint16_t point_rate; - + uint32_t ins_buckets; uint64_t ins_size; uint16_t ins_rate; diff --git a/include/bitcoin/database/store.hpp b/include/bitcoin/database/store.hpp index 94dea7e18..35d233229 100644 --- a/include/bitcoin/database/store.hpp +++ b/include/bitcoin/database/store.hpp @@ -138,13 +138,9 @@ class store Storage output_head_; Storage output_body_; - // record hashmap - Storage point_head_; - Storage point_body_; - - // array + // aggregate (point spine + sequence satellite) Storage ins_head_; - Storage ins_body_; + table::ins_storage ins_body_; // array Storage outs_head_; @@ -261,7 +257,6 @@ class store table::header header; table::input input; table::output output; - table::point point; table::ins ins; table::outs outs; table::transaction tx; diff --git a/include/bitcoin/database/tables/archives/input.hpp b/include/bitcoin/database/tables/archives/input.hpp index 2bca0bf15..4bef4bbec 100644 --- a/include/bitcoin/database/tables/archives/input.hpp +++ b/include/bitcoin/database/tables/archives/input.hpp @@ -145,11 +145,11 @@ struct input inline link count() const NOEXCEPT { using namespace system; - constexpr auto sequence_point_size = sizeof(uint32_t) + + constexpr auto sequence_ins_size = sizeof(uint32_t) + chain::point::serialized_size(); const auto& ins = *tx_.inputs_ptr(); - const auto other = ins.size() * sequence_point_size; + const auto other = ins.size() * sequence_ins_size; const auto inputs = std::accumulate(ins.cbegin(), ins.cend(), zero, [](size_t total, const auto& in) NOEXCEPT { diff --git a/include/bitcoin/database/tables/archives/ins.hpp b/include/bitcoin/database/tables/archives/ins.hpp index 874b87ab8..efe37de6e 100644 --- a/include/bitcoin/database/tables/archives/ins.hpp +++ b/include/bitcoin/database/tables/archives/ins.hpp @@ -29,17 +29,100 @@ namespace libbitcoin { namespace database { namespace table { -/// Sequence is part of an input, denormalized here for confirmation. -struct ins - : public no_map +/// Point column (spine): the searchable point (hash:index) key, no value. +struct ins_point +{ + using ix = linkage; + using link = schema::ins::link; + static constexpr auto width = schema::ins::minrow; + static constexpr auto suffix = "point"_t; + + static uint32_t to_index(ix::integer value) NOEXCEPT + { + using namespace system; + return value == ix::terminal ? chain::point::null_index : value; + } + + struct record + : public schema::ins + { + inline bool from_data(reader& source) NOEXCEPT + { + source.rewind_bytes(schema::ins::sk); + hash = source.read_hash(); + index = to_index(source.read_little_endian()); + BC_ASSERT(!source || source.get_read_position() == minrow); + return source; + } + + inline bool to_data(flipper& sink) const NOEXCEPT + { + BC_ASSERT(!sink || sink.get_write_position() == minrow); + return sink; + } + + inline bool is_null() const NOEXCEPT + { + return index == system::chain::point::null_index; + } + + inline bool operator==(const record& other) const NOEXCEPT + { + return hash == other.hash + && index == other.index; + } + + hash_digest hash{}; + ix::integer index{}; + }; + + struct get_composed + : public schema::ins + { + inline bool from_data(reader& source) NOEXCEPT + { + source.rewind_bytes(schema::ins::sk); + key = + { + source.read_hash(), + to_index(source.read_little_endian()) + }; + BC_ASSERT(!source || source.get_read_position() == minrow); + return source; + } + + system::chain::point key{}; + }; + + struct wire_point + : public schema::ins + { + inline bool from_data(reader& source) NOEXCEPT + { + source.rewind_bytes(schema::ins::sk); + sink.write_bytes(source.read_hash()); + const auto value = source.read_little_endian(); + sink.write_4_bytes_little_endian(to_index(value)); + return source; + } + + bytewriter& sink; + }; +}; + +/// Sequence column: input sequence, denormalized here for confirmation, with +/// input and parent tx navigation. +struct ins_sequence { using ix = linkage; using in = schema::input::link; using tx = schema::transaction::link; - using no_map::nomap; + using link = schema::ins_sequence::link; + static constexpr auto width = schema::ins_sequence::size; + static constexpr auto suffix = schema::ins_sequence::suffix; struct record - : public schema::ins + : public schema::ins_sequence { inline bool from_data(reader& source) NOEXCEPT { @@ -72,7 +155,7 @@ struct ins }; struct get_parent - : public schema::ins + : public schema::ins_sequence { inline bool from_data(reader& source) NOEXCEPT { @@ -85,7 +168,7 @@ struct ins }; struct get_input - : public schema::ins + : public schema::ins_sequence { inline bool from_data(reader& source) NOEXCEPT { @@ -99,7 +182,7 @@ struct ins }; struct put_ref - : public schema::ins + : public schema::ins_sequence { inline link count() const NOEXCEPT { @@ -109,7 +192,7 @@ struct ins inline bool to_data(flipper& sink) const NOEXCEPT { using namespace system; - constexpr auto sequence_point_size = sizeof(uint32_t) + + constexpr auto sequence_ins_size = sizeof(uint32_t) + chain::point::serialized_size(); auto in_fk = input_fk; @@ -122,7 +205,7 @@ struct ins // Calculate next corresponding input fk from serialized size. // (script + witness + sequence + point) - (sequence + point) - in_fk += (in->serialized_size(true) - sequence_point_size); + in_fk += (in->serialized_size(true) - sequence_ins_size); }); BC_ASSERT(!sink || sink.get_write_position() == count() * minrow); @@ -135,7 +218,7 @@ struct ins }; struct put_view - : public schema::ins + : public schema::ins_sequence { inline link count() const NOEXCEPT { @@ -199,7 +282,7 @@ struct ins }; struct wire_sequence - : public schema::ins + : public schema::ins_sequence { inline bool from_data(reader& source) NOEXCEPT { @@ -212,6 +295,22 @@ struct ins }; }; +/// The ins association: point spine (search key) with the aligned sequence +/// satellite column (one row per input), shared row count and allocation. +struct ins + : public hash_maps +{ + using base = hash_maps; + using base::hashmaps; + + /// The sequence satellite column (rows aligned with the point spine). + column sequence{ *this }; +}; + +/// Aggregate (files). +template