diff options
Diffstat (limited to 'src/uint256.h')
-rw-r--r-- | src/uint256.h | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/src/uint256.h b/src/uint256.h index cf008765bd..8223787041 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -9,6 +9,7 @@ #include <crypto/common.h> #include <span.h> #include <util/strencodings.h> +#include <util/string.h> #include <algorithm> #include <array> @@ -17,6 +18,7 @@ #include <cstring> #include <optional> #include <string> +#include <string_view> /** Template base class for fixed-sized opaque blobs. */ template<unsigned int BITS> @@ -125,20 +127,11 @@ 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. + if (hex_str.length() != m_data.size() * 2) throw "Hex string must fit exactly"; auto str_it = hex_str.rbegin(); for (auto& elem : m_data) { - auto lo = from_hex(*(str_it++)); - elem = (from_hex(*(str_it++)) << 4) | lo; + auto lo = util::ConstevalHexDigit(*(str_it++)); + elem = (util::ConstevalHexDigit(*(str_it++)) << 4) | lo; } } @@ -157,6 +150,25 @@ std::optional<uintN_t> FromHex(std::string_view str) rv.SetHexDeprecated(str); return rv; } +/** + * @brief Like FromHex(std::string_view str), but allows an "0x" prefix + * and pads the input with leading zeroes if it is shorter than + * the expected length of uintN_t::size()*2. + * + * Designed to be used when dealing with user input. + */ +template <class uintN_t> +std::optional<uintN_t> FromUserHex(std::string_view input) +{ + input = util::RemovePrefixView(input, "0x"); + constexpr auto expected_size{uintN_t::size() * 2}; + if (input.size() < expected_size) { + auto padded = std::string(expected_size, '0'); + std::copy(input.begin(), input.end(), padded.begin() + expected_size - input.size()); + return FromHex<uintN_t>(padded); + } + return FromHex<uintN_t>(input); +} } // namespace detail /** 160-bit opaque blob. @@ -178,6 +190,7 @@ public: class uint256 : public base_blob<256> { public: static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); } + static std::optional<uint256> FromUserHex(std::string_view str) { return detail::FromUserHex<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) {} @@ -186,14 +199,4 @@ public: static const uint256 ONE; }; -/* uint256 from std::string_view, containing byte-reversed hex encoding. - * DEPRECATED. Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated! - */ -inline uint256 uint256S(std::string_view str) -{ - uint256 rv; - rv.SetHexDeprecated(str); - return rv; -} - #endif // BITCOIN_UINT256_H |