diff --git a/include/bitcoin/database/error.hpp b/include/bitcoin/database/error.hpp index 8d3caceb..2272f607 100644 --- a/include/bitcoin/database/error.hpp +++ b/include/bitcoin/database/error.hpp @@ -143,7 +143,14 @@ enum error_t : uint8_t txs_empty, txs_height, txs_confirm, - txs_txs_put + txs_txs_put, + + /// optional + merkle_proof, + merkle_interval, + merkle_hashes, + merkle_arguments, + merkle_not_found }; // No current need for error_code equivalence mapping. diff --git a/include/bitcoin/database/impl/query/archive_write.ipp b/include/bitcoin/database/impl/query/archive_write.ipp index ed54581e..3e1f1cce 100644 --- a/include/bitcoin/database/impl/query/archive_write.ipp +++ b/include/bitcoin/database/impl/query/archive_write.ipp @@ -394,7 +394,7 @@ code CLASS::set_code(const block& block, const header_link& key, return ec; using bytes = linkage::integer; - auto interval = get_interval(key, height); + auto interval = create_interval(key, height); const auto size = block.serialized_size(true); const auto wire = possible_narrow_cast(size); diff --git a/include/bitcoin/database/impl/query/height.ipp b/include/bitcoin/database/impl/query/height.ipp index 92f40a33..b5a81a48 100644 --- a/include/bitcoin/database/impl/query/height.ipp +++ b/include/bitcoin/database/impl/query/height.ipp @@ -20,6 +20,7 @@ #define LIBBITCOIN_DATABASE_QUERY_HEIGHT_IPP #include +#include #include #include @@ -209,6 +210,32 @@ hashes CLASS::get_confirmed_hashes(const heights& heights) const NOEXCEPT /////////////////////////////////////////////////////////////////////////// } +TEMPLATE +hashes CLASS::get_confirmed_hashes(size_t first, size_t count) const NOEXCEPT +{ + using namespace system; + const auto size = is_odd(count) && count > one ? add1(count) : count; + if (is_add_overflow(count, one) || is_add_overflow(first, size)) + return {}; + + auto link = to_confirmed(first + count); + if (link.is_terminal()) + return {}; + + // Extra allocation for odd count optimizes for merkle root. + // Vector capacity is never reduced when resizing to smaller size. + hashes out(size); + out.resize(count); + + for (auto& hash: std::views::reverse(out)) + { + hash = get_header_key(link); + link = to_parent(link); + } + + return out; +} + // writers // ---------------------------------------------------------------------------- diff --git a/include/bitcoin/database/impl/query/optional.ipp b/include/bitcoin/database/impl/query/optional.ipp index 5e917965..6d53dcd1 100644 --- a/include/bitcoin/database/impl/query/optional.ipp +++ b/include/bitcoin/database/impl/query/optional.ipp @@ -243,7 +243,7 @@ code CLASS::get_confirmed_balance(std::atomic_bool& cancel, uint64_t& balance, const hash_digest& key, bool turbo) const NOEXCEPT { outpoints outs{}; - if (code ec = get_confirmed_unspent_outputs(cancel, outs, key, turbo)) + if (const auto ec = get_confirmed_unspent_outputs(cancel, outs, key, turbo)) { balance = zero; return ec; @@ -259,42 +259,151 @@ code CLASS::get_confirmed_balance(std::atomic_bool& cancel, uint64_t& balance, return error::success; } +// merkle +// ---------------------------------------------------------------------------- + +// protected TEMPLATE -std::optional CLASS::get_interval(const header_link& link, - size_t height) const NOEXCEPT +size_t CLASS::interval_span() const NOEXCEPT { - // Interval is enabled by address table. - if (!address_enabled()) - return {}; - - // Interval is the merkle root that spans 2^depth block hashes. + // span of zero (overflow) is disallowed (division by zero). + // span of one (2^0) caches every block (no optimization, wasted storage). + // span greater than top height eliminates caching (no optimization). const auto span = system::power2(store_.interval_depth()); + return is_zero(span) ? max_size_t : span; +} - // power2() overflow returns zero. - if (is_zero(span)) - return {}; - - // One is a functional but undesirable case. - if (is_one(span)) - return get_header_key(link); - +// protected +TEMPLATE +CLASS::hash_option CLASS::create_interval(header_link link, + size_t height) const NOEXCEPT +{ // Interval ends at nth block where n is a multiple of span. - if (!system::is_multiple(add1(height), span)) + // One is a functional but undesirable case (no optimization). + const auto span = interval_span(); + BC_ASSERT(!is_zero(span)); + + // If valid link is provided then empty return implies non-interval height. + if (link.is_terminal() || !system::is_multiple(add1(height), span)) return {}; // Generate the leaf nodes for the span. - auto header = link; hashes leaves(span); for (auto& leaf: std::views::reverse(leaves)) { - leaf = get_header_key(header); - header = to_parent(header); + leaf = get_header_key(link); + link = to_parent(link); } - // Generate the interval (merkle root) for the span ending on link header. + // Generate the merkle root of the interval ending on link header. return system::merkle_root(std::move(leaves)); } +// protected +TEMPLATE +CLASS::hash_option CLASS::get_confirmed_interval(size_t height) const NOEXCEPT +{ + const auto span = interval_span(); + BC_ASSERT(!is_zero(span)); + + if (!system::is_multiple(add1(height), span)) + return {}; + + table::txs::get_interval txs{}; + if (!store_.txs.get(to_confirmed(height), txs)) + return {}; + + return txs.interval; +} + +// protected +TEMPLATE +void CLASS::push_merkle(hashes& to, hashes&& from, size_t first) NOEXCEPT +{ + using namespace system; + for (const auto& row: block::merkle_branch(first, from.size())) + { + BC_ASSERT(row.sibling * add1(row.width) <= from.size()); + const auto it = std::next(from.begin(), row.sibling * row.width); + const auto mover = std::make_move_iterator(it); + to.push_back(merkle_root({ mover, std::next(mover, row.width) })); + } +} + +// protected +TEMPLATE +code CLASS::get_merkle_proof(hashes& proof, hashes roots, size_t target, + size_t waypoint) NOEXCEPT +{ + const auto span = interval_span(); + BC_ASSERT(!is_zero(span)); + + const auto first = (target / span) * span; + const auto last = std::min(sub1(first + span), waypoint); + auto other = get_confirmed_hashes(first, add1(last - first)); + if (other.empty()) + return error::merkle_proof; + + using namespace system; + proof.reserve(ceilinged_log2(other.size()) + ceilinged_log2(roots.size())); + push_merkle(proof, std::move(other), target % span); + push_merkle(proof, std::move(roots), target / span); + return error::success; +} + +// protected +TEMPLATE +code CLASS::get_merkle_tree(hashes& tree, size_t waypoint) NOEXCEPT +{ + const auto span = interval_span(); + BC_ASSERT(!is_zero(span)); + + const auto range = add1(waypoint); + tree.reserve(system::ceilinged_divide(range, span)); + for (size_t first{}; first < range; first += span) + { + const auto last = std::min(sub1(first + span), waypoint); + const auto size = add1(last - first); + + if (size == span) + { + auto interval = get_confirmed_interval(first); + if (!interval.has_value()) return error::merkle_interval; + tree.push_back(std::move(interval.value())); + } + else + { + auto confirmed = get_confirmed_hashes(first, size); + if (confirmed.empty()) return error::merkle_hashes; + tree.push_back(system::merkle_root(std::move(confirmed))); + } + } + + return error::success; +} + +TEMPLATE +code CLASS::get_merkle_root_and_proof(hash_digest& root, hashes& proof, + size_t target, size_t waypoint) NOEXCEPT +{ + if (target > waypoint) + return error::merkle_arguments; + + if (waypoint > get_top_confirmed()) + return error::merkle_not_found; + + hashes tree{}; + if (const auto ec = get_merkle_tree(tree, waypoint)) + return ec; + + proof.clear(); + if (const auto ec = get_merkle_proof(proof, tree, target, waypoint)) + return ec; + + root = system::merkle_root(std::move(tree)); + return {}; +} + ////TEMPLATE ////bool CLASS::set_address_output(const output& output, //// const output_link& link) NOEXCEPT diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index 97795d5b..39a24229 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -234,8 +234,6 @@ class query size_t get_unassociated_count_above(size_t height) const NOEXCEPT; size_t get_unassociated_count_above(size_t height, size_t last) const NOEXCEPT; - hashes get_candidate_hashes(const heights& heights) const NOEXCEPT; - hashes get_confirmed_hashes(const heights& heights) const NOEXCEPT; /// Translation (key/link to link/s). /// ----------------------------------------------------------------------- @@ -537,6 +535,10 @@ class query size_t get_confirmed_size() const NOEXCEPT; size_t get_confirmed_size(size_t top) const NOEXCEPT; + hashes get_candidate_hashes(const heights& heights) const NOEXCEPT; + hashes get_confirmed_hashes(const heights& heights) const NOEXCEPT; + hashes get_confirmed_hashes(size_t first, size_t count) const NOEXCEPT; + header_links get_confirmed_fork(const header_link& fork) const NOEXCEPT; header_links get_candidate_fork(size_t& fork_point) const NOEXCEPT; header_states get_validated_fork(size_t& fork_point, @@ -570,10 +572,8 @@ class query code get_confirmed_balance(std::atomic_bool& cancel, uint64_t& balance, const hash_digest& key, bool turbo=false) const NOEXCEPT; - - /// No value if header is not at configured interval. - std::optional get_interval(const header_link& link, - size_t height) const NOEXCEPT; + code get_merkle_root_and_proof(hash_digest& root, hashes& proof, + size_t target, size_t checkpoint) NOEXCEPT; bool is_filtered_body(const header_link& link) const NOEXCEPT; bool get_filter_body(filter& out, const header_link& link) const NOEXCEPT; @@ -593,6 +593,7 @@ class query const hash_digest& hash) NOEXCEPT; protected: + using hash_option = std::optional; struct span { size_t size() const NOEXCEPT { return end - begin; } @@ -707,7 +708,6 @@ class query /// address /// ----------------------------------------------------------------------- - code get_address_outputs_turbo(std::atomic_bool& cancel, outpoints& out, const hash_digest& key) const NOEXCEPT; code get_confirmed_unspent_outputs_turbo(std::atomic_bool& cancel, @@ -716,6 +716,16 @@ class query outpoints& out, const hash_digest& key, uint64_t minimum) const NOEXCEPT; + /// merkle + /// ----------------------------------------------------------------------- + size_t interval_span() const NOEXCEPT; + hash_option get_confirmed_interval(size_t height) const NOEXCEPT; + hash_option create_interval(header_link link, size_t height) const NOEXCEPT; + void push_merkle(hashes& branch, hashes&& hashes, size_t first) NOEXCEPT; + code get_merkle_tree(hashes& roots, size_t waypoint) NOEXCEPT; + code get_merkle_proof(hashes& proof, hashes roots, size_t target, + size_t waypoint) NOEXCEPT; + /// tx_fk must be allocated. /// ----------------------------------------------------------------------- code set_code(const tx_link& tx_fk, const transaction& tx, diff --git a/include/bitcoin/database/tables/archives/txs.hpp b/include/bitcoin/database/tables/archives/txs.hpp index 5ba9e41b..c3dda20d 100644 --- a/include/bitcoin/database/tables/archives/txs.hpp +++ b/include/bitcoin/database/tables/archives/txs.hpp @@ -68,14 +68,14 @@ struct txs { using namespace system; tx_fks.resize(source.read_little_endian()); - const auto flaged = source.read_little_endian(); - wire = set_right(flaged, offset, false); + const auto flagged = source.read_little_endian(); + wire = set_right(flagged, offset, false); std::for_each(tx_fks.begin(), tx_fks.end(), [&](auto& fk) NOEXCEPT { fk = source.read_little_endian(); }); - if (get_right(flaged, offset)) interval = source.read_hash(); + if (get_right(flagged, offset)) interval = source.read_hash(); BC_ASSERT(!source || source.get_read_position() == count()); return source; } @@ -86,11 +86,11 @@ struct txs BC_ASSERT(tx_fks.size() < power2(to_bits(ct::size))); const auto flag = interval.has_value(); - const auto flaged = merge(flag, wire); + const auto flagged = merge(flag, wire); const auto fks = possible_narrow_cast(tx_fks.size()); sink.write_little_endian(fks); - sink.write_little_endian(flaged); + sink.write_little_endian(flagged); std::for_each(tx_fks.begin(), tx_fks.end(), [&](const auto& fk) NOEXCEPT { @@ -150,6 +150,28 @@ struct txs hash interval{}; }; + struct get_interval + : public schema::txs + { + inline link count() const NOEXCEPT + { + BC_ASSERT(false); + return {}; + } + + inline bool from_data(reader& source) NOEXCEPT + { + using namespace system; + const auto number = source.read_little_endian(); + const auto flagged = source.read_little_endian(); + source.skip_bytes(tx::size * number); + if (get_right(flagged, offset)) interval = source.read_hash(); + return source; + } + + hash interval{}; + }; + struct get_position : public schema::txs { diff --git a/src/error.cpp b/src/error.cpp index 19916be2..d1cf1f45 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -136,7 +136,14 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { txs_empty, "txs_empty" }, { txs_height, "txs_height" }, { txs_confirm, "txs_confirm" }, - { txs_txs_put, "txs_txs_put" } + { txs_txs_put, "txs_txs_put" }, + + // optional + { merkle_proof, "merkle_proof" }, + { merkle_interval, "merkle_interval" }, + { merkle_hashes, "merkle_hashes" }, + { merkle_arguments, "merkle_arguments" }, + { merkle_not_found, "merkle_not_found" } }; DEFINE_ERROR_T_CATEGORY(error, "database", "database code") diff --git a/test/error.cpp b/test/error.cpp index 7c608d03..231b2553 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -23,7 +23,7 @@ BOOST_AUTO_TEST_SUITE(error_tests) // error_t // These test std::error_code equality operator overrides. -BOOST_AUTO_TEST_CASE(error_t__code__success__false_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__success__false_expected_message) { constexpr auto value = error::success; const auto ec = code(value); @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__success__false_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "success"); } -BOOST_AUTO_TEST_CASE(error_t__code__canceled__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__canceled__true_expected_message) { constexpr auto value = error::canceled; const auto ec = code(value); @@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__canceled__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "canceled"); } -BOOST_AUTO_TEST_CASE(error_t__code__unknown_state__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unknown_state__true_expected_message) { constexpr auto value = error::unknown_state; const auto ec = code(value); @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unknown_state__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "unknown state"); } -BOOST_AUTO_TEST_CASE(error_t__code__integrity__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__integrity__true_expected_message) { constexpr auto value = error::integrity; const auto ec = code(value); @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__integrity__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "store corrupted"); } -BOOST_AUTO_TEST_CASE(error_t__code__open_open__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__open_open__true_expected_message) { constexpr auto value = error::open_open; const auto ec = code(value); @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__open_open__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "opening open file"); } -BOOST_AUTO_TEST_CASE(error_t__code__size_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__size_failure__true_expected_message) { constexpr auto value = error::size_failure; const auto ec = code(value); @@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__size_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "filure obtaining file size"); } -BOOST_AUTO_TEST_CASE(error_t__code__close_loaded__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__close_loaded__true_expected_message) { constexpr auto value = error::close_loaded; const auto ec = code(value); @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__close_loaded__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "closing loaded file"); } -BOOST_AUTO_TEST_CASE(error_t__code__load_loaded__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__load_loaded__true_expected_message) { constexpr auto value = error::load_loaded; const auto ec = code(value); @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__load_loaded__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "loading loaded file"); } -BOOST_AUTO_TEST_CASE(error_t__code__load_locked__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__load_locked__true_expected_message) { constexpr auto value = error::load_locked; const auto ec = code(value); @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__load_locked__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "loading locked file"); } -BOOST_AUTO_TEST_CASE(error_t__code__load_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__load_failure__true_expected_message) { constexpr auto value = error::load_failure; const auto ec = code(value); @@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__load_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "file failed to load, disk may be full"); } -BOOST_AUTO_TEST_CASE(error_t__code__reload_unloaded__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__reload_unloaded__true_expected_message) { constexpr auto value = error::reload_unloaded; const auto ec = code(value); @@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__reload_unloaded__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "reloading unloaded file"); } -BOOST_AUTO_TEST_CASE(error_t__code__reload_locked__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__reload_locked__true_expected_message) { constexpr auto value = error::reload_locked; const auto ec = code(value); @@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__reload_locked__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "reloading locked file"); } -BOOST_AUTO_TEST_CASE(error_t__code__flush_unloaded__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__flush_unloaded__true_expected_message) { constexpr auto value = error::flush_unloaded; const auto ec = code(value); @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__flush_unloaded__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "flushing unloaded file"); } -BOOST_AUTO_TEST_CASE(error_t__code__flush_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__flush_failure__true_expected_message) { constexpr auto value = error::flush_failure; const auto ec = code(value); @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__flush_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "file failed to flush"); } -BOOST_AUTO_TEST_CASE(error_t__code__unload_locked__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unload_locked__true_expected_message) { constexpr auto value = error::unload_locked; const auto ec = code(value); @@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unload_locked__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "unloading locked file"); } -BOOST_AUTO_TEST_CASE(error_t__code__unload_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unload_failure__true_expected_message) { constexpr auto value = error::unload_failure; const auto ec = code(value); @@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unload_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "file failed to unload"); } -BOOST_AUTO_TEST_CASE(error_t__code__disk_full__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__disk_full__true_expected_message) { constexpr auto value = error::disk_full; const auto ec = code(value); @@ -176,7 +176,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__disk_full__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "disk full"); } -BOOST_AUTO_TEST_CASE(error_t__code__mmap_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__mmap_failure__true_expected_message) { constexpr auto value = error::mmap_failure; const auto ec = code(value); @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__mmap_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "mmap failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__mremap_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__mremap_failure__true_expected_message) { constexpr auto value = error::mremap_failure; const auto ec = code(value); @@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__mremap_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "mremap failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__munmap_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__munmap_failure__true_expected_message) { constexpr auto value = error::munmap_failure; const auto ec = code(value); @@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__munmap_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "munmap failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__madvise_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__madvise_failure__true_expected_message) { constexpr auto value = error::madvise_failure; const auto ec = code(value); @@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__madvise_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "madvise failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__sysconf_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__sysconf_failure__true_expected_message) { constexpr auto value = error::sysconf_failure; const auto ec = code(value); @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__sysconf_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "sysconf failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__ftruncate_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__ftruncate_failure__true_expected_message) { constexpr auto value = error::ftruncate_failure; const auto ec = code(value); @@ -230,7 +230,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__ftruncate_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "ftruncate failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__fsync_failure__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__fsync_failure__true_expected_message) { constexpr auto value = error::fsync_failure; const auto ec = code(value); @@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__fsync_failure__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "fsync failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__transactor_lock__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__transactor_lock__true_expected_message) { constexpr auto value = error::transactor_lock; const auto ec = code(value); @@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__transactor_lock__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "transactor lock failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__process_lock__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__process_lock__true_expected_message) { constexpr auto value = error::process_lock; const auto ec = code(value); @@ -257,7 +257,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__process_lock__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "process lock failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__flush_lock__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__flush_lock__true_expected_message) { constexpr auto value = error::flush_lock; const auto ec = code(value); @@ -266,7 +266,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__flush_lock__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "flush lock failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__flush_unlock__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__flush_unlock__true_expected_message) { constexpr auto value = error::flush_unlock; const auto ec = code(value); @@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__flush_unlock__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "flush unlock failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__process_unlock__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__process_unlock__true_expected_message) { constexpr auto value = error::process_unlock; const auto ec = code(value); @@ -284,7 +284,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__process_unlock__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "process unlock failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__missing_directory__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__missing_directory__true_expected_message) { constexpr auto value = error::missing_directory; const auto ec = code(value); @@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__missing_directory__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "missing directory failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__clear_directory__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__clear_directory__true_expected_message) { constexpr auto value = error::clear_directory; const auto ec = code(value); @@ -302,7 +302,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__clear_directory__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "clear directory failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__rename_directory__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__rename_directory__true_expected_message) { constexpr auto value = error::rename_directory; const auto ec = code(value); @@ -311,7 +311,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__rename_directory__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "rename directory failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__copy_directory__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__copy_directory__true_expected_message) { constexpr auto value = error::copy_directory; const auto ec = code(value); @@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__copy_directory__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "copy directory failure"); } -BOOST_AUTO_TEST_CASE(error_t__code__not_coalesced__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__not_coalesced__true_expected_message) { constexpr auto value = error::not_coalesced; const auto ec = code(value); @@ -329,7 +329,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__not_coalesced__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "not coalesced"); } -BOOST_AUTO_TEST_CASE(error_t__code__missing_snapshot__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__missing_snapshot__true_expected_message) { constexpr auto value = error::missing_snapshot; const auto ec = code(value); @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__missing_snapshot__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "missing snapshot"); } -BOOST_AUTO_TEST_CASE(error_t__code__unloaded_file__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unloaded_file__true_expected_message) { constexpr auto value = error::unloaded_file; const auto ec = code(value); @@ -347,7 +347,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unloaded_file__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "file not loaded"); } -BOOST_AUTO_TEST_CASE(error_t__code__create_table__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__create_table__true_expected_message) { constexpr auto value = error::create_table; const auto ec = code(value); @@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__create_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to create table"); } -BOOST_AUTO_TEST_CASE(error_t__code__close_table__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__close_table__true_expected_message) { constexpr auto value = error::close_table; const auto ec = code(value); @@ -365,7 +365,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__close_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to close table"); } -BOOST_AUTO_TEST_CASE(error_t__code__prune_table__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__prune_table__true_expected_message) { constexpr auto value = error::prune_table; const auto ec = code(value); @@ -374,7 +374,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__prune_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to prune table"); } -BOOST_AUTO_TEST_CASE(error_t__code__backup_table__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__backup_table__true_expected_message) { constexpr auto value = error::backup_table; const auto ec = code(value); @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__backup_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to backup table"); } -BOOST_AUTO_TEST_CASE(error_t__code__restore_table__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__restore_table__true_expected_message) { constexpr auto value = error::restore_table; const auto ec = code(value); @@ -392,7 +392,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__restore_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to restore table"); } -BOOST_AUTO_TEST_CASE(error_t__code__verify_table__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__verify_table__true_expected_message) { constexpr auto value = error::verify_table; const auto ec = code(value); @@ -401,7 +401,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__verify_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to verify table"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_connected__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_connected__true_expected_message) { constexpr auto value = error::tx_connected; const auto ec = code(value); @@ -410,7 +410,7 @@ 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_disconnected__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_disconnected__true_expected_message) { constexpr auto value = error::tx_disconnected; const auto ec = code(value); @@ -419,7 +419,7 @@ 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_valid__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__block_valid__true_expected_message) { constexpr auto value = error::block_valid; const auto ec = code(value); @@ -428,7 +428,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__block_valid__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "block valid"); } -BOOST_AUTO_TEST_CASE(error_t__code__block_confirmable__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__block_confirmable__true_expected_message) { constexpr auto value = error::block_confirmable; const auto ec = code(value); @@ -437,7 +437,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__block_confirmable__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "block confirmable"); } -BOOST_AUTO_TEST_CASE(error_t__code__block_unconfirmable__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__block_unconfirmable__true_expected_message) { constexpr auto value = error::block_unconfirmable; const auto ec = code(value); @@ -446,7 +446,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__block_unconfirmable__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "block unconfirmable"); } -BOOST_AUTO_TEST_CASE(error_t__code__unassociated__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unassociated__true_expected_message) { constexpr auto value = error::unassociated; const auto ec = code(value); @@ -455,7 +455,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unassociated__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "unassociated"); } -BOOST_AUTO_TEST_CASE(error_t__code__unvalidated__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unvalidated__true_expected_message) { constexpr auto value = error::unvalidated; const auto ec = code(value); @@ -464,7 +464,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unvalidated__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "unvalidated"); } -BOOST_AUTO_TEST_CASE(error_t__code__bypassed__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__bypassed__true_expected_message) { constexpr auto value = error::bypassed; const auto ec = code(value); @@ -473,7 +473,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__bypassed__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "bypassed"); } -BOOST_AUTO_TEST_CASE(error_t__code__missing_previous_output__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__missing_previous_output__true_expected_message) { constexpr auto value = error::missing_previous_output; const auto ec = code(value); @@ -482,7 +482,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__missing_previous_output__true_exected_messag BOOST_REQUIRE_EQUAL(ec.message(), "missing previous output"); } -BOOST_AUTO_TEST_CASE(error_t__code__coinbase_maturity__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__coinbase_maturity__true_expected_message) { constexpr auto value = error::coinbase_maturity; const auto ec = code(value); @@ -491,7 +491,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__coinbase_maturity__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "coinbase maturity"); } -BOOST_AUTO_TEST_CASE(error_t__code__unspent_coinbase_collision__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unspent_coinbase_collision__true_expected_message) { constexpr auto value = error::unspent_coinbase_collision; const auto ec = code(value); @@ -500,7 +500,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unspent_coinbase_collision__true_exected_mes BOOST_REQUIRE_EQUAL(ec.message(), "unspent coinbase collision"); } -BOOST_AUTO_TEST_CASE(error_t__code__relative_time_locked__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__relative_time_locked__true_expected_message) { constexpr auto value = error::relative_time_locked; const auto ec = code(value); @@ -509,7 +509,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__relative_time_locked__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "relative time locked"); } -BOOST_AUTO_TEST_CASE(error_t__code__unconfirmed_spend__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__unconfirmed_spend__true_expected_message) { constexpr auto value = error::unconfirmed_spend; const auto ec = code(value); @@ -518,7 +518,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__unconfirmed_spend__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "unconfirmed spend"); } -BOOST_AUTO_TEST_CASE(error_t__code__confirmed_double_spend__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__confirmed_double_spend__true_expected_message) { constexpr auto value = error::confirmed_double_spend; const auto ec = code(value); @@ -529,7 +529,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__confirmed_double_spend__true_exected_message // tx archive -BOOST_AUTO_TEST_CASE(error_t__code__tx_empty__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_empty__true_expected_message) { constexpr auto value = error::tx_empty; const auto ec = code(value); @@ -538,7 +538,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_empty__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_empty"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_allocate__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_allocate__true_expected_message) { constexpr auto value = error::tx_tx_allocate; const auto ec = code(value); @@ -547,7 +547,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_allocate__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_tx_allocate"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_input_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_input_put__true_expected_message) { constexpr auto value = error::tx_input_put; const auto ec = code(value); @@ -556,7 +556,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_input_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_input_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_ins_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_ins_put__true_expected_message) { constexpr auto value = error::tx_ins_put; const auto ec = code(value); @@ -565,7 +565,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_ins_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_ins_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_output_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_output_put__true_expected_message) { constexpr auto value = error::tx_output_put; const auto ec = code(value); @@ -574,7 +574,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_output_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_output_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_outs_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_outs_put__true_expected_message) { constexpr auto value = error::tx_outs_put; const auto ec = code(value); @@ -583,7 +583,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_outs_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_outs_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_point_allocate__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_point_allocate__true_expected_message) { constexpr auto value = error::tx_point_allocate; const auto ec = code(value); @@ -592,7 +592,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_point_allocate__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_point_allocate"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_point_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_point_put__true_expected_message) { constexpr auto value = error::tx_point_put; const auto ec = code(value); @@ -601,7 +601,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_point_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_point_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_null_point_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_null_point_put__true_expected_message) { constexpr auto value = error::tx_null_point_put; const auto ec = code(value); @@ -610,7 +610,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_null_point_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_null_point_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_duplicate_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_duplicate_put__true_expected_message) { constexpr auto value = error::tx_duplicate_put; const auto ec = code(value); @@ -619,7 +619,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_duplicate_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_duplicate_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_set__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_set__true_expected_message) { constexpr auto value = error::tx_tx_set; const auto ec = code(value); @@ -628,7 +628,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_set__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_tx_set"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_address_allocate__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_address_allocate__true_expected_message) { constexpr auto value = error::tx_address_allocate; const auto ec = code(value); @@ -637,7 +637,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_address_allocate__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_address_allocate"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_address_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_address_put__true_expected_message) { constexpr auto value = error::tx_address_put; const auto ec = code(value); @@ -646,7 +646,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_address_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "tx_address_put"); } -BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_commit__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_commit__true_expected_message) { constexpr auto value = error::tx_tx_commit; const auto ec = code(value); @@ -657,7 +657,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__tx_tx_commit__true_exected_message) // header archive -BOOST_AUTO_TEST_CASE(error_t__code__header_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__header_put__true_expected_message) { constexpr auto value = error::header_put; const auto ec = code(value); @@ -668,7 +668,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__header_put__true_exected_message) // txs archive -BOOST_AUTO_TEST_CASE(error_t__code__txs_header__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__txs_header__true_expected_message) { constexpr auto value = error::txs_header; const auto ec = code(value); @@ -677,7 +677,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__txs_header__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "txs_header"); } -BOOST_AUTO_TEST_CASE(error_t__code__txs_empty__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__txs_empty__true_expected_message) { constexpr auto value = error::txs_empty; const auto ec = code(value); @@ -686,7 +686,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__txs_empty__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "txs_empty"); } -BOOST_AUTO_TEST_CASE(error_t__code__txs_height__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__txs_height__true_expected_message) { constexpr auto value = error::txs_height; const auto ec = code(value); @@ -695,7 +695,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__txs_height__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "txs_height"); } -BOOST_AUTO_TEST_CASE(error_t__code__txs_confirm__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__txs_confirm__true_expected_message) { constexpr auto value = error::txs_confirm; const auto ec = code(value); @@ -704,7 +704,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__txs_confirm__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "txs_confirm"); } -BOOST_AUTO_TEST_CASE(error_t__code__txs_txs_put__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__txs_txs_put__true_expected_message) { constexpr auto value = error::txs_txs_put; const auto ec = code(value); @@ -713,4 +713,51 @@ BOOST_AUTO_TEST_CASE(error_t__code__txs_txs_put__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "txs_txs_put"); } +// optional + +BOOST_AUTO_TEST_CASE(error_t__code__merkle_proof__true_expected_message) +{ + constexpr auto value = error::merkle_proof; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "merkle_proof"); +} + +BOOST_AUTO_TEST_CASE(error_t__code__merkle_interval__true_expected_message) +{ + constexpr auto value = error::merkle_interval; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "merkle_interval"); +} + +BOOST_AUTO_TEST_CASE(error_t__code__merkle_hashes__true_expected_message) +{ + constexpr auto value = error::merkle_hashes; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "merkle_hashes"); +} + +BOOST_AUTO_TEST_CASE(error_t__code__merkle_arguments__true_expected_message) +{ + constexpr auto value = error::merkle_arguments; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "merkle_arguments"); +} + +BOOST_AUTO_TEST_CASE(error_t__code__merkle_not_found__true_expected_message) +{ + constexpr auto value = error::merkle_not_found; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "merkle_not_found"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/query/height.cpp b/test/query/height.cpp index 7c0c2a24..c31ed23d 100644 --- a/test/query/height.cpp +++ b/test/query/height.cpp @@ -22,11 +22,129 @@ BOOST_FIXTURE_TEST_SUITE(query_height_tests, test::directory_setup_fixture) -////const auto events_handler = [](auto, auto) {}; +const auto events_handler = [](auto, auto) {}; -BOOST_AUTO_TEST_CASE(query_height_test) +// get_candidate_hashes + +BOOST_AUTO_TEST_CASE(query_height__get_candidate_hashes__initialized__one) +{ + 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_EQUAL(query.get_candidate_hashes({ 0, 1, 2, 4, 6, 8 }).size(), 1u); +} + +BOOST_AUTO_TEST_CASE(query_height__get_candidate_hashes__gapped__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(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block2, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block3, test::context, false, false)); + BOOST_REQUIRE(query.push_candidate(query.to_header(test::block1.hash()))); + BOOST_REQUIRE(query.push_candidate(query.to_header(test::block2.hash()))); + BOOST_REQUIRE(query.push_candidate(query.to_header(test::block3.hash()))); + const auto locator = query.get_candidate_hashes({ 0, 1, 3, 4 }); + BOOST_REQUIRE_EQUAL(locator.size(), 3u); + BOOST_REQUIRE_EQUAL(locator[0], test::genesis.hash()); + BOOST_REQUIRE_EQUAL(locator[1], test::block1.hash()); + BOOST_REQUIRE_EQUAL(locator[2], test::block3.hash()); +} + +// get_confirmed_hashes1 + +BOOST_AUTO_TEST_CASE(query_height__get_confirmed_hashes1__initialized__one) { - BOOST_REQUIRE(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_EQUAL(query.get_confirmed_hashes({ 0, 1, 2, 4, 6, 8 }).size(), 1u); +} + +BOOST_AUTO_TEST_CASE(query_height__get_confirmed_hashes1__gapped__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(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block2, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block3, test::context, false, false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block1.hash()), false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block2.hash()), false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block3.hash()), false)); + const auto locator = query.get_confirmed_hashes({ 0, 1, 3, 4 }); + BOOST_REQUIRE_EQUAL(locator.size(), 3u); + BOOST_REQUIRE_EQUAL(locator[0], test::genesis.hash()); + BOOST_REQUIRE_EQUAL(locator[1], test::block1.hash()); + BOOST_REQUIRE_EQUAL(locator[2], test::block3.hash()); +} + +// get_confirmed_hashes2 + +BOOST_AUTO_TEST_CASE(query_height__get_confirmed_hashes2__various__expected_sizes) +{ + 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, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block2, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block3, test::context, false, false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block1.hash()), false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block2.hash()), false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block3.hash()), false)); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(0, 0).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(0, 1).size(), 1u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(0, 2).size(), 2u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(0, 3).size(), 3u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(0, 4).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(1, 0).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(1, 1).size(), 1u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(1, 2).size(), 2u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(1, 3).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(2, 0).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(2, 1).size(), 1u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(2, 2).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(3, 0).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(3, 1).size(), 0u); + BOOST_REQUIRE_EQUAL(query.get_confirmed_hashes(4, 0).size(), 0u); +} + +BOOST_AUTO_TEST_CASE(query_height__get_confirmed_hashes2__three__ascending_order) +{ + 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, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block2, test::context, false, false)); + BOOST_REQUIRE(query.set(test::block3, test::context, false, false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block1.hash()), false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block2.hash()), false)); + BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block3.hash()), false)); + + const auto hashes = query.get_confirmed_hashes(0, 3); + BOOST_REQUIRE_EQUAL(hashes.size(), 3); + BOOST_REQUIRE_EQUAL(hashes[0], test::block1.hash()); + BOOST_REQUIRE_EQUAL(hashes[1], test::block2.hash()); + BOOST_REQUIRE_EQUAL(hashes[2], test::block3.hash()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/query/initialize.cpp b/test/query/initialize.cpp index 3d1264d7..61e193e1 100644 --- a/test/query/initialize.cpp +++ b/test/query/initialize.cpp @@ -498,72 +498,4 @@ BOOST_AUTO_TEST_CASE(query_initialize__get_unassociated_count_above__gapped_cand BOOST_REQUIRE_EQUAL(query.get_unassociated_count_above(3), 0u); } -// get_candidate_hashes - -BOOST_AUTO_TEST_CASE(query_initialize__get_candidate_hashes__initialized__one) -{ - 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_EQUAL(query.get_candidate_hashes({ 0, 1, 2, 4, 6, 8 }).size(), 1u); -} - -BOOST_AUTO_TEST_CASE(query_initialize__get_candidate_hashes__gapped__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(query.initialize(test::genesis)); - BOOST_REQUIRE(query.set(test::block1, test::context, false, false)); - BOOST_REQUIRE(query.set(test::block2, test::context, false, false)); - BOOST_REQUIRE(query.set(test::block3, test::context, false, false)); - BOOST_REQUIRE(query.push_candidate(query.to_header(test::block1.hash()))); - BOOST_REQUIRE(query.push_candidate(query.to_header(test::block2.hash()))); - BOOST_REQUIRE(query.push_candidate(query.to_header(test::block3.hash()))); - const auto locator = query.get_candidate_hashes({ 0, 1, 3, 4 }); - BOOST_REQUIRE_EQUAL(locator.size(), 3u); - BOOST_REQUIRE_EQUAL(locator[0], test::genesis.hash()); - BOOST_REQUIRE_EQUAL(locator[1], test::block1.hash()); - BOOST_REQUIRE_EQUAL(locator[2], test::block3.hash()); -} - -// get_confirmed_hashes - -BOOST_AUTO_TEST_CASE(query_initialize__get_confirmed_hashes__initialized__one) -{ - 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_EQUAL(query.get_confirmed_hashes({ 0, 1, 2, 4, 6, 8 }).size(), 1u); -} - -BOOST_AUTO_TEST_CASE(query_initialize__get_confirmed_hashes__gapped__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(query.initialize(test::genesis)); - BOOST_REQUIRE(query.set(test::block1, test::context, false, false)); - BOOST_REQUIRE(query.set(test::block2, test::context, false, false)); - BOOST_REQUIRE(query.set(test::block3, test::context, false, false)); - BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block1.hash()), false)); - BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block2.hash()), false)); - BOOST_REQUIRE(query.push_confirmed(query.to_header(test::block3.hash()), false)); - const auto locator = query.get_confirmed_hashes({ 0, 1, 3, 4 }); - BOOST_REQUIRE_EQUAL(locator.size(), 3u); - BOOST_REQUIRE_EQUAL(locator[0], test::genesis.hash()); - BOOST_REQUIRE_EQUAL(locator[1], test::block1.hash()); - BOOST_REQUIRE_EQUAL(locator[2], test::block3.hash()); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/test/query/optional.cpp b/test/query/optional.cpp index 30004858..630e1b08 100644 --- a/test/query/optional.cpp +++ b/test/query/optional.cpp @@ -236,13 +236,22 @@ constexpr auto root02 = system::base16_hash("f2a2a2907abb326726a2d6500fe494f6377 // Merkle root of test blocks [0..4] constexpr auto root04 = system::sha256::double_hash(root01, root02); -BOOST_AUTO_TEST_CASE(query_optional__get_interval__depth_0__block_hash) +class query_create_interval + : public test::query_accessor +{ +public: + using base = test::query_accessor; + using base::base; + using base::create_interval; +}; + +BOOST_AUTO_TEST_CASE(query_optional__create_interval__depth_0__block_hash) { settings settings{}; settings.interval_depth = 0; settings.path = TEST_DIRECTORY; test::chunk_store store{ settings }; - test::query_accessor query{ store }; + query_create_interval query{ store }; BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); BOOST_REQUIRE(query.initialize(test::genesis)); BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); @@ -257,23 +266,23 @@ BOOST_AUTO_TEST_CASE(query_optional__get_interval__depth_0__block_hash) BOOST_REQUIRE(!header1.is_terminal()); BOOST_REQUIRE(!header2.is_terminal()); BOOST_REQUIRE(!header3.is_terminal()); - BOOST_REQUIRE(query.get_interval(header0, 0).has_value()); - BOOST_REQUIRE(query.get_interval(header1, 1).has_value()); - BOOST_REQUIRE(query.get_interval(header2, 2).has_value()); - BOOST_REQUIRE(query.get_interval(header3, 3).has_value()); - BOOST_REQUIRE_EQUAL(query.get_interval(header0, 0).value(), test::genesis.hash()); - BOOST_REQUIRE_EQUAL(query.get_interval(header1, 1).value(), test::block1.hash()); - BOOST_REQUIRE_EQUAL(query.get_interval(header2, 2).value(), test::block2.hash()); - BOOST_REQUIRE_EQUAL(query.get_interval(header3, 3).value(), test::block3.hash()); + BOOST_REQUIRE(query.create_interval(header0, 0).has_value()); + BOOST_REQUIRE(query.create_interval(header1, 1).has_value()); + BOOST_REQUIRE(query.create_interval(header2, 2).has_value()); + BOOST_REQUIRE(query.create_interval(header3, 3).has_value()); + BOOST_REQUIRE_EQUAL(query.create_interval(header0, 0).value(), test::genesis.hash()); + BOOST_REQUIRE_EQUAL(query.create_interval(header1, 1).value(), test::block1.hash()); + BOOST_REQUIRE_EQUAL(query.create_interval(header2, 2).value(), test::block2.hash()); + BOOST_REQUIRE_EQUAL(query.create_interval(header3, 3).value(), test::block3.hash()); } -BOOST_AUTO_TEST_CASE(query_optional__get_interval__depth_1__expected) +BOOST_AUTO_TEST_CASE(query_optional__create_interval__depth_1__expected) { settings settings{}; settings.interval_depth = 1; settings.path = TEST_DIRECTORY; test::chunk_store store{ settings }; - test::query_accessor query{ store }; + query_create_interval query{ store }; BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); BOOST_REQUIRE(query.initialize(test::genesis)); BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); @@ -288,21 +297,21 @@ BOOST_AUTO_TEST_CASE(query_optional__get_interval__depth_1__expected) BOOST_REQUIRE(!header1.is_terminal()); BOOST_REQUIRE(!header2.is_terminal()); BOOST_REQUIRE(!header3.is_terminal()); - BOOST_REQUIRE(!query.get_interval(header0, 0).has_value()); - BOOST_REQUIRE( query.get_interval(header1, 1).has_value()); - BOOST_REQUIRE(!query.get_interval(header2, 2).has_value()); - BOOST_REQUIRE( query.get_interval(header3, 3).has_value()); - BOOST_REQUIRE_EQUAL(query.get_interval(header1, 1).value(), root01); - BOOST_REQUIRE_EQUAL(query.get_interval(header3, 3).value(), root02); + BOOST_REQUIRE(!query.create_interval(header0, 0).has_value()); + BOOST_REQUIRE( query.create_interval(header1, 1).has_value()); + BOOST_REQUIRE(!query.create_interval(header2, 2).has_value()); + BOOST_REQUIRE( query.create_interval(header3, 3).has_value()); + BOOST_REQUIRE_EQUAL(query.create_interval(header1, 1).value(), root01); + BOOST_REQUIRE_EQUAL(query.create_interval(header3, 3).value(), root02); } -BOOST_AUTO_TEST_CASE(query_optional__get_interval__depth_2__expected) +BOOST_AUTO_TEST_CASE(query_optional__create_interval__depth_2__expected) { settings settings{}; settings.interval_depth = 2; settings.path = TEST_DIRECTORY; test::chunk_store store{ settings }; - test::query_accessor query{ store }; + query_create_interval query{ store }; BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success); BOOST_REQUIRE(query.initialize(test::genesis)); BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, false, false)); @@ -311,8 +320,8 @@ BOOST_AUTO_TEST_CASE(query_optional__get_interval__depth_2__expected) const auto header3 = query.to_header(test::block3.hash()); BOOST_REQUIRE(!header3.is_terminal()); - BOOST_REQUIRE(query.get_interval(header3, 3).has_value()); - BOOST_REQUIRE_EQUAL(query.get_interval(header3, 3).value(), root04); + BOOST_REQUIRE(query.create_interval(header3, 3).has_value()); + BOOST_REQUIRE_EQUAL(query.create_interval(header3, 3).value(), root04); } ////BOOST_AUTO_TEST_CASE(query_optional__set_filter__get_filter_and_head__expected)