The method `ledger::hash_root_random()` required the block count to fit into a uint32_t. This limit is too small to be future-proof. This commit increases the limit to UINT64_MAX, so that it matches the other places where block count is a uint64_t.
628 lines
21 KiB
C++
628 lines
21 KiB
C++
#include <nano/crypto_lib/random_pool.hpp>
|
|
#include <nano/secure/common.hpp>
|
|
#include <nano/test_common/testutil.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <thread>
|
|
|
|
namespace
|
|
{
|
|
template <typename Union, typename Bound>
|
|
void assert_union_types ();
|
|
|
|
template <typename Union, typename Bound>
|
|
void test_union_operator_less_than ();
|
|
|
|
template <typename Num>
|
|
void check_operator_less_than (Num lhs, Num rhs);
|
|
|
|
template <typename Union, typename Bound>
|
|
void test_union_operator_greater_than ();
|
|
|
|
template <typename Num>
|
|
void check_operator_greater_than (Num lhs, Num rhs);
|
|
}
|
|
|
|
TEST (uint128_union, decode_dec)
|
|
{
|
|
nano::uint128_union value;
|
|
std::string text ("16");
|
|
ASSERT_FALSE (value.decode_dec (text));
|
|
ASSERT_EQ (16, value.bytes[15]);
|
|
}
|
|
|
|
TEST (uint128_union, decode_dec_negative)
|
|
{
|
|
nano::uint128_union value;
|
|
std::string text ("-1");
|
|
auto error (value.decode_dec (text));
|
|
ASSERT_TRUE (error);
|
|
}
|
|
|
|
TEST (uint128_union, decode_dec_zero)
|
|
{
|
|
nano::uint128_union value;
|
|
std::string text ("0");
|
|
ASSERT_FALSE (value.decode_dec (text));
|
|
ASSERT_TRUE (value.is_zero ());
|
|
}
|
|
|
|
TEST (uint128_union, decode_dec_leading_zero)
|
|
{
|
|
nano::uint128_union value;
|
|
std::string text ("010");
|
|
auto error (value.decode_dec (text));
|
|
ASSERT_TRUE (error);
|
|
}
|
|
|
|
TEST (uint128_union, decode_dec_overflow)
|
|
{
|
|
nano::uint128_union value;
|
|
std::string text ("340282366920938463463374607431768211456");
|
|
auto error (value.decode_dec (text));
|
|
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
|
|
{
|
|
return { { value, none, none, none } };
|
|
}
|
|
int do_frac_digits () const
|
|
{
|
|
return 0;
|
|
}
|
|
char_type do_decimal_point () const
|
|
{
|
|
return '+';
|
|
}
|
|
char_type do_thousands_sep () const
|
|
{
|
|
return '-';
|
|
}
|
|
string_type do_grouping () const
|
|
{
|
|
return "\3\4";
|
|
}
|
|
};
|
|
|
|
TEST (uint128_union, balance_format)
|
|
{
|
|
ASSERT_EQ ("0", nano::amount (nano::uint128_t ("0")).format_balance (nano::Mxrb_ratio, 0, false));
|
|
ASSERT_EQ ("0", nano::amount (nano::uint128_t ("0")).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("340,282,366", nano::amount (nano::uint128_t ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")).format_balance (nano::Mxrb_ratio, 0, true));
|
|
ASSERT_EQ ("340,282,366.920938463463374607431768211455", nano::amount (nano::uint128_t ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")).format_balance (nano::Mxrb_ratio, 64, true));
|
|
ASSERT_EQ ("340,282,366,920,938,463,463,374,607,431,768,211,455", nano::amount (nano::uint128_t ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")).format_balance (1, 4, true));
|
|
ASSERT_EQ ("340,282,366", nano::amount (nano::uint128_t ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")).format_balance (nano::Mxrb_ratio, 0, true));
|
|
ASSERT_EQ ("340,282,366.920938463463374607431768211454", nano::amount (nano::uint128_t ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")).format_balance (nano::Mxrb_ratio, 64, true));
|
|
ASSERT_EQ ("340282366920938463463374607431768211454", nano::amount (nano::uint128_t ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")).format_balance (1, 4, false));
|
|
ASSERT_EQ ("170,141,183", nano::amount (nano::uint128_t ("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")).format_balance (nano::Mxrb_ratio, 0, true));
|
|
ASSERT_EQ ("170,141,183.460469231731687303715884105726", nano::amount (nano::uint128_t ("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")).format_balance (nano::Mxrb_ratio, 64, true));
|
|
ASSERT_EQ ("170141183460469231731687303715884105726", nano::amount (nano::uint128_t ("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")).format_balance (1, 4, false));
|
|
ASSERT_EQ ("1", nano::amount (nano::uint128_t ("1000000000000000000000000000000")).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("1.2", nano::amount (nano::uint128_t ("1200000000000000000000000000000")).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("1.23", nano::amount (nano::uint128_t ("1230000000000000000000000000000")).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("1.2", nano::amount (nano::uint128_t ("1230000000000000000000000000000")).format_balance (nano::Mxrb_ratio, 1, true));
|
|
ASSERT_EQ ("1", nano::amount (nano::uint128_t ("1230000000000000000000000000000")).format_balance (nano::Mxrb_ratio, 0, true));
|
|
ASSERT_EQ ("< 0.01", nano::amount (nano::xrb_ratio * 10).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("< 0.1", nano::amount (nano::xrb_ratio * 10).format_balance (nano::Mxrb_ratio, 1, true));
|
|
ASSERT_EQ ("< 1", nano::amount (nano::xrb_ratio * 10).format_balance (nano::Mxrb_ratio, 0, true));
|
|
ASSERT_EQ ("< 0.01", nano::amount (nano::xrb_ratio * 9999).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("0.01", nano::amount (nano::xrb_ratio * 10000).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("123456789", nano::amount (nano::Mxrb_ratio * 123456789).format_balance (nano::Mxrb_ratio, 2, false));
|
|
ASSERT_EQ ("123,456,789", nano::amount (nano::Mxrb_ratio * 123456789).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("123,456,789.12", nano::amount (nano::Mxrb_ratio * 123456789 + nano::kxrb_ratio * 123).format_balance (nano::Mxrb_ratio, 2, true));
|
|
ASSERT_EQ ("12-3456-789+123", nano::amount (nano::Mxrb_ratio * 123456789 + nano::kxrb_ratio * 123).format_balance (nano::Mxrb_ratio, 4, true, std::locale (std::cout.getloc (), new test_punct)));
|
|
}
|
|
|
|
TEST (uint128_union, decode_decimal)
|
|
{
|
|
nano::amount amount;
|
|
ASSERT_FALSE (amount.decode_dec ("340282366920938463463374607431768211455", nano::raw_ratio));
|
|
ASSERT_EQ (std::numeric_limits<nano::uint128_t>::max (), amount.number ());
|
|
ASSERT_TRUE (amount.decode_dec ("340282366920938463463374607431768211456", nano::raw_ratio));
|
|
ASSERT_TRUE (amount.decode_dec ("340282366920938463463374607431768211455.1", nano::raw_ratio));
|
|
ASSERT_TRUE (amount.decode_dec ("0.1", nano::raw_ratio));
|
|
ASSERT_FALSE (amount.decode_dec ("1", nano::raw_ratio));
|
|
ASSERT_EQ (1, amount.number ());
|
|
ASSERT_FALSE (amount.decode_dec ("340282366.920938463463374607431768211454", nano::Mxrb_ratio));
|
|
ASSERT_EQ (std::numeric_limits<nano::uint128_t>::max () - 1, amount.number ());
|
|
ASSERT_TRUE (amount.decode_dec ("340282366.920938463463374607431768211456", nano::Mxrb_ratio));
|
|
ASSERT_TRUE (amount.decode_dec ("340282367", nano::Mxrb_ratio));
|
|
ASSERT_FALSE (amount.decode_dec ("0.000000000000000000000001", nano::Mxrb_ratio));
|
|
ASSERT_EQ (1000000, amount.number ());
|
|
ASSERT_FALSE (amount.decode_dec ("0.000000000000000000000000000001", nano::Mxrb_ratio));
|
|
ASSERT_EQ (1, amount.number ());
|
|
ASSERT_TRUE (amount.decode_dec ("0.0000000000000000000000000000001", nano::Mxrb_ratio));
|
|
ASSERT_TRUE (amount.decode_dec (".1", nano::Mxrb_ratio));
|
|
ASSERT_TRUE (amount.decode_dec ("0.", nano::Mxrb_ratio));
|
|
ASSERT_FALSE (amount.decode_dec ("9.999999999999999999999999999999", nano::Mxrb_ratio));
|
|
ASSERT_EQ (nano::uint128_t ("9999999999999999999999999999999"), amount.number ());
|
|
ASSERT_FALSE (amount.decode_dec ("170141183460469.231731687303715884105727", nano::xrb_ratio));
|
|
ASSERT_EQ (nano::uint128_t ("170141183460469231731687303715884105727"), amount.number ());
|
|
ASSERT_FALSE (amount.decode_dec ("2.000000000000000000000002", nano::xrb_ratio));
|
|
ASSERT_EQ (2 * nano::xrb_ratio + 2, amount.number ());
|
|
ASSERT_FALSE (amount.decode_dec ("2", nano::xrb_ratio));
|
|
ASSERT_EQ (2 * nano::xrb_ratio, amount.number ());
|
|
ASSERT_FALSE (amount.decode_dec ("1230", nano::Gxrb_ratio));
|
|
ASSERT_EQ (1230 * nano::Gxrb_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;
|
|
nano::raw_key secret_key;
|
|
secret_key.clear ();
|
|
nano::uint256_union encrypted;
|
|
encrypted.encrypt (key1.prv, secret_key, key1.pub.owords[0]);
|
|
nano::raw_key key4;
|
|
key4.decrypt (encrypted, secret_key, key1.pub.owords[0]);
|
|
ASSERT_EQ (key1.prv, key4);
|
|
auto pub (nano::pub_key (key4));
|
|
ASSERT_EQ (key1.pub, pub);
|
|
}
|
|
|
|
TEST (uint256_union, encryption)
|
|
{
|
|
nano::raw_key key;
|
|
key.clear ();
|
|
nano::raw_key number1;
|
|
number1 = 1;
|
|
nano::uint256_union encrypted1;
|
|
encrypted1.encrypt (number1, key, key.owords[0]);
|
|
nano::uint256_union encrypted2;
|
|
encrypted2.encrypt (number1, key, key.owords[0]);
|
|
ASSERT_EQ (encrypted1, encrypted2);
|
|
nano::raw_key number2;
|
|
number2.decrypt (encrypted1, key, key.owords[0]);
|
|
ASSERT_EQ (number1, number2);
|
|
}
|
|
|
|
TEST (uint256_union, decode_empty)
|
|
{
|
|
std::string text;
|
|
nano::uint256_union val;
|
|
ASSERT_TRUE (val.decode_hex (text));
|
|
}
|
|
|
|
TEST (uint256_union, parse_zero)
|
|
{
|
|
nano::uint256_union input (nano::uint256_t (0));
|
|
std::string text;
|
|
input.encode_hex (text);
|
|
nano::uint256_union output;
|
|
auto error (output.decode_hex (text));
|
|
ASSERT_FALSE (error);
|
|
ASSERT_EQ (input, output);
|
|
ASSERT_TRUE (output.number ().is_zero ());
|
|
}
|
|
|
|
TEST (uint256_union, parse_zero_short)
|
|
{
|
|
std::string text ("0");
|
|
nano::uint256_union output;
|
|
auto error (output.decode_hex (text));
|
|
ASSERT_FALSE (error);
|
|
ASSERT_TRUE (output.number ().is_zero ());
|
|
}
|
|
|
|
TEST (uint256_union, parse_one)
|
|
{
|
|
nano::uint256_union input (nano::uint256_t (1));
|
|
std::string text;
|
|
input.encode_hex (text);
|
|
nano::uint256_union output;
|
|
auto error (output.decode_hex (text));
|
|
ASSERT_FALSE (error);
|
|
ASSERT_EQ (input, output);
|
|
ASSERT_EQ (1, output.number ());
|
|
}
|
|
|
|
TEST (uint256_union, parse_error_symbol)
|
|
{
|
|
nano::uint256_union input (nano::uint256_t (1000));
|
|
std::string text;
|
|
input.encode_hex (text);
|
|
text[5] = '!';
|
|
nano::uint256_union output;
|
|
auto error (output.decode_hex (text));
|
|
ASSERT_TRUE (error);
|
|
}
|
|
|
|
TEST (uint256_union, max_hex)
|
|
{
|
|
nano::uint256_union input (std::numeric_limits<nano::uint256_t>::max ());
|
|
std::string text;
|
|
input.encode_hex (text);
|
|
nano::uint256_union output;
|
|
auto error (output.decode_hex (text));
|
|
ASSERT_FALSE (error);
|
|
ASSERT_EQ (input, output);
|
|
ASSERT_EQ (nano::uint256_t ("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), output.number ());
|
|
}
|
|
|
|
TEST (uint256_union, decode_dec)
|
|
{
|
|
nano::uint256_union value;
|
|
std::string text ("16");
|
|
ASSERT_FALSE (value.decode_dec (text));
|
|
ASSERT_EQ (16, value.bytes[31]);
|
|
}
|
|
|
|
TEST (uint256_union, max_dec)
|
|
{
|
|
nano::uint256_union input (std::numeric_limits<nano::uint256_t>::max ());
|
|
std::string text;
|
|
input.encode_dec (text);
|
|
nano::uint256_union output;
|
|
auto error (output.decode_dec (text));
|
|
ASSERT_FALSE (error);
|
|
ASSERT_EQ (input, output);
|
|
ASSERT_EQ (nano::uint256_t ("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), output.number ());
|
|
}
|
|
|
|
TEST (uint256_union, decode_dec_negative)
|
|
{
|
|
nano::uint256_union value;
|
|
std::string text ("-1");
|
|
auto error (value.decode_dec (text));
|
|
ASSERT_TRUE (error);
|
|
}
|
|
|
|
TEST (uint256_union, decode_dec_zero)
|
|
{
|
|
nano::uint256_union value;
|
|
std::string text ("0");
|
|
ASSERT_FALSE (value.decode_dec (text));
|
|
ASSERT_TRUE (value.is_zero ());
|
|
}
|
|
|
|
TEST (uint256_union, decode_dec_leading_zero)
|
|
{
|
|
nano::uint256_union value;
|
|
std::string text ("010");
|
|
auto error (value.decode_dec (text));
|
|
ASSERT_TRUE (error);
|
|
}
|
|
|
|
TEST (uint256_union, parse_error_overflow)
|
|
{
|
|
nano::uint256_union input (std::numeric_limits<nano::uint256_t>::max ());
|
|
std::string text;
|
|
input.encode_hex (text);
|
|
text.push_back (0);
|
|
nano::uint256_union output;
|
|
auto error (output.decode_hex (text));
|
|
ASSERT_TRUE (error);
|
|
}
|
|
|
|
TEST (uint256_union, big_endian_union_constructor)
|
|
{
|
|
nano::uint256_t value1 (1);
|
|
nano::uint256_union bytes1 (value1);
|
|
ASSERT_EQ (1, bytes1.bytes[31]);
|
|
nano::uint512_t value2 (1);
|
|
nano::uint512_union bytes2 (value2);
|
|
ASSERT_EQ (1, bytes2.bytes[63]);
|
|
}
|
|
|
|
TEST (uint256_union, big_endian_union_function)
|
|
{
|
|
nano::uint256_union bytes1 ("FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210");
|
|
ASSERT_EQ (0xfe, bytes1.bytes[0x00]);
|
|
ASSERT_EQ (0xdc, bytes1.bytes[0x01]);
|
|
ASSERT_EQ (0xba, bytes1.bytes[0x02]);
|
|
ASSERT_EQ (0x98, bytes1.bytes[0x03]);
|
|
ASSERT_EQ (0x76, bytes1.bytes[0x04]);
|
|
ASSERT_EQ (0x54, bytes1.bytes[0x05]);
|
|
ASSERT_EQ (0x32, bytes1.bytes[0x06]);
|
|
ASSERT_EQ (0x10, bytes1.bytes[0x07]);
|
|
ASSERT_EQ (0xfe, bytes1.bytes[0x08]);
|
|
ASSERT_EQ (0xdc, bytes1.bytes[0x09]);
|
|
ASSERT_EQ (0xba, bytes1.bytes[0x0a]);
|
|
ASSERT_EQ (0x98, bytes1.bytes[0x0b]);
|
|
ASSERT_EQ (0x76, bytes1.bytes[0x0c]);
|
|
ASSERT_EQ (0x54, bytes1.bytes[0x0d]);
|
|
ASSERT_EQ (0x32, bytes1.bytes[0x0e]);
|
|
ASSERT_EQ (0x10, bytes1.bytes[0x0f]);
|
|
ASSERT_EQ (0xfe, bytes1.bytes[0x10]);
|
|
ASSERT_EQ (0xdc, bytes1.bytes[0x11]);
|
|
ASSERT_EQ (0xba, bytes1.bytes[0x12]);
|
|
ASSERT_EQ (0x98, bytes1.bytes[0x13]);
|
|
ASSERT_EQ (0x76, bytes1.bytes[0x14]);
|
|
ASSERT_EQ (0x54, bytes1.bytes[0x15]);
|
|
ASSERT_EQ (0x32, bytes1.bytes[0x16]);
|
|
ASSERT_EQ (0x10, bytes1.bytes[0x17]);
|
|
ASSERT_EQ (0xfe, bytes1.bytes[0x18]);
|
|
ASSERT_EQ (0xdc, bytes1.bytes[0x19]);
|
|
ASSERT_EQ (0xba, bytes1.bytes[0x1a]);
|
|
ASSERT_EQ (0x98, bytes1.bytes[0x1b]);
|
|
ASSERT_EQ (0x76, bytes1.bytes[0x1c]);
|
|
ASSERT_EQ (0x54, bytes1.bytes[0x1d]);
|
|
ASSERT_EQ (0x32, bytes1.bytes[0x1e]);
|
|
ASSERT_EQ (0x10, bytes1.bytes[0x1f]);
|
|
ASSERT_EQ ("FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210", bytes1.to_string ());
|
|
ASSERT_EQ (nano::uint256_t ("0xFEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210"), bytes1.number ());
|
|
nano::uint512_union bytes2;
|
|
bytes2.clear ();
|
|
bytes2.bytes[63] = 1;
|
|
ASSERT_EQ (nano::uint512_t (1), bytes2.number ());
|
|
}
|
|
|
|
TEST (uint256_union, decode_nano_variant)
|
|
{
|
|
nano::account key;
|
|
ASSERT_FALSE (key.decode_account ("xrb_1111111111111111111111111111111111111111111111111111hifc8npp"));
|
|
ASSERT_FALSE (key.decode_account ("nano_1111111111111111111111111111111111111111111111111111hifc8npp"));
|
|
}
|
|
|
|
/**
|
|
* It used to be the case that when the address was wrong only in the checksum part
|
|
* then the decode_account would return error and it would also write the address with
|
|
* fixed checksum into 'key', which is not desirable.
|
|
*/
|
|
TEST (uint256_union, key_is_not_updated_on_checksum_error)
|
|
{
|
|
nano::account key;
|
|
ASSERT_EQ (key, 0);
|
|
bool result = key.decode_account ("nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpiij4txtd1");
|
|
ASSERT_EQ (key, 0);
|
|
ASSERT_TRUE (result);
|
|
}
|
|
|
|
TEST (uint256_union, account_transcode)
|
|
{
|
|
nano::account value;
|
|
auto text (nano::dev::genesis_key.pub.to_account ());
|
|
ASSERT_FALSE (value.decode_account (text));
|
|
ASSERT_EQ (nano::dev::genesis_key.pub, value);
|
|
|
|
/*
|
|
* Handle different offsets for the underscore separator
|
|
* for "xrb_" prefixed and "nano_" prefixed accounts
|
|
*/
|
|
unsigned offset = (text.front () == 'x') ? 3 : 4;
|
|
ASSERT_EQ ('_', text[offset]);
|
|
text[offset] = '-';
|
|
nano::account value2;
|
|
ASSERT_FALSE (value2.decode_account (text));
|
|
ASSERT_EQ (value, value2);
|
|
}
|
|
|
|
TEST (uint256_union, account_encode_lex)
|
|
{
|
|
nano::account min ("0000000000000000000000000000000000000000000000000000000000000000");
|
|
nano::account max ("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
auto min_text (min.to_account ());
|
|
auto max_text (max.to_account ());
|
|
|
|
/*
|
|
* Handle different lengths for "xrb_" prefixed and "nano_" prefixed accounts
|
|
*/
|
|
unsigned length = (min_text.front () == 'x') ? 64 : 65;
|
|
ASSERT_EQ (length, min_text.size ());
|
|
ASSERT_EQ (length, max_text.size ());
|
|
|
|
auto previous (min_text);
|
|
for (auto i (1); i != 1000; ++i)
|
|
{
|
|
nano::account number (min.number () + i);
|
|
auto text (number.to_account ());
|
|
nano::account output;
|
|
output.decode_account (text);
|
|
ASSERT_EQ (number, output);
|
|
ASSERT_GT (text, previous);
|
|
previous = text;
|
|
}
|
|
for (auto i (1); i != 1000; ++i)
|
|
{
|
|
nano::keypair key;
|
|
auto text (key.pub.to_account ());
|
|
nano::account output;
|
|
output.decode_account (text);
|
|
ASSERT_EQ (key.pub, output);
|
|
}
|
|
}
|
|
|
|
TEST (uint256_union, bounds)
|
|
{
|
|
nano::account key;
|
|
std::string bad1 (64, '\x000');
|
|
bad1[0] = 'x';
|
|
bad1[1] = 'r';
|
|
bad1[2] = 'b';
|
|
bad1[3] = '-';
|
|
ASSERT_TRUE (key.decode_account (bad1));
|
|
std::string bad2 (64, '\x0ff');
|
|
bad2[0] = 'x';
|
|
bad2[1] = 'r';
|
|
bad2[2] = 'b';
|
|
bad2[3] = '-';
|
|
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);
|
|
ASSERT_FALSE (nano::from_string_hex ("0", value0));
|
|
ASSERT_EQ (0, value0);
|
|
uint64_t value1 (1);
|
|
ASSERT_FALSE (nano::from_string_hex ("ffffffffffffffff", value1));
|
|
ASSERT_EQ (0xffffffffffffffffULL, value1);
|
|
uint64_t value2 (1);
|
|
ASSERT_TRUE (nano::from_string_hex ("g", value2));
|
|
uint64_t value3 (1);
|
|
ASSERT_TRUE (nano::from_string_hex ("ffffffffffffffff0", value3));
|
|
uint64_t value4 (1);
|
|
ASSERT_TRUE (nano::from_string_hex ("", value4));
|
|
}
|
|
|
|
TEST (uint256_union, hash)
|
|
{
|
|
ASSERT_EQ (4, nano::uint256_union{}.qwords.size ());
|
|
std::hash<nano::uint256_union> h{};
|
|
for (size_t i (0), n (nano::uint256_union{}.bytes.size ()); i < n; ++i)
|
|
{
|
|
nano::uint256_union x1{ 0 };
|
|
nano::uint256_union x2{ 0 };
|
|
x2.bytes[i] = 1;
|
|
ASSERT_NE (h (x1), h (x2));
|
|
}
|
|
}
|
|
|
|
TEST (uint512_union, hash)
|
|
{
|
|
ASSERT_EQ (2, nano::uint512_union{}.uint256s.size ());
|
|
std::hash<nano::uint512_union> h{};
|
|
for (size_t i (0), n (nano::uint512_union{}.bytes.size ()); i < n; ++i)
|
|
{
|
|
nano::uint512_union x1{ 0 };
|
|
nano::uint512_union x2{ 0 };
|
|
x2.bytes[i] = 1;
|
|
ASSERT_NE (h (x1), h (x2));
|
|
}
|
|
for (auto part (0); part < nano::uint512_union{}.uint256s.size (); ++part)
|
|
{
|
|
for (size_t i (0), n (nano::uint512_union{}.uint256s[part].bytes.size ()); i < n; ++i)
|
|
{
|
|
nano::uint512_union x1{ 0 };
|
|
nano::uint512_union x2{ 0 };
|
|
x2.uint256s[part].bytes[i] = 1;
|
|
ASSERT_NE (h (x1), h (x2));
|
|
}
|
|
}
|
|
}
|
|
|
|
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_TRUE (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_TRUE (big_random >= min);
|
|
}
|