diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 23d3d751b..0dd6e786d 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -2406,7 +2406,7 @@ TEST (ledger, state_account) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); - ASSERT_EQ (nano::dev::genesis_key.pub, ledger.any.block_account (transaction, send1->hash ())); + ASSERT_EQ (nano::dev::genesis_key.pub, ledger.any.block_account (transaction, send1->hash ()).value ()); } TEST (ledger, state_send_receive) diff --git a/nano/lib/numbers.cpp b/nano/lib/numbers.cpp index f33d6f3cb..b4bb819b7 100644 --- a/nano/lib/numbers.cpp +++ b/nano/lib/numbers.cpp @@ -286,11 +286,6 @@ nano::uint256_union::uint256_union (uint64_t value0) *this = nano::uint256_t (value0); } -bool nano::uint512_union::operator== (nano::uint512_union const & other_a) const -{ - return bytes == other_a.bytes; -} - nano::uint512_union::uint512_union (nano::uint256_union const & upper, nano::uint256_union const & lower) { uint256s[0] = upper; @@ -355,11 +350,6 @@ bool nano::uint512_union::decode_hex (std::string const & text) return error; } -bool nano::uint512_union::operator!= (nano::uint512_union const & other_a) const -{ - return !(*this == other_a); -} - nano::uint512_union & nano::uint512_union::operator^= (nano::uint512_union const & other_a) { uint256s[0] ^= other_a.uint256s[0]; @@ -446,26 +436,6 @@ nano::uint128_union::uint128_union (nano::uint128_t const & number_a) boost::multiprecision::export_bits (number_a, bytes.rbegin (), 8, false); } -bool nano::uint128_union::operator== (nano::uint128_union const & other_a) const -{ - return qwords[0] == other_a.qwords[0] && qwords[1] == other_a.qwords[1]; -} - -bool nano::uint128_union::operator!= (nano::uint128_union const & other_a) const -{ - return !(*this == other_a); -} - -bool nano::uint128_union::operator< (nano::uint128_union const & other_a) const -{ - return std::memcmp (bytes.data (), other_a.bytes.data (), 16) < 0; -} - -bool nano::uint128_union::operator> (nano::uint128_union const & other_a) const -{ - return std::memcmp (bytes.data (), other_a.bytes.data (), 16) > 0; -} - nano::uint128_t nano::uint128_union::number () const { nano::uint128_t result; @@ -811,36 +781,11 @@ std::string nano::hash_or_account::to_account () const return account.to_account (); } -nano::block_hash const & nano::hash_or_account::as_block_hash () const -{ - return hash; -} - -nano::account const & nano::hash_or_account::as_account () const -{ - return account; -} - -nano::hash_or_account::operator nano::uint256_union const & () const -{ - return raw; -} - nano::block_hash const & nano::root::previous () const { return hash; } -bool nano::hash_or_account::operator== (nano::hash_or_account const & hash_or_account_a) const -{ - return bytes == hash_or_account_a.bytes; -} - -bool nano::hash_or_account::operator!= (nano::hash_or_account const & hash_or_account_a) const -{ - return !(*this == hash_or_account_a); -} - std::string nano::to_string_hex (uint64_t const value_a) { std::stringstream stream; @@ -963,16 +908,6 @@ nano::public_key::operator nano::hash_or_account const & () const return reinterpret_cast (*this); } -bool nano::public_key::operator== (std::nullptr_t) const -{ - return bytes == null ().bytes; -} - -bool nano::public_key::operator!= (std::nullptr_t) const -{ - return !(*this == nullptr); -} - nano::block_hash::operator nano::link const & () const { return reinterpret_cast (*this); diff --git a/nano/lib/numbers.hpp b/nano/lib/numbers.hpp index 71856e3b0..aca9a338c 100644 --- a/nano/lib/numbers.hpp +++ b/nano/lib/numbers.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -23,29 +24,32 @@ class uint128_union { public: uint128_union () = default; + uint128_union (uint64_t); + uint128_union (nano::uint128_t const &); + /** * Decode from hex string * @warning Aborts at runtime if the input is invalid */ - uint128_union (std::string const &); - uint128_union (uint64_t); - uint128_union (nano::uint128_t const &); - bool operator== (nano::uint128_union const &) const; - bool operator!= (nano::uint128_union const &) const; - bool operator< (nano::uint128_union const &) const; - bool operator> (nano::uint128_union const &) const; + explicit uint128_union (std::string const &); + void encode_hex (std::string &) const; bool decode_hex (std::string const &); void encode_dec (std::string &) const; bool decode_dec (std::string const &, bool = false); bool decode_dec (std::string const &, nano::uint128_t); + std::string format_balance (nano::uint128_t scale, int precision, bool group_digits) const; std::string format_balance (nano::uint128_t scale, int precision, bool group_digits, std::locale const & locale) const; + nano::uint128_t number () const; void clear (); bool is_zero () const; + std::string to_string () const; std::string to_string_dec () const; + +public: union { std::array bytes; @@ -53,6 +57,24 @@ public: std::array dwords; std::array qwords; }; + +public: // Keep operators inlined + std::strong_ordering operator<=> (nano::uint128_union const & other) const + { + return std::memcmp (bytes.data (), other.bytes.data (), 16) <=> 0; + }; + bool operator== (nano::uint128_union const & other) const + { + return *this <=> other == 0; + } + operator nano::uint128_t () const + { + return number (); + } + uint128_union const & as_union () const + { + return *this; + } }; static_assert (std::is_nothrow_move_constructible::value, "uint128_union should be noexcept MoveConstructible"); @@ -62,37 +84,48 @@ class amount : public uint128_union public: using uint128_union::uint128_union; + auto operator<=> (nano::amount const & other) const + { + return uint128_union::operator<=> (other); + } operator nano::uint128_t () const { return number (); } }; + class raw_key; class uint256_union { public: uint256_union () = default; + uint256_union (uint64_t); + uint256_union (uint256_t const &); + /** * Decode from hex string * @warning Aborts at runtime if the input is invalid */ explicit uint256_union (std::string const &); - uint256_union (uint64_t); - uint256_union (nano::uint256_t const &); + void encrypt (nano::raw_key const &, nano::raw_key const &, uint128_union const &); - uint256_union & operator^= (nano::uint256_union const &); - uint256_union operator^ (nano::uint256_union const &) const; + + uint256_union & operator^= (uint256_union const &); + uint256_union operator^ (uint256_union const &) const; + void encode_hex (std::string &) const; bool decode_hex (std::string const &); void encode_dec (std::string &) const; bool decode_dec (std::string const &); + nano::uint256_t number () const; void clear (); bool is_zero () const; - std::string to_string () const; - nano::uint256_t number () const; + std::string to_string () const; + +public: union { std::array bytes; @@ -101,23 +134,25 @@ public: std::array qwords; std::array owords; }; + +public: // Keep operators inlined + std::strong_ordering operator<=> (nano::uint256_union const & other) const + { + return std::memcmp (bytes.data (), other.bytes.data (), 32) <=> 0; + }; + bool operator== (nano::uint256_union const & other) const + { + return *this <=> other == 0; + } + operator nano::uint256_t () const + { + return number (); + } + uint256_union const & as_union () const + { + return *this; + } }; -inline bool operator== (nano::uint256_union const & lhs, nano::uint256_union const & rhs) -{ - return lhs.bytes == rhs.bytes; -} -inline bool operator!= (nano::uint256_union const & lhs, nano::uint256_union const & rhs) -{ - return !(lhs == rhs); -} -inline bool operator< (nano::uint256_union const & lhs, nano::uint256_union const & rhs) -{ - return std::memcmp (lhs.bytes.data (), rhs.bytes.data (), 32) < 0; -} -inline bool operator> (nano::uint256_union const & lhs, nano::uint256_union const & rhs) -{ - return std::memcmp (lhs.bytes.data (), rhs.bytes.data (), 32) > 0; -} static_assert (std::is_nothrow_move_constructible::value, "uint256_union should be noexcept MoveConstructible"); class link; @@ -129,9 +164,24 @@ class block_hash final : public uint256_union { public: using uint256_union::uint256_union; + operator nano::link const & () const; operator nano::root const & () const; operator nano::hash_or_account const & () const; + +public: // Keep operators inlined + auto operator<=> (nano::block_hash const & other) const + { + return uint256_union::operator<=> (other); + } + bool operator== (nano::block_hash const & other) const + { + return *this <=> other == 0; + } + operator nano::uint256_t () const + { + return number (); + } }; class public_key final : public uint256_union @@ -152,8 +202,24 @@ public: operator nano::link const & () const; operator nano::root const & () const; operator nano::hash_or_account const & () const; - bool operator== (std::nullptr_t) const; - bool operator!= (std::nullptr_t) const; + +public: // Keep operators inlined + auto operator<=> (nano::public_key const & other) const + { + return uint256_union::operator<=> (other); + } + bool operator== (nano::public_key const & other) const + { + return *this <=> other == 0; + } + bool operator== (std::nullptr_t) const + { + return *this == null (); + } + operator nano::uint256_t () const + { + return number (); + } }; class wallet_id : public uint256_union @@ -172,19 +238,13 @@ public: bool is_zero () const; void clear (); + std::string to_string () const; bool decode_hex (std::string const &); bool decode_account (std::string const &); std::string to_account () const; - nano::account const & as_account () const; - nano::block_hash const & as_block_hash () const; - - operator nano::uint256_union const & () const; - - bool operator== (nano::hash_or_account const &) const; - bool operator!= (nano::hash_or_account const &) const; - +public: union { std::array bytes; @@ -192,6 +252,32 @@ public: nano::account account; nano::block_hash hash; }; + +public: // Keep operators inlined + auto operator<=> (nano::hash_or_account const & other) const + { + return raw <=> other.raw; + }; + bool operator== (nano::hash_or_account const & other) const + { + return *this <=> other == 0; + } + operator nano::uint256_t () const + { + return raw.number (); + } + operator nano::uint256_union () const + { + return raw; + } + nano::account const & as_account () const + { + return account; + } + nano::block_hash const & as_block_hash () const + { + return hash; + } }; // A link can either be a destination account or source hash @@ -218,22 +304,27 @@ public: ~raw_key (); void decrypt (nano::uint256_union const &, nano::raw_key const &, uint128_union const &); }; + class uint512_union { public: uint512_union () = default; uint512_union (nano::uint256_union const &, nano::uint256_union const &); uint512_union (nano::uint512_t const &); - bool operator== (nano::uint512_union const &) const; - bool operator!= (nano::uint512_union const &) const; + nano::uint512_union & operator^= (nano::uint512_union const &); + void encode_hex (std::string &) const; bool decode_hex (std::string const &); + void clear (); bool is_zero () const; + nano::uint512_t number () const; + std::string to_string () const; +public: union { std::array bytes; @@ -241,6 +332,24 @@ public: std::array qwords; std::array uint256s; }; + +public: // Keep operators inlined + std::strong_ordering operator<=> (nano::uint512_union const & other) const + { + return std::memcmp (bytes.data (), other.bytes.data (), 64) <=> 0; + }; + bool operator== (nano::uint512_union const & other) const + { + return *this <=> other == 0; + } + operator nano::uint512_t () const + { + return number (); + } + uint512_union const & as_union () const + { + return *this; + } }; static_assert (std::is_nothrow_move_constructible::value, "uint512_union should be noexcept MoveConstructible"); @@ -381,15 +490,6 @@ struct hash<::nano::qualified_root> return hash<::nano::uint512_union> () (data_a); } }; - -template <> -struct equal_to> -{ - bool operator() (std::reference_wrapper<::nano::block_hash const> const & lhs, std::reference_wrapper<::nano::block_hash const> const & rhs) const - { - return lhs.get () == rhs.get (); - } -}; } namespace boost diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.cpp b/nano/node/bootstrap/bootstrap_bulk_pull.cpp index a4967bf35..892e28691 100644 --- a/nano/node/bootstrap/bootstrap_bulk_pull.cpp +++ b/nano/node/bootstrap/bootstrap_bulk_pull.cpp @@ -177,7 +177,7 @@ void nano::bulk_pull_client::received_block (boost::system::error_code ec, std:: // Is block expected? bool block_expected (false); // Unconfirmed head is used only for lazy destinations if legacy bootstrap is not available, see nano::bootstrap_attempt::lazy_destinations_increment (...) - bool unconfirmed_account_head = node->flags.disable_legacy_bootstrap && pull_blocks == 0 && pull.retry_limit <= node->network_params.bootstrap.lazy_retry_limit && (expected == pull.account_or_head.as_block_hash ()) && (block->account_field () == pull.account_or_head.as_account ()); + bool unconfirmed_account_head = node->flags.disable_legacy_bootstrap && pull_blocks == 0 && pull.retry_limit <= node->network_params.bootstrap.lazy_retry_limit && (expected == pull.account_or_head.as_block_hash ()) && (block->account_field ().value_or (0) == pull.account_or_head.as_account ()); if (hash == expected || unconfirmed_account_head) { expected = block->previous (); @@ -394,7 +394,7 @@ void nano::bulk_pull_server::set_current_end () if (!request->end.is_zero ()) { auto account (node->ledger.any.block_account (transaction, request->end)); - if (account != request->start.as_account ()) + if (account.value_or (0) != request->start.as_account ()) { node->logger.debug (nano::log::type::bulk_pull_server, "Request for block that is not on account chain: {} not on {}", request->end.to_string (), request->start.to_account ()); diff --git a/nano/node/bootstrap/bootstrap_frontier.cpp b/nano/node/bootstrap/bootstrap_frontier.cpp index db696dbd6..d0ad8276a 100644 --- a/nano/node/bootstrap/bootstrap_frontier.cpp +++ b/nano/node/bootstrap/bootstrap_frontier.cpp @@ -22,7 +22,7 @@ void nano::frontier_req_client::run (nano::account const & start_account_a, uint return; } nano::frontier_req request{ node->network_params.network }; - request.start = (start_account_a.is_zero () || start_account_a.number () == std::numeric_limits::max ()) ? start_account_a : start_account_a.number () + 1; + request.start = (start_account_a.is_zero () || start_account_a.number () == std::numeric_limits::max ()) ? start_account_a.number () : start_account_a.number () + 1; request.age = frontiers_age_a; request.count = count_a; current = start_account_a; diff --git a/nano/node/bootstrap/bootstrap_lazy.cpp b/nano/node/bootstrap/bootstrap_lazy.cpp index 30661abd7..439aa0ced 100644 --- a/nano/node/bootstrap/bootstrap_lazy.cpp +++ b/nano/node/bootstrap/bootstrap_lazy.cpp @@ -293,7 +293,7 @@ bool nano::bootstrap_attempt_lazy::process_block_lazy (std::shared_ptrsource_field () && !node->block_or_pruned_exists (block_a->source_field ().value ()) && block_a->source_field ().value () != node->network_params.ledger.genesis->account ()) + if (block_a->source_field () && !node->block_or_pruned_exists (block_a->source_field ().value ()) && block_a->source_field ().value () != node->network_params.ledger.genesis->account ().as_union ()) { lazy_add (block_a->source_field ().value (), retry_limit); } diff --git a/nano/node/bootstrap_ascending/service.cpp b/nano/node/bootstrap_ascending/service.cpp index 776f0b3d8..661072b44 100644 --- a/nano/node/bootstrap_ascending/service.cpp +++ b/nano/node/bootstrap_ascending/service.cpp @@ -789,7 +789,7 @@ nano::bootstrap_ascending::service::verify_result nano::bootstrap_ascending::ser case query_type::blocks_by_account: { // Open & state blocks always contain account field - if (first->account_field () != tag.start.as_account ()) + if (first->account_field ().value_or (0) != tag.start.as_account ()) { // TODO: Stat & log return verify_result::invalid; diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 591ce4b99..1091f3828 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -2462,7 +2462,7 @@ public: // Report opens as a receive tree.put ("type", "receive"); } - if (block_a.hashables.source != handler.node.ledger.constants.genesis->account ()) + if (block_a.hashables.source != handler.node.ledger.constants.genesis->account ().as_union ()) { bool error_or_pruned (false); auto amount = handler.node.ledger.any.block_amount (transaction, hash); diff --git a/nano/qt/qt.cpp b/nano/qt/qt.cpp index 48466d012..7a513e8b4 100644 --- a/nano/qt/qt.cpp +++ b/nano/qt/qt.cpp @@ -555,7 +555,7 @@ public: void open_block (nano::open_block const & block_a) { type = "Receive"; - if (block_a.hashables.source != ledger.constants.genesis->account ()) + if (block_a.hashables.source != ledger.constants.genesis->account ().as_union ()) { auto account_l = ledger.any.block_account (transaction, block_a.hashables.source); auto amount_l = ledger.any.block_amount (transaction, block_a.hash ()); diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 309290dc1..206a55092 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -2628,7 +2628,7 @@ TEST (rpc, wallet_frontiers) frontiers.push_back (nano::account (i->second.get (""))); } ASSERT_EQ (1, frontiers.size ()); - ASSERT_EQ (node->latest (nano::dev::genesis_key.pub), frontiers[0]); + ASSERT_EQ (node->latest (nano::dev::genesis_key.pub), frontiers[0].as_union ()); } TEST (rpc, work_validate) diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index ec5aa666d..d2857974d 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1093,7 +1093,7 @@ public: } void open_block (nano::open_block const & block_a) override { - if (block_a.source_field ().value () != ledger.constants.genesis->account ()) + if (block_a.source_field ().value () != ledger.constants.genesis->account ().as_union ()) { result[0] = block_a.source_field ().value (); }