diff --git a/nano/core_test/CMakeLists.txt b/nano/core_test/CMakeLists.txt index e5b47c9e43..1d01f6e796 100644 --- a/nano/core_test/CMakeLists.txt +++ b/nano/core_test/CMakeLists.txt @@ -35,10 +35,12 @@ add_executable( network_filter.cpp network_functions.cpp node.cpp + numbers.cpp object_stream.cpp optimistic_scheduler.cpp processing_queue.cpp processor_service.cpp + random_pool.cpp rep_crawler.cpp receivable.cpp peer_history.cpp @@ -54,7 +56,6 @@ add_executable( throttle.cpp toml.cpp timer.cpp - uint256_union.cpp unchecked_map.cpp utility.cpp vote_cache.cpp diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 23d3d751b1..0dd6e786db 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/core_test/uint256_union.cpp b/nano/core_test/numbers.cpp similarity index 75% rename from nano/core_test/uint256_union.cpp rename to nano/core_test/numbers.cpp index 743d0fe1c7..a30b2eb108 100644 --- a/nano/core_test/uint256_union.cpp +++ b/nano/core_test/numbers.cpp @@ -1,27 +1,192 @@ -#include +#include #include -#include #include +#include + #include +#include + +TEST (numbers, identity) +{ + ASSERT_EQ (1, nano::uint128_union (1).number ().convert_to ()); + ASSERT_EQ (1, nano::uint256_union (1).number ().convert_to ()); + ASSERT_EQ (1, nano::uint512_union (1).number ().convert_to ()); +} namespace { -template -void assert_union_types (); +template +void check_operator_less_than (Type lhs, Type rhs) +{ + ASSERT_TRUE (lhs < rhs); + ASSERT_FALSE (rhs < lhs); + ASSERT_FALSE (lhs < lhs); + ASSERT_FALSE (rhs < rhs); +} + +template +void test_operator_less_than () +{ + using underlying_t = typename Type::underlying_type; + + // Small + check_operator_less_than (Type{ 123 }, Type{ 124 }); + check_operator_less_than (Type{ 124 }, Type{ 125 }); + + // Medium + check_operator_less_than (Type{ std::numeric_limits::max () - 1 }, Type{ std::numeric_limits::max () + 1 }); + check_operator_less_than (Type{ std::numeric_limits::max () - 12345678 }, Type{ std::numeric_limits::max () - 123456 }); + + // Large + check_operator_less_than (Type{ std::numeric_limits::max () - 555555555555 }, Type{ std::numeric_limits::max () - 1 }); + + // Boundary values + check_operator_less_than (Type{ std::numeric_limits::min () }, Type{ std::numeric_limits::max () }); +} + +template +void check_operator_greater_than (Type lhs, Type rhs) +{ + ASSERT_TRUE (lhs > rhs); + ASSERT_FALSE (rhs > lhs); + ASSERT_FALSE (lhs > lhs); + ASSERT_FALSE (rhs > rhs); +} + +template +void test_operator_greater_than () +{ + using underlying_t = typename Type::underlying_type; -template -void test_union_operator_less_than (); + // Small + check_operator_greater_than (Type{ 124 }, Type{ 123 }); + check_operator_greater_than (Type{ 125 }, Type{ 124 }); -template -void check_operator_less_than (Num lhs, Num rhs); + // Medium + check_operator_greater_than (Type{ std::numeric_limits::max () + 1 }, Type{ std::numeric_limits::max () - 1 }); + check_operator_greater_than (Type{ std::numeric_limits::max () - 123456 }, Type{ std::numeric_limits::max () - 12345678 }); -template -void test_union_operator_greater_than (); + // Large + check_operator_greater_than (Type{ std::numeric_limits::max () - 1 }, Type{ std::numeric_limits::max () - 555555555555 }); -template -void check_operator_greater_than (Num lhs, Num rhs); + // Boundary values + check_operator_greater_than (Type{ std::numeric_limits::max () }, Type{ std::numeric_limits::min () }); +} + +template +void test_comparison () +{ + test_operator_less_than (); + test_operator_greater_than (); +} +} + +TEST (numbers, comparison) +{ + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); + test_comparison (); +} + +namespace +{ +template class Hash> +void test_hashing () +{ + Hash hash; + using underlying_t = typename Type::underlying_type; + + // Basic equality tests + ASSERT_EQ (hash (Type{}), hash (Type{})); + ASSERT_EQ (hash (Type{ 123 }), hash (Type{ 123 })); + + // Basic inequality tests + ASSERT_NE (hash (Type{ 123 }), hash (Type{ 124 })); + ASSERT_NE (hash (Type{ 0 }), hash (Type{ 1 })); + + // Boundary value tests + constexpr auto min_val = std::numeric_limits::min (); + constexpr auto max_val = std::numeric_limits::max (); + + // Min/Max tests + ASSERT_EQ (hash (Type{ min_val }), hash (Type{ min_val })); + ASSERT_EQ (hash (Type{ max_val }), hash (Type{ max_val })); + ASSERT_NE (hash (Type{ min_val }), hash (Type{ max_val })); + + // Near boundary tests + ASSERT_NE (hash (Type{ min_val }), hash (Type{ min_val + 1 })); + ASSERT_NE (hash (Type{ max_val }), hash (Type{ max_val - 1 })); + ASSERT_NE (hash (Type{ min_val + 1 }), hash (Type{ max_val })); + ASSERT_NE (hash (Type{ max_val - 1 }), hash (Type{ min_val })); + + // Common value tests + std::vector common_values = { + 0, // Zero + 1, // One + 42, // Common test value + 0xFF, // Byte boundary + 0xFFFF, // Word boundary + min_val, // Minimum + max_val, // Maximum + max_val / 2, // Middle value + min_val + (max_val / 2) // Offset middle + }; + + // Test all common values against each other + for (size_t i = 0; i < common_values.size (); ++i) + { + for (size_t j = i + 1; j < common_values.size (); ++j) + { + if (common_values[i] != common_values[j]) + { + ASSERT_NE (hash (Type{ common_values[i] }), hash (Type{ common_values[j] })); + } + else + { + ASSERT_EQ (hash (Type{ common_values[i] }), hash (Type{ common_values[j] })); + } + } + } +} +} + +TEST (numbers, hashing) +{ + // Using std::hash + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + + // Using boost::hash + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); + test_hashing (); } TEST (uint128_union, decode_dec) @@ -64,16 +229,6 @@ TEST (uint128_union, decode_dec_overflow) ASSERT_TRUE (error); } -TEST (uint128_union, operator_less_than) -{ - test_union_operator_less_than (); -} - -TEST (uint128_union, operator_greater_than) -{ - test_union_operator_greater_than (); -} - struct test_punct : std::moneypunct { pattern do_pos_format () const @@ -149,13 +304,6 @@ TEST (uint128_union, decode_decimal) ASSERT_EQ (1230 * nano::Knano_ratio, amount.number ()); } -TEST (unions, identity) -{ - ASSERT_EQ (1, nano::uint128_union (1).number ().convert_to ()); - ASSERT_EQ (1, nano::uint256_union (1).number ().convert_to ()); - ASSERT_EQ (1, nano::uint512_union (1).number ().convert_to ()); -} - TEST (uint256_union, key_encryption) { nano::keypair key1; @@ -449,11 +597,6 @@ TEST (uint256_union, bounds) ASSERT_TRUE (key.decode_account (bad2)); } -TEST (uint256_union, operator_less_than) -{ - test_union_operator_less_than (); -} - TEST (uint64_t, parse) { uint64_t value0 (1); @@ -504,114 +647,4 @@ TEST (uint512_union, hash) ASSERT_NE (h (x1), h (x2)); } } -} - -namespace -{ -template -void assert_union_types () -{ - static_assert ((std::is_same::value && std::is_same::value) || (std::is_same::value && std::is_same::value) || (std::is_same::value && std::is_same::value), - "Union type needs to be consistent with the lower/upper Bound type"); -} - -template -void test_union_operator_less_than () -{ - assert_union_types (); - - // Small - check_operator_less_than (Union (123), Union (124)); - check_operator_less_than (Union (124), Union (125)); - - // Medium - check_operator_less_than (Union (std::numeric_limits::max () - 1), Union (std::numeric_limits::max () + 1)); - check_operator_less_than (Union (std::numeric_limits::max () - 12345678), Union (std::numeric_limits::max () - 123456)); - - // Large - check_operator_less_than (Union (std::numeric_limits::max () - 555555555555), Union (std::numeric_limits::max () - 1)); - - // Boundary values - check_operator_less_than (Union (std::numeric_limits::min ()), Union (std::numeric_limits::max ())); -} - -template -void check_operator_less_than (Num lhs, Num rhs) -{ - ASSERT_TRUE (lhs < rhs); - ASSERT_FALSE (rhs < lhs); - ASSERT_FALSE (lhs < lhs); - ASSERT_FALSE (rhs < rhs); -} - -template -void test_union_operator_greater_than () -{ - assert_union_types (); - - // Small - check_operator_greater_than (Union (124), Union (123)); - check_operator_greater_than (Union (125), Union (124)); - - // Medium - check_operator_greater_than (Union (std::numeric_limits::max () + 1), Union (std::numeric_limits::max () - 1)); - check_operator_greater_than (Union (std::numeric_limits::max () - 123456), Union (std::numeric_limits::max () - 12345678)); - - // Large - check_operator_greater_than (Union (std::numeric_limits::max () - 1), Union (std::numeric_limits::max () - 555555555555)); - - // Boundary values - check_operator_greater_than (Union (std::numeric_limits::max ()), Union (std::numeric_limits::min ())); -} - -template -void check_operator_greater_than (Num lhs, Num rhs) -{ - ASSERT_TRUE (lhs > rhs); - ASSERT_FALSE (rhs > lhs); - ASSERT_FALSE (lhs > lhs); - ASSERT_FALSE (rhs > rhs); -} -} - -TEST (random_pool, multithreading) -{ - std::vector threads; - for (auto i = 0; i < 100; ++i) - { - threads.emplace_back ([] () { - nano::uint256_union number; - nano::random_pool::generate_block (number.bytes.data (), number.bytes.size ()); - }); - } - for (auto & i : threads) - { - i.join (); - } -} - -// Test that random 64bit numbers are within the given range -TEST (random_pool, generate_word64) -{ - int occurrences[10] = { 0 }; - for (auto i = 0; i < 1000; ++i) - { - auto random = nano::random_pool::generate_word64 (1, 9); - ASSERT_TRUE (random >= 1 && random <= 9); - occurrences[random] += 1; - } - - for (auto i = 1; i < 10; ++i) - { - ASSERT_GT (occurrences[i], 0); - } -} - -// Test random numbers > uint32 max -TEST (random_pool, generate_word64_big_number) -{ - uint64_t min = static_cast (std::numeric_limits::max ()) + 1; - uint64_t max = std::numeric_limits::max (); - auto big_random = nano::random_pool::generate_word64 (min, max); - ASSERT_GE (big_random, min); -} +} \ No newline at end of file diff --git a/nano/core_test/random_pool.cpp b/nano/core_test/random_pool.cpp new file mode 100644 index 0000000000..227ea87fcb --- /dev/null +++ b/nano/core_test/random_pool.cpp @@ -0,0 +1,48 @@ +#include +#include + +#include + +#include + +TEST (random_pool, multithreading) +{ + std::vector threads; + for (auto i = 0; i < 100; ++i) + { + threads.emplace_back ([] () { + nano::uint256_union number; + nano::random_pool::generate_block (number.bytes.data (), number.bytes.size ()); + }); + } + for (auto & i : threads) + { + i.join (); + } +} + +// Test that random 64bit numbers are within the given range +TEST (random_pool, generate_word64) +{ + int occurrences[10] = { 0 }; + for (auto i = 0; i < 1000; ++i) + { + auto random = nano::random_pool::generate_word64 (1, 9); + ASSERT_TRUE (random >= 1 && random <= 9); + occurrences[random] += 1; + } + + for (auto i = 1; i < 10; ++i) + { + ASSERT_GT (occurrences[i], 0); + } +} + +// Test random numbers > uint32 max +TEST (random_pool, generate_word64_big_number) +{ + uint64_t min = static_cast (std::numeric_limits::max ()) + 1; + uint64_t max = std::numeric_limits::max (); + auto big_random = nano::random_pool::generate_word64 (min, max); + ASSERT_GE (big_random, min); +} diff --git a/nano/lib/blocks.cpp b/nano/lib/blocks.cpp index a4c21b8678..4fc527eb0d 100644 --- a/nano/lib/blocks.cpp +++ b/nano/lib/blocks.cpp @@ -609,7 +609,7 @@ std::optional nano::send_block::destination_field () const return hashables.destination; } -nano::root const & nano::send_block::root () const +nano::root nano::send_block::root () const { return hashables.previous; } @@ -899,7 +899,7 @@ std::optional nano::open_block::source_field () const return hashables.source; } -nano::root const & nano::open_block::root () const +nano::root nano::open_block::root () const { return hashables.account; } @@ -1165,7 +1165,7 @@ bool nano::change_block::valid_predecessor (nano::block const & block_a) const return result; } -nano::root const & nano::change_block::root () const +nano::root nano::change_block::root () const { return hashables.previous; } @@ -1482,7 +1482,7 @@ bool nano::state_block::valid_predecessor (nano::block const & block_a) const return true; } -nano::root const & nano::state_block::root () const +nano::root nano::state_block::root () const { if (!hashables.previous.is_zero ()) { @@ -1836,7 +1836,7 @@ std::optional nano::receive_block::source_field () const return hashables.source; } -nano::root const & nano::receive_block::root () const +nano::root nano::receive_block::root () const { return hashables.previous; } diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 1ddb8302dd..2312855cb6 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -33,7 +33,7 @@ class block virtual uint64_t block_work () const = 0; virtual void block_work_set (uint64_t) = 0; // Previous block or account number for open blocks - virtual nano::root const & root () const = 0; + virtual nano::root root () const = 0; // Qualified root value based on previous() and root() virtual nano::qualified_root qualified_root () const; virtual void serialize (nano::stream &) const = 0; @@ -123,7 +123,7 @@ class send_block : public nano::block virtual ~send_block () = default; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::root const & root () const override; + nano::root root () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -177,7 +177,7 @@ class receive_block : public nano::block virtual ~receive_block () = default; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::root const & root () const override; + nano::root root () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -232,7 +232,7 @@ class open_block : public nano::block virtual ~open_block () = default; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::root const & root () const override; + nano::root root () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -287,7 +287,7 @@ class change_block : public nano::block virtual ~change_block () = default; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::root const & root () const override; + nano::root root () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -353,7 +353,7 @@ class state_block : public nano::block virtual ~state_block () = default; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::root const & root () const override; + nano::root root () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; diff --git a/nano/lib/numbers.cpp b/nano/lib/numbers.cpp index f33d6f3cb3..916329b673 100644 --- a/nano/lib/numbers.cpp +++ b/nano/lib/numbers.cpp @@ -61,11 +61,6 @@ std::string nano::public_key::to_account () const return result; } -nano::public_key::public_key () : - uint256_union{ 0 } -{ -} - nano::public_key const & nano::public_key::null () { return nano::hardened_constants::get ().not_an_account; @@ -143,12 +138,6 @@ bool nano::public_key::decode_account (std::string const & source_a) return error; } -nano::uint256_union::uint256_union (nano::uint256_t const & number_a) -{ - bytes.fill (0); - boost::multiprecision::export_bits (number_a, bytes.rbegin (), 8, false); -} - // Construct a uint256_union = AES_ENC_CTR (cleartext, key, iv) void nano::uint256_union::encrypt (nano::raw_key const & cleartext, nano::raw_key const & key, uint128_union const & iv) { @@ -157,11 +146,6 @@ void nano::uint256_union::encrypt (nano::raw_key const & cleartext, nano::raw_ke enc.ProcessData (bytes.data (), cleartext.bytes.data (), sizeof (cleartext.bytes)); } -bool nano::uint256_union::is_zero () const -{ - return qwords[0] == 0 && qwords[1] == 0 && qwords[2] == 0 && qwords[3] == 0; -} - std::string nano::uint256_union::to_string () const { std::string result; @@ -193,22 +177,9 @@ nano::uint256_union nano::uint256_union::operator^ (nano::uint256_union const & nano::uint256_union::uint256_union (std::string const & hex_a) { auto error (decode_hex (hex_a)); - release_assert (!error); } -void nano::uint256_union::clear () -{ - qwords.fill (0); -} - -nano::uint256_t nano::uint256_union::number () const -{ - nano::uint256_t result; - boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ()); - return result; -} - void nano::uint256_union::encode_hex (std::string & text) const { debug_assert (text.empty ()); @@ -281,46 +252,6 @@ bool nano::uint256_union::decode_dec (std::string const & text) return error; } -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; - uint256s[1] = lower; -} - -nano::uint512_union::uint512_union (nano::uint512_t const & number_a) -{ - bytes.fill (0); - boost::multiprecision::export_bits (number_a, bytes.rbegin (), 8, false); -} - -bool nano::uint512_union::is_zero () const -{ - return qwords[0] == 0 && qwords[1] == 0 && qwords[2] == 0 && qwords[3] == 0 - && qwords[4] == 0 && qwords[5] == 0 && qwords[6] == 0 && qwords[7] == 0; -} - -void nano::uint512_union::clear () -{ - bytes.fill (0); -} - -nano::uint512_t nano::uint512_union::number () const -{ - nano::uint512_t result; - boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ()); - return result; -} - void nano::uint512_union::encode_hex (std::string & text) const { debug_assert (text.empty ()); @@ -355,18 +286,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]; - uint256s[1] ^= other_a.uint256s[1]; - return *this; -} - std::string nano::uint512_union::to_string () const { std::string result; @@ -431,48 +350,9 @@ bool nano::validate_message (nano::public_key const & public_key, nano::uint256_ nano::uint128_union::uint128_union (std::string const & string_a) { auto error (decode_hex (string_a)); - release_assert (!error); } -nano::uint128_union::uint128_union (uint64_t value_a) -{ - *this = nano::uint128_t (value_a); -} - -nano::uint128_union::uint128_union (nano::uint128_t const & number_a) -{ - bytes.fill (0); - 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; - boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ()); - return result; -} - void nano::uint128_union::encode_hex (std::string & text) const { debug_assert (text.empty ()); @@ -747,16 +627,6 @@ std::string nano::uint128_union::format_balance (nano::uint128_t scale, int prec return ::format_balance (number (), scale, precision, group_digits, thousands_sep, decimal_point, grouping); } -void nano::uint128_union::clear () -{ - qwords.fill (0); -} - -bool nano::uint128_union::is_zero () const -{ - return qwords[0] == 0 && qwords[1] == 0; -} - std::string nano::uint128_union::to_string () const { std::string result; @@ -771,26 +641,6 @@ std::string nano::uint128_union::to_string_dec () const return result; } -nano::hash_or_account::hash_or_account () : - account{} -{ -} - -nano::hash_or_account::hash_or_account (uint64_t value_a) : - raw (value_a) -{ -} - -bool nano::hash_or_account::is_zero () const -{ - return raw.is_zero (); -} - -void nano::hash_or_account::clear () -{ - raw.clear (); -} - bool nano::hash_or_account::decode_hex (std::string const & text_a) { return raw.decode_hex (text_a); @@ -811,36 +661,6 @@ 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; @@ -915,6 +735,13 @@ std::ostream & nano::operator<< (std::ostream & os, const uint512_union & val) return os; } +std::ostream & nano::operator<< (std::ostream & os, const hash_or_account & val) +{ + // TODO: Replace with streaming implementation + os << val.to_string (); + return os; +} + #ifdef _WIN32 #pragma warning(push) #pragma warning(disable : 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned @@ -947,43 +774,3 @@ double nano::difficulty::to_multiplier (uint64_t const difficulty_a, uint64_t co #ifdef _WIN32 #pragma warning(pop) #endif - -nano::public_key::operator nano::link const & () const -{ - return reinterpret_cast (*this); -} - -nano::public_key::operator nano::root const & () const -{ - return reinterpret_cast (*this); -} - -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); -} - -nano::block_hash::operator nano::root const & () const -{ - return reinterpret_cast (*this); -} - -nano::block_hash::operator nano::hash_or_account const & () const -{ - return reinterpret_cast (*this); -} diff --git a/nano/lib/numbers.hpp b/nano/lib/numbers.hpp index c637e1594b..bf8137c657 100644 --- a/nano/lib/numbers.hpp +++ b/nano/lib/numbers.hpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include @@ -13,6 +15,7 @@ namespace nano using uint128_t = boost::multiprecision::uint128_t; using uint256_t = boost::multiprecision::uint256_t; using uint512_t = boost::multiprecision::uint512_t; + // SI dividers nano::uint128_t const Knano_ratio = nano::uint128_t ("1000000000000000000000000000000000"); // 10^33 = 1000 nano nano::uint128_t const nano_ratio = nano::uint128_t ("1000000000000000000000000000000"); // 10^30 = 1 nano @@ -20,31 +23,55 @@ nano::uint128_t const raw_ratio = nano::uint128_t ("1"); // 10^0 class uint128_union { +public: + // Type that is implicitly convertible to this union + using underlying_type = nano::uint128_t; + public: uint128_union () = default; + uint128_union (uint64_t value) : + uint128_union (nano::uint128_t{ value }){}; + uint128_union (nano::uint128_t const & value) + { + bytes.fill (0); + boost::multiprecision::export_bits (value, bytes.rbegin (), 8, false); + } + /** * 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; + + void clear () + { + qwords.fill (0); + } + bool is_zero () const + { + return qwords[0] == 0 && qwords[1] == 0; + } + + nano::uint128_t number () const + { + nano::uint128_t result; + boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ()); + return result; + } + std::string to_string () const; std::string to_string_dec () const; + +public: union { std::array bytes; @@ -52,6 +79,24 @@ class uint128_union 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"); @@ -61,37 +106,69 @@ 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: + // Type that is implicitly convertible to this union + using underlying_type = nano::uint256_t; + public: uint256_union () = default; + uint256_union (uint64_t value) : + uint256_union (nano::uint256_t{ value }){}; + uint256_union (nano::uint256_t const & value) + { + bytes.fill (0); + boost::multiprecision::export_bits (value, bytes.rbegin (), 8, false); + } + /** * 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 &); - void clear (); - bool is_zero () const; + void clear () + { + qwords.fill (0); + } + bool is_zero () const + { + return owords[0].is_zero () && owords[1].is_zero (); + } + + nano::uint256_t number () const + { + nano::uint256_t result; + boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ()); + return result; + } + std::string to_string () const; - nano::uint256_t number () const; +public: union { std::array bytes; @@ -100,33 +177,46 @@ class uint256_union 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; -} static_assert (std::is_nothrow_move_constructible::value, "uint256_union should be noexcept MoveConstructible"); -class link; -class root; -class hash_or_account; - // All keys and hashes are 256 bit. 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 @@ -134,21 +224,35 @@ class public_key final : public uint256_union public: using uint256_union::uint256_union; - public_key (); + public_key () : + uint256_union{ 0 } {}; static const public_key & null (); - std::string to_node_id () const; - bool decode_node_id (std::string const & source_a); + bool decode_node_id (std::string const &); void encode_account (std::string &) const; - std::string to_account () const; bool decode_account (std::string const &); - 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; + std::string to_node_id () const; + std::string to_account () 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 @@ -162,24 +266,33 @@ using account = public_key; class hash_or_account { public: - hash_or_account (); - hash_or_account (uint64_t value_a); + // Type that is implicitly convertible to this union + using underlying_type = nano::uint256_t; + +public: + hash_or_account () : + account{} {}; + hash_or_account (uint64_t value) : + raw{ value } {}; + hash_or_account (uint256_union const & value) : + raw{ value } {}; + + void clear () + { + raw.clear (); + } + bool is_zero () const + { + return raw.is_zero (); + } - 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; + std::string to_string () const; + std::string to_account () const; +public: union { std::array bytes; @@ -187,6 +300,36 @@ class hash_or_account 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; + } + explicit operator nano::uint256_t () const + { + return raw.number (); + } + explicit 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; + } + nano::uint256_union const & as_union () const + { + return raw; + } }; // A link can either be a destination account or source hash @@ -194,6 +337,16 @@ class link final : public hash_or_account { public: using hash_or_account::hash_or_account; + +public: // Keep operators inlined + auto operator<=> (nano::link const & other) const + { + return hash_or_account::operator<=> (other); + } + bool operator== (nano::link const & other) const + { + return *this <=> other == 0; + } }; // A root can either be an open block hash or a previous hash @@ -202,7 +355,20 @@ class root final : public hash_or_account public: using hash_or_account::hash_or_account; - nano::block_hash const & previous () const; + nano::block_hash const & previous () const + { + return hash; + } + +public: // Keep operators inlined + auto operator<=> (nano::root const & other) const + { + return hash_or_account::operator<=> (other); + } + bool operator== (nano::root const & other) const + { + return *this <=> other == 0; + } }; // The seed or private key @@ -213,22 +379,52 @@ class raw_key final : public uint256_union ~raw_key (); void decrypt (nano::uint256_union const &, nano::raw_key const &, uint128_union const &); }; + class uint512_union { +public: + // Type that is implicitly convertible to this union + using underlying_type = nano::uint512_t; + 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 &); + uint512_union (nano::uint512_t const & value) + { + bytes.fill (0); + boost::multiprecision::export_bits (value, bytes.rbegin (), 8, false); + } + uint512_union (nano::uint256_union const & upper, nano::uint256_union const & lower) : + uint256s{ upper, lower } {}; + + nano::uint512_union & operator^= (nano::uint512_union const & other) + { + uint256s[0] ^= other.uint256s[0]; + uint256s[1] ^= other.uint256s[1]; + return *this; + } + void encode_hex (std::string &) const; bool decode_hex (std::string const &); - void clear (); - bool is_zero () const; - nano::uint512_t number () const; + + void clear () + { + bytes.fill (0); + } + bool is_zero () const + { + return uint256s[0].is_zero () && uint256s[1].is_zero (); + } + + nano::uint512_t number () const + { + nano::uint512_t result; + boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ()); + return result; + } + std::string to_string () const; +public: union { std::array bytes; @@ -236,6 +432,24 @@ class uint512_union 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"); @@ -248,15 +462,19 @@ class signature : public uint512_union class qualified_root : public uint512_union { public: - using uint512_union::uint512_union; + qualified_root () = default; + qualified_root (nano::root const & root, nano::block_hash const & previous) : + uint512_union{ root.as_union (), previous.as_union () } {}; + qualified_root (nano::uint512_t const & value) : + uint512_union{ value } {}; - nano::root const & root () const + nano::root root () const { - return reinterpret_cast (uint256s[0]); + return nano::root{ uint256s[0] }; } - nano::block_hash const & previous () const + nano::block_hash previous () const { - return reinterpret_cast (uint256s[1]); + return nano::block_hash{ uint256s[1] }; } }; @@ -276,6 +494,7 @@ bool from_string_hex (std::string const &, uint64_t &); std::ostream & operator<< (std::ostream &, const uint128_union &); std::ostream & operator<< (std::ostream &, const uint256_union &); std::ostream & operator<< (std::ostream &, const uint512_union &); +std::ostream & operator<< (std::ostream &, const hash_or_account &); /** * Convert a double to string in fixed format @@ -297,113 +516,183 @@ namespace difficulty namespace std { template <> +struct hash<::nano::uint128_union> +{ + size_t operator() (::nano::uint128_union const & value) const noexcept + { + return value.qwords[0] + value.qwords[1]; + } +}; +template <> struct hash<::nano::uint256_union> { - size_t operator() (::nano::uint256_union const & data_a) const + size_t operator() (::nano::uint256_union const & value) const noexcept { - return data_a.qwords[0] + data_a.qwords[1] + data_a.qwords[2] + data_a.qwords[3]; + return value.qwords[0] + value.qwords[1] + value.qwords[2] + value.qwords[3]; } }; template <> -struct hash<::nano::account> +struct hash<::nano::public_key> { - size_t operator() (::nano::account const & data_a) const + size_t operator() (::nano::public_key const & value) const noexcept { - return hash<::nano::uint256_union> () (data_a); + return hash<::nano::uint256_union>{}(value); } }; template <> struct hash<::nano::block_hash> { - size_t operator() (::nano::block_hash const & data_a) const + size_t operator() (::nano::block_hash const & value) const noexcept { - return hash<::nano::uint256_union> () (data_a); + return hash<::nano::uint256_union>{}(value); } }; template <> struct hash<::nano::hash_or_account> { - size_t operator() (::nano::hash_or_account const & data_a) const + size_t operator() (::nano::hash_or_account const & value) const noexcept { - return hash<::nano::block_hash> () (data_a.as_block_hash ()); + return hash<::nano::block_hash>{}(value.as_block_hash ()); } }; template <> -struct hash<::nano::raw_key> +struct hash<::nano::root> { - size_t operator() (::nano::raw_key const & data_a) const + size_t operator() (::nano::root const & value) const noexcept { - return hash<::nano::uint256_union> () (data_a); + return hash<::nano::hash_or_account>{}(value); } }; template <> -struct hash<::nano::root> +struct hash<::nano::link> { - size_t operator() (::nano::root const & data_a) const + size_t operator() (::nano::link const & value) const noexcept { - return hash<::nano::uint256_union> () (data_a); + return hash<::nano::hash_or_account>{}(value); } }; template <> -struct hash<::nano::wallet_id> +struct hash<::nano::raw_key> { - size_t operator() (::nano::wallet_id const & data_a) const + size_t operator() (::nano::raw_key const & value) const noexcept { - return hash<::nano::uint256_union> () (data_a); + return hash<::nano::uint256_union>{}(value); } }; template <> -struct hash<::nano::uint256_t> +struct hash<::nano::wallet_id> { - size_t operator() (::nano::uint256_t const & number_a) const + size_t operator() (::nano::wallet_id const & value) const noexcept { - return number_a.convert_to (); + return hash<::nano::uint256_union>{}(value); } }; template <> struct hash<::nano::uint512_union> { - size_t operator() (::nano::uint512_union const & data_a) const + size_t operator() (::nano::uint512_union const & value) const noexcept { - return hash<::nano::uint256_union> () (data_a.uint256s[0]) + hash<::nano::uint256_union> () (data_a.uint256s[1]); + return hash<::nano::uint256_union>{}(value.uint256s[0]) + hash<::nano::uint256_union> () (value.uint256s[1]); } }; template <> struct hash<::nano::qualified_root> { - size_t operator() (::nano::qualified_root const & data_a) const + size_t operator() (::nano::qualified_root const & value) const noexcept { - return hash<::nano::uint512_union> () (data_a); + return hash<::nano::uint512_union>{}(value); } }; +} +namespace boost +{ template <> -struct equal_to> +struct hash<::nano::uint128_union> { - bool operator() (std::reference_wrapper<::nano::block_hash const> const & lhs, std::reference_wrapper<::nano::block_hash const> const & rhs) const + size_t operator() (::nano::uint128_union const & value) const noexcept { - return lhs.get () == rhs.get (); + return std::hash<::nano::uint128_union> () (value); } }; -} - -namespace boost +template <> +struct hash<::nano::uint256_union> { + size_t operator() (::nano::uint256_union const & value) const noexcept + { + return std::hash<::nano::uint256_union> () (value); + } +}; template <> -struct hash> +struct hash<::nano::public_key> { - size_t operator() (std::reference_wrapper<::nano::block_hash const> const & hash_a) const + size_t operator() (::nano::public_key const & value) const noexcept { - std::hash<::nano::block_hash> hash; - return hash (hash_a); + return std::hash<::nano::public_key> () (value); + } +}; +template <> +struct hash<::nano::block_hash> +{ + size_t operator() (::nano::block_hash const & value) const noexcept + { + return std::hash<::nano::block_hash> () (value); + } +}; +template <> +struct hash<::nano::hash_or_account> +{ + size_t operator() (::nano::hash_or_account const & value) const noexcept + { + return std::hash<::nano::hash_or_account> () (value); } }; template <> struct hash<::nano::root> { - size_t operator() (::nano::root const & value_a) const + size_t operator() (::nano::root const & value) const noexcept { - return std::hash<::nano::root> () (value_a); + return std::hash<::nano::root> () (value); + } +}; +template <> +struct hash<::nano::link> +{ + size_t operator() (::nano::link const & value) const noexcept + { + return std::hash<::nano::link> () (value); + } +}; +template <> +struct hash<::nano::raw_key> +{ + size_t operator() (::nano::raw_key const & value) const noexcept + { + return std::hash<::nano::raw_key> () (value); + } +}; +template <> +struct hash<::nano::wallet_id> +{ + size_t operator() (::nano::wallet_id const & value) const noexcept + { + return std::hash<::nano::wallet_id> () (value); + } +}; +template <> +struct hash<::nano::uint512_union> +{ + size_t operator() (::nano::uint512_union const & value) const noexcept + { + return std::hash<::nano::uint512_union> () (value); + } +}; +template <> +struct hash<::nano::qualified_root> +{ + size_t operator() (::nano::qualified_root const & value) const noexcept + { + return std::hash<::nano::qualified_root> () (value); } }; } @@ -427,6 +716,11 @@ struct fmt::formatter : fmt::ostream_formatter { }; +template <> +struct fmt::formatter : fmt::ostream_formatter +{ +}; + template <> struct fmt::formatter : fmt::formatter { @@ -440,4 +734,4 @@ struct fmt::formatter : fmt::formatter template <> struct fmt::formatter : fmt::formatter { -}; \ No newline at end of file +}; diff --git a/nano/node/bootstrap/bootstrap.cpp b/nano/node/bootstrap/bootstrap.cpp index 3db711dfce..8779400eec 100644 --- a/nano/node/bootstrap/bootstrap.cpp +++ b/nano/node/bootstrap/bootstrap.cpp @@ -313,7 +313,7 @@ void nano::pulls_cache::add (nano::pull_info const & pull_a) cache.erase (cache.begin ()); } debug_assert (cache.size () <= cache_size_max); - nano::uint512_union head_512 (pull_a.account_or_head, pull_a.head_original); + nano::uint512_union head_512 (pull_a.account_or_head.as_union (), pull_a.head_original); auto existing (cache.get ().find (head_512)); if (existing == cache.get ().end ()) { @@ -336,7 +336,7 @@ void nano::pulls_cache::add (nano::pull_info const & pull_a) void nano::pulls_cache::update_pull (nano::pull_info & pull_a) { nano::lock_guard guard{ pulls_cache_mutex }; - nano::uint512_union head_512 (pull_a.account_or_head, pull_a.head_original); + nano::uint512_union head_512 (pull_a.account_or_head.as_union (), pull_a.head_original); auto existing (cache.get ().find (head_512)); if (existing != cache.get ().end ()) { @@ -347,7 +347,7 @@ void nano::pulls_cache::update_pull (nano::pull_info & pull_a) void nano::pulls_cache::remove (nano::pull_info const & pull_a) { nano::lock_guard guard{ pulls_cache_mutex }; - nano::uint512_union head_512 (pull_a.account_or_head, pull_a.head_original); + nano::uint512_union head_512 (pull_a.account_or_head.as_union (), pull_a.head_original); cache.get ().erase (head_512); } diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.cpp b/nano/node/bootstrap/bootstrap_bulk_pull.cpp index a4967bf35c..892e28691d 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 db696dbd61..d0ad8276a1 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 30661abd7a..439aa0ced0 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 776f0b3d8e..661072b448 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 591ce4b997..1091f38283 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -2462,7 +2462,7 @@ class history_visitor : public nano::block_visitor // 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 48466d012a..7a513e8b4a 100644 --- a/nano/qt/qt.cpp +++ b/nano/qt/qt.cpp @@ -555,7 +555,7 @@ class short_text_visitor : public nano::block_visitor 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 309290dc1d..206a550922 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/common.hpp b/nano/secure/common.hpp index fd28d30b13..e1639bd265 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -21,61 +21,6 @@ #include #include -namespace boost -{ -template <> -struct hash<::nano::uint256_union> -{ - size_t operator() (::nano::uint256_union const & value_a) const - { - return std::hash<::nano::uint256_union> () (value_a); - } -}; - -template <> -struct hash<::nano::block_hash> -{ - size_t operator() (::nano::block_hash const & value_a) const - { - return std::hash<::nano::block_hash> () (value_a); - } -}; - -template <> -struct hash<::nano::hash_or_account> -{ - size_t operator() (::nano::hash_or_account const & data_a) const - { - return std::hash<::nano::hash_or_account> () (data_a); - } -}; - -template <> -struct hash<::nano::public_key> -{ - size_t operator() (::nano::public_key const & value_a) const - { - return std::hash<::nano::public_key> () (value_a); - } -}; -template <> -struct hash<::nano::uint512_union> -{ - size_t operator() (::nano::uint512_union const & value_a) const - { - return std::hash<::nano::uint512_union> () (value_a); - } -}; -template <> -struct hash<::nano::qualified_root> -{ - size_t operator() (::nano::qualified_root const & value_a) const - { - return std::hash<::nano::qualified_root> () (value_a); - } -}; -} - namespace nano { /** diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index ec5aa666da..d2857974de 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1093,7 +1093,7 @@ class dependent_block_visitor : public nano::block_visitor } 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 (); } diff --git a/nano/secure/pending_info.hpp b/nano/secure/pending_info.hpp index 2d57df9ba2..c00e1cdb39 100644 --- a/nano/secure/pending_info.hpp +++ b/nano/secure/pending_info.hpp @@ -67,9 +67,9 @@ namespace std template <> struct hash<::nano::pending_key> { - size_t operator() (::nano::pending_key const & data_a) const + size_t operator() (::nano::pending_key const & value) const { - return hash<::nano::uint512_union>{}({ ::nano::uint256_union{ data_a.account.number () }, data_a.hash }); + return hash<::nano::uint512_union>{}({ ::nano::uint256_union{ value.account.number () }, value.hash }); } }; }