dncurrency/nano/lib/numbers.hpp
theohax 9bb89ab323
Improvements in const correctness and 'const' positioning (#3510)
* Improve const correctness and adhere to 'const' specifier positioning style

Co-authored-by: Mario Ortiz Manero <marioortizmanero@gmail.com>
2021-10-21 16:20:09 +03:00

367 lines
10 KiB
C++

#pragma once
#include <boost/multiprecision/cpp_int.hpp>
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 Gxrb_ratio = nano::uint128_t ("1000000000000000000000000000000000"); // 10^33
nano::uint128_t const Mxrb_ratio = nano::uint128_t ("1000000000000000000000000000000"); // 10^30
nano::uint128_t const kxrb_ratio = nano::uint128_t ("1000000000000000000000000000"); // 10^27
nano::uint128_t const xrb_ratio = nano::uint128_t ("1000000000000000000000000"); // 10^24
nano::uint128_t const raw_ratio = nano::uint128_t ("1"); // 10^0
class uint128_union
{
public:
uint128_union () = default;
/**
* 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;
void encode_hex (std::string &) const;
bool decode_hex (std::string const &);
void encode_dec (std::string &) const;
bool decode_dec (std::string const &, bool = false);
bool decode_dec (std::string const &, nano::uint128_t);
std::string format_balance (nano::uint128_t scale, int precision, bool group_digits) const;
std::string format_balance (nano::uint128_t scale, int precision, bool group_digits, std::locale const & locale) const;
nano::uint128_t number () const;
void clear ();
bool is_zero () const;
std::string to_string () const;
std::string to_string_dec () const;
union
{
std::array<uint8_t, 16> bytes;
std::array<char, 16> chars;
std::array<uint32_t, 4> dwords;
std::array<uint64_t, 2> qwords;
};
};
static_assert (std::is_nothrow_move_constructible<uint128_union>::value, "uint128_union should be noexcept MoveConstructible");
// Balances are 128 bit.
class amount : public uint128_union
{
public:
using uint128_union::uint128_union;
};
class raw_key;
class uint256_union
{
public:
uint256_union () = default;
/**
* 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;
bool operator== (nano::uint256_union const &) const;
bool operator!= (nano::uint256_union const &) const;
bool operator< (nano::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;
union
{
std::array<uint8_t, 32> bytes;
std::array<char, 32> chars;
std::array<uint32_t, 8> dwords;
std::array<uint64_t, 4> qwords;
std::array<uint128_union, 2> owords;
};
};
static_assert (std::is_nothrow_move_constructible<uint256_union>::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;
};
class public_key final : public uint256_union
{
public:
using uint256_union::uint256_union;
public_key ();
static const public_key & null ();
std::string to_node_id () const;
bool decode_node_id (std::string const & source_a);
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;
using uint256_union::operator==;
using uint256_union::operator!=;
};
class wallet_id : public uint256_union
{
using uint256_union::uint256_union;
};
// These are synonymous
using account = public_key;
class hash_or_account
{
public:
hash_or_account ();
hash_or_account (uint64_t value_a);
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;
union
{
std::array<uint8_t, 32> bytes;
nano::uint256_union raw; // This can be used when you don't want to explicitly mention either of the types
nano::account account;
nano::block_hash hash;
};
};
// A link can either be a destination account or source hash
class link final : public hash_or_account
{
public:
using hash_or_account::hash_or_account;
};
// A root can either be an open block hash or a previous hash
class root final : public hash_or_account
{
public:
using hash_or_account::hash_or_account;
nano::block_hash const & previous () const;
};
// The seed or private key
class raw_key final : public uint256_union
{
public:
using uint256_union::uint256_union;
~raw_key ();
void decrypt (nano::uint256_union const &, nano::raw_key const &, uint128_union const &);
};
class uint512_union
{
public:
uint512_union () = default;
uint512_union (nano::uint256_union const &, nano::uint256_union const &);
uint512_union (nano::uint512_t const &);
bool operator== (nano::uint512_union const &) const;
bool operator!= (nano::uint512_union const &) const;
nano::uint512_union & operator^= (nano::uint512_union const &);
void encode_hex (std::string &) const;
bool decode_hex (std::string const &);
void clear ();
bool is_zero () const;
nano::uint512_t number () const;
std::string to_string () const;
union
{
std::array<uint8_t, 64> bytes;
std::array<uint32_t, 16> dwords;
std::array<uint64_t, 8> qwords;
std::array<uint256_union, 2> uint256s;
};
};
static_assert (std::is_nothrow_move_constructible<uint512_union>::value, "uint512_union should be noexcept MoveConstructible");
class signature : public uint512_union
{
public:
using uint512_union::uint512_union;
};
class qualified_root : public uint512_union
{
public:
using uint512_union::uint512_union;
nano::root const & root () const
{
return reinterpret_cast<nano::root const &> (uint256s[0]);
}
nano::block_hash const & previous () const
{
return reinterpret_cast<nano::block_hash const &> (uint256s[1]);
}
};
nano::signature sign_message (nano::raw_key const &, nano::public_key const &, nano::uint256_union const &);
nano::signature sign_message (nano::raw_key const &, nano::public_key const &, uint8_t const *, size_t);
bool validate_message (nano::public_key const &, nano::uint256_union const &, nano::signature const &);
bool validate_message (nano::public_key const &, uint8_t const *, size_t, nano::signature const &);
bool validate_message_batch (unsigned char const **, size_t *, unsigned char const **, unsigned char const **, size_t, int *);
nano::raw_key deterministic_key (nano::raw_key const &, uint32_t);
nano::public_key pub_key (nano::raw_key const &);
/* Conversion methods */
std::string to_string_hex (uint64_t const);
bool from_string_hex (std::string const &, uint64_t &);
/**
* Convert a double to string in fixed format
* @param precision_a (optional) use a specific precision (default is the maximum)
*/
std::string to_string (double const, int const precision_a = std::numeric_limits<double>::digits10);
namespace difficulty
{
uint64_t from_multiplier (double const, uint64_t const);
double to_multiplier (uint64_t const, uint64_t const);
}
}
namespace std
{
template <>
struct hash<::nano::uint256_union>
{
size_t operator() (::nano::uint256_union const & data_a) const
{
return data_a.qwords[0] + data_a.qwords[1] + data_a.qwords[2] + data_a.qwords[3];
}
};
template <>
struct hash<::nano::account>
{
size_t operator() (::nano::account const & data_a) const
{
return hash<::nano::uint256_union> () (data_a);
}
};
template <>
struct hash<::nano::block_hash>
{
size_t operator() (::nano::block_hash const & data_a) const
{
return hash<::nano::uint256_union> () (data_a);
}
};
template <>
struct hash<::nano::raw_key>
{
size_t operator() (::nano::raw_key const & data_a) const
{
return hash<::nano::uint256_union> () (data_a);
}
};
template <>
struct hash<::nano::root>
{
size_t operator() (::nano::root const & data_a) const
{
return hash<::nano::uint256_union> () (data_a);
}
};
template <>
struct hash<::nano::wallet_id>
{
size_t operator() (::nano::wallet_id const & data_a) const
{
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> ();
}
};
template <>
struct hash<::nano::uint512_union>
{
size_t operator() (::nano::uint512_union const & data_a) const
{
return hash<::nano::uint256_union> () (data_a.uint256s[0]) + hash<::nano::uint256_union> () (data_a.uint256s[1]);
}
};
template <>
struct hash<::nano::qualified_root>
{
size_t operator() (::nano::qualified_root const & data_a) const
{
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 ();
}
};
}
namespace boost
{
template <>
struct hash<std::reference_wrapper<::nano::block_hash const>>
{
size_t operator() (std::reference_wrapper<::nano::block_hash const> const & hash_a) const
{
std::hash<::nano::block_hash> hash;
return hash (hash_a);
}
};
}