0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

refactor: Add consteval uint256(hex_str)

Complements uint256::FromHex() nicely in that it naturally does all error checking at compile time and so doesn't need to return an std::optional.

Will be used in the following 2 commits to replace many calls to uint256S(). uint256S() calls taking C-string literals are littered throughout the codebase and executed at runtime to perform parsing unless a given optimizer was surprisingly efficient. While this may not be a hot spot, it's better hygiene in C++20 to store the parsed data blob directly in the binary, without any parsing at runtime.
This commit is contained in:
Hodlinator 2024-08-01 23:33:24 +02:00
parent 1afa3c84fc
commit b74d8d58fa
No known key found for this signature in database
2 changed files with 30 additions and 0 deletions

View file

@ -399,4 +399,11 @@ BOOST_AUTO_TEST_CASE( check_ONE )
BOOST_CHECK_EQUAL(one, uint256::ONE);
}
BOOST_AUTO_TEST_CASE(FromHex_vs_uint256)
{
auto runtime_uint{uint256::FromHex("4A5E1E4BAAB89F3A32518A88C31BC87F618f76673e2cc77ab2127b7afdeda33b").value()};
constexpr uint256 consteval_uint{ "4a5e1e4baab89f3a32518a88c31bc87f618F76673E2CC77AB2127B7AFDEDA33B"};
BOOST_CHECK_EQUAL(consteval_uint, runtime_uint);
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -41,6 +41,8 @@ public:
std::copy(vch.begin(), vch.end(), m_data.begin());
}
consteval explicit base_blob(std::string_view hex_str);
constexpr bool IsNull() const
{
return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
@ -120,6 +122,26 @@ public:
}
};
template <unsigned int BITS>
consteval base_blob<BITS>::base_blob(std::string_view hex_str)
{
// Non-lookup table version of HexDigit().
auto from_hex = [](const char c) -> int8_t {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 0xA;
if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
assert(false); // Reached if ctor is called with an invalid hex digit.
};
assert(hex_str.length() == m_data.size() * 2); // 2 hex digits per byte.
auto str_it = hex_str.rbegin();
for (auto& elem : m_data) {
auto lo = from_hex(*(str_it++));
elem = (from_hex(*(str_it++)) << 4) | lo;
}
}
namespace detail {
/**
* Writes the hex string (in reverse byte order) into a new uintN_t object
@ -157,6 +179,7 @@ class uint256 : public base_blob<256> {
public:
static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); }
constexpr uint256() = default;
consteval explicit uint256(std::string_view hex_str) : base_blob<256>(hex_str) {}
constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {}
constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {}
static const uint256 ZERO;