Merge pull request #4767 from pwojcikdev/spaceship-comparisons

Use spaceship comparisons
This commit is contained in:
Piotr Wójcik 2024-10-26 00:51:27 +02:00 committed by GitHub
commit 04ebc91fd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 679 additions and 571 deletions

View file

@ -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

View file

@ -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)

View file

@ -1,27 +1,192 @@
#include <nano/crypto_lib/random_pool.hpp>
#include <nano/lib/numbers.hpp>
#include <nano/secure/common.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
#include <boost/container_hash/hash.hpp>
#include <thread>
#include <unordered_set>
TEST (numbers, identity)
{
ASSERT_EQ (1, nano::uint128_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint256_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint512_union (1).number ().convert_to<uint8_t> ());
}
namespace
{
template <typename Union, typename Bound>
void assert_union_types ();
template <typename Type>
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 <typename Union, typename Bound>
void test_union_operator_less_than ();
template <typename Type>
void test_operator_less_than ()
{
using underlying_t = typename Type::underlying_type;
template <typename Num>
void check_operator_less_than (Num lhs, Num rhs);
// Small
check_operator_less_than (Type{ 123 }, Type{ 124 });
check_operator_less_than (Type{ 124 }, Type{ 125 });
template <typename Union, typename Bound>
void test_union_operator_greater_than ();
// Medium
check_operator_less_than (Type{ std::numeric_limits<uint16_t>::max () - 1 }, Type{ std::numeric_limits<uint16_t>::max () + 1 });
check_operator_less_than (Type{ std::numeric_limits<uint32_t>::max () - 12345678 }, Type{ std::numeric_limits<uint32_t>::max () - 123456 });
template <typename Num>
void check_operator_greater_than (Num lhs, Num rhs);
// Large
check_operator_less_than (Type{ std::numeric_limits<uint64_t>::max () - 555555555555 }, Type{ std::numeric_limits<uint64_t>::max () - 1 });
// Boundary values
check_operator_less_than (Type{ std::numeric_limits<underlying_t>::min () }, Type{ std::numeric_limits<underlying_t>::max () });
}
template <typename Type>
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 <typename Type>
void test_operator_greater_than ()
{
using underlying_t = typename Type::underlying_type;
// Small
check_operator_greater_than (Type{ 124 }, Type{ 123 });
check_operator_greater_than (Type{ 125 }, Type{ 124 });
// Medium
check_operator_greater_than (Type{ std::numeric_limits<uint16_t>::max () + 1 }, Type{ std::numeric_limits<uint16_t>::max () - 1 });
check_operator_greater_than (Type{ std::numeric_limits<uint32_t>::max () - 123456 }, Type{ std::numeric_limits<uint32_t>::max () - 12345678 });
// Large
check_operator_greater_than (Type{ std::numeric_limits<uint64_t>::max () - 1 }, Type{ std::numeric_limits<uint64_t>::max () - 555555555555 });
// Boundary values
check_operator_greater_than (Type{ std::numeric_limits<underlying_t>::max () }, Type{ std::numeric_limits<underlying_t>::min () });
}
template <typename Type>
void test_comparison ()
{
test_operator_less_than<Type> ();
test_operator_greater_than<Type> ();
}
}
TEST (numbers, comparison)
{
test_comparison<nano::uint128_union> ();
test_comparison<nano::uint256_union> ();
test_comparison<nano::uint512_union> ();
test_comparison<nano::block_hash> ();
test_comparison<nano::public_key> ();
test_comparison<nano::hash_or_account> ();
test_comparison<nano::link> ();
test_comparison<nano::root> ();
test_comparison<nano::raw_key> ();
test_comparison<nano::wallet_id> ();
test_comparison<nano::qualified_root> ();
}
namespace
{
template <typename Type, template <typename> class Hash>
void test_hashing ()
{
Hash<Type> 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<underlying_t>::min ();
constexpr auto max_val = std::numeric_limits<underlying_t>::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<underlying_t> 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<nano::uint128_union, std::hash> ();
test_hashing<nano::uint256_union, std::hash> ();
test_hashing<nano::uint512_union, std::hash> ();
test_hashing<nano::block_hash, std::hash> ();
test_hashing<nano::public_key, std::hash> ();
test_hashing<nano::hash_or_account, std::hash> ();
test_hashing<nano::link, std::hash> ();
test_hashing<nano::root, std::hash> ();
test_hashing<nano::raw_key, std::hash> ();
test_hashing<nano::wallet_id, std::hash> ();
test_hashing<nano::qualified_root, std::hash> ();
// Using boost::hash
test_hashing<nano::uint128_union, boost::hash> ();
test_hashing<nano::uint256_union, boost::hash> ();
test_hashing<nano::uint512_union, boost::hash> ();
test_hashing<nano::block_hash, boost::hash> ();
test_hashing<nano::public_key, boost::hash> ();
test_hashing<nano::hash_or_account, boost::hash> ();
test_hashing<nano::link, boost::hash> ();
test_hashing<nano::root, boost::hash> ();
test_hashing<nano::raw_key, boost::hash> ();
test_hashing<nano::wallet_id, boost::hash> ();
test_hashing<nano::qualified_root, boost::hash> ();
}
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<nano::uint128_union, nano::uint128_t> ();
}
TEST (uint128_union, operator_greater_than)
{
test_union_operator_greater_than<nano::uint128_union, nano::uint128_t> ();
}
struct test_punct : std::moneypunct<char>
{
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<uint8_t> ());
ASSERT_EQ (1, nano::uint256_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint512_union (1).number ().convert_to<uint8_t> ());
}
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<nano::uint256_union, nano::uint256_t> ();
}
TEST (uint64_t, parse)
{
uint64_t value0 (1);
@ -505,113 +648,3 @@ TEST (uint512_union, hash)
}
}
}
namespace
{
template <typename Union, typename Bound>
void assert_union_types ()
{
static_assert ((std::is_same<Union, nano::uint128_union>::value && std::is_same<Bound, nano::uint128_t>::value) || (std::is_same<Union, nano::uint256_union>::value && std::is_same<Bound, nano::uint256_t>::value) || (std::is_same<Union, nano::uint512_union>::value && std::is_same<Bound, nano::uint512_t>::value),
"Union type needs to be consistent with the lower/upper Bound type");
}
template <typename Union, typename Bound>
void test_union_operator_less_than ()
{
assert_union_types<Union, Bound> ();
// 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<uint16_t>::max () - 1), Union (std::numeric_limits<uint16_t>::max () + 1));
check_operator_less_than (Union (std::numeric_limits<uint32_t>::max () - 12345678), Union (std::numeric_limits<uint32_t>::max () - 123456));
// Large
check_operator_less_than (Union (std::numeric_limits<uint64_t>::max () - 555555555555), Union (std::numeric_limits<uint64_t>::max () - 1));
// Boundary values
check_operator_less_than (Union (std::numeric_limits<Bound>::min ()), Union (std::numeric_limits<Bound>::max ()));
}
template <typename Num>
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 <typename Union, typename Bound>
void test_union_operator_greater_than ()
{
assert_union_types<Union, Bound> ();
// 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<uint16_t>::max () + 1), Union (std::numeric_limits<uint16_t>::max () - 1));
check_operator_greater_than (Union (std::numeric_limits<uint32_t>::max () - 123456), Union (std::numeric_limits<uint32_t>::max () - 12345678));
// Large
check_operator_greater_than (Union (std::numeric_limits<uint64_t>::max () - 1), Union (std::numeric_limits<uint64_t>::max () - 555555555555));
// Boundary values
check_operator_greater_than (Union (std::numeric_limits<Bound>::max ()), Union (std::numeric_limits<Bound>::min ()));
}
template <typename Num>
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<std::thread> 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<uint64_t> (std::numeric_limits<uint32_t>::max ()) + 1;
uint64_t max = std::numeric_limits<uint64_t>::max ();
auto big_random = nano::random_pool::generate_word64 (min, max);
ASSERT_GE (big_random, min);
}

