diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 841aec1e14..a14f44ad45 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -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() diff --git a/src/uint256.h b/src/uint256.h index 1d45401aa1..cf008765bd 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -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 +consteval base_blob::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 FromHex(std::string_view str) { return detail::FromHex(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 vch) : base_blob<256>(vch) {} static const uint256 ZERO;