View file

@ -0,0 +1,48 @@
#include <nano/crypto_lib/random_pool.hpp>
#include <nano/lib/numbers.hpp>
#include <gtest/gtest.h>
#include <thread>
TEST (random_pool, multithreading)
{
std::vector<std::thread> 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<uint64_t> (std::numeric_limits<uint32_t>::max ()) + 1;
uint64_t max = std::numeric_limits<uint64_t>::max ();
auto big_random = nano::random_pool::generate_word64 (min, max);
ASSERT_GE (big_random, min);
}

View file

@ -609,7 +609,7 @@ std::optional<nano::account> 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::block_hash> 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::block_hash> 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;
}

View file

@ -33,7 +33,7 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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;

View file

@ -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<nano::link const &> (*this);
}
nano::public_key::operator nano::root const & () const
{
return reinterpret_cast<nano::root const &> (*this);
}
nano::public_key::operator nano::hash_or_account const & () const
{
return reinterpret_cast<nano::hash_or_account const &> (*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<nano::link const &> (*this);
}
nano::block_hash::operator nano::root const & () const
{
return reinterpret_cast<nano::root const &> (*this);
}
nano::block_hash::operator nano::hash_or_account const & () const
{
return reinterpret_cast<nano::hash_or_account const &> (*this);
}

View file

@ -4,6 +4,8 @@
#include <boost/multiprecision/cpp_int.hpp>
#include <array>
#include <compare>
#include <limits>
#include <ostream>
#include <fmt/ostream.h>
@ -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<uint8_t, 16> bytes;
@ -52,6 +79,24 @@ public:
std::array<uint32_t, 4> dwords;
std::array<uint64_t, 2> 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<uint128_union>::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;
std::string to_string () const;
nano::uint256_t number () 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;
public:
union
{
std::array<uint8_t, 32> bytes;
@ -100,33 +177,46 @@ public:
std::array<uint64_t, 4> qwords;
std::array<uint128_union, 2> owords;
};
};
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<uint256_union>::value, "uint256_union should be noexcept MoveConstructible");
class link;
class root;
class hash_or_account;
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;
}
};
static_assert (std::is_nothrow_move_constructible<uint256_union>::value, "uint256_union should be noexcept MoveConstructible");
// 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_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<uint8_t, 32> bytes;
@ -187,6 +300,36 @@ 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;
}
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 @@ public:
~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<uint8_t, 64> bytes;
@ -236,6 +432,24 @@ public:
std::array<uint64_t, 8> qwords;
std::array<uint256_union, 2> 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<uint512_union>::value, "uint512_union should be noexcept MoveConstructible");
@ -248,15 +462,19 @@ public:
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<nano::root const &> (uint256s[0]);
return nano::root{ uint256s[0] };
}
nano::block_hash const & previous () const
nano::block_hash previous () const
{
return reinterpret_cast<nano::block_hash const &> (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,92 +516,91 @@ namespace difficulty
namespace std
{
template <>
struct hash<::nano::uint256_union>
struct hash<::nano::uint128_union>
{
size_t operator() (::nano::uint256_union const & data_a) const
size_t operator() (::nano::uint128_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];
}
};
template <>
struct hash<::nano::account>
struct hash<::nano::uint256_union>
{
size_t operator() (::nano::account const & data_a) const
size_t operator() (::nano::uint256_union const & value) const noexcept
{
return hash<::nano::uint256_union> () (data_a);
return value.qwords[0] + value.qwords[1] + value.qwords[2] + value.qwords[3];
}
};
template <>
struct hash<::nano::public_key>
{
size_t operator() (::nano::public_key const & value) const noexcept
{
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 ());
}
};
template <>
struct hash<::nano::raw_key>
{
size_t operator() (::nano::raw_key const & data_a) const
{
return hash<::nano::uint256_union> () (data_a);
return hash<::nano::block_hash>{}(value.as_block_hash ());
}
};
template <>
struct hash<::nano::root>
{
size_t operator() (::nano::root 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::link>
{
size_t operator() (::nano::link const & value) const noexcept
{
return hash<::nano::hash_or_account>{}(value);
}
};
template <>
struct hash<::nano::raw_key>
{
size_t operator() (::nano::raw_key const & value) const noexcept
{
return hash<::nano::uint256_union>{}(value);
}
};
template <>
struct hash<::nano::wallet_id>
{
size_t operator() (::nano::wallet_id const & data_a) const
size_t operator() (::nano::wallet_id const & value) const noexcept
{
return hash<::nano::uint256_union> () (data_a);
}
};
template <>
struct hash<::nano::uint256_t>
{
size_t operator() (::nano::uint256_t const & number_a) const
{
return number_a.convert_to<size_t> ();
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);
}
};
template <>
struct equal_to<std::reference_wrapper<::nano::block_hash const>>
{
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 ();
return hash<::nano::uint512_union>{}(value);
}
};
}
@ -390,20 +608,91 @@ struct equal_to<std::reference_wrapper<::nano::block_hash const>>
namespace boost
{
template <>
struct hash<std::reference_wrapper<::nano::block_hash const>>
struct hash<::nano::uint128_union>
{
size_t operator() (std::reference_wrapper<::nano::block_hash const> const & hash_a) const
size_t operator() (::nano::uint128_union const & value) const noexcept
{
std::hash<::nano::block_hash> hash;
return hash (hash_a);
return std::hash<::nano::uint128_union> () (value);
}
};
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<::nano::public_key>
{
size_t operator() (::nano::public_key const & value) const noexcept
{
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<nano::uint512_union> : fmt::ostream_formatter
{
};
template <>
struct fmt::formatter<nano::hash_or_account> : fmt::ostream_formatter
{
};
template <>
struct fmt::formatter<nano::block_hash> : fmt::formatter<nano::uint256_union>
{

View file

@ -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<account_head_tag> ().find (head_512));
if (existing == cache.get<account_head_tag> ().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<nano::mutex> 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<account_head_tag> ().find (head_512));
if (existing != cache.get<account_head_tag> ().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<nano::mutex> 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<account_head_tag> ().erase (head_512);
}

View file

@ -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 ());

View file

@ -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<nano::uint256_t>::max ()) ? start_account_a : start_account_a.number () + 1;
request.start = (start_account_a.is_zero () || start_account_a.number () == std::numeric_limits<nano::uint256_t>::max ()) ? start_account_a.number () : start_account_a.number () + 1;
request.age = frontiers_age_a;
request.count = count_a;
current = start_account_a;

View file

@ -293,7 +293,7 @@ bool nano::bootstrap_attempt_lazy::process_block_lazy (std::shared_ptr<nano::blo
if (!lazy_blocks_processed (hash))
{
// Search for new dependencies
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 ())
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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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 ());

View file

@ -2628,7 +2628,7 @@ TEST (rpc, wallet_frontiers)
frontiers.push_back (nano::account (i->second.get<std::string> ("")));
}
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)

View file

@ -21,61 +21,6 @@
#include <array>
#include <unordered_map>
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
{
/**

View file

@ -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 ();
}

View file

@ -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 });
}
};
}