uint256.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-present The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 6 #ifndef BITCOIN_UINT256_H 7 #define BITCOIN_UINT256_H 8 9 #include <crypto/common.h> 10 #include <crypto/hex_base.h> 11 #include <span.h> 12 #include <util/strencodings.h> 13 #include <util/string.h> 14 15 #include <algorithm> 16 #include <array> 17 #include <cassert> 18 #include <cstdint> 19 #include <cstring> 20 #include <optional> 21 #include <string> 22 #include <string_view> 23 24 /** Template base class for fixed-sized opaque blobs. */ 25 template<unsigned int BITS> 26 class base_blob 27 { 28 protected: 29 static constexpr int WIDTH = BITS / 8; 30 static_assert(BITS % 8 == 0, "base_blob currently only supports whole bytes."); 31 std::array<uint8_t, WIDTH> m_data; 32 static_assert(WIDTH == sizeof(m_data), "Sanity check"); 33 34 public: 35 /* construct 0 value by default */ 36 constexpr base_blob() : m_data() {} 37 38 /* constructor for constants between 1 and 255 */ 39 constexpr explicit base_blob(uint8_t v) : m_data{v} {} 40 41 constexpr explicit base_blob(std::span<const unsigned char> vch) 42 { 43 assert(vch.size() == WIDTH); 44 std::copy(vch.begin(), vch.end(), m_data.begin()); 45 } 46 47 consteval explicit base_blob(std::string_view hex_str); 48 49 constexpr bool IsNull() const 50 { 51 return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { 52 return val == 0; 53 }); 54 } 55 56 constexpr void SetNull() 57 { 58 std::fill(m_data.begin(), m_data.end(), 0); 59 } 60 61 /** Lexicographic ordering 62 * @note Does NOT match the ordering on the corresponding \ref 63 * base_uint::CompareTo, which starts comparing from the end. 64 */ 65 constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); } 66 67 friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } 68 friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } 69 70 /** @name Hex representation 71 * 72 * The hex representation used by GetHex(), ToString(), and FromHex() 73 * is unusual, since it shows bytes of the base_blob in reverse order. 74 * For example, a 4-byte blob {0x12, 0x34, 0x56, 0x78} is represented 75 * as "78563412" instead of the more typical "12345678" representation 76 * that would be shown in a hex editor or used by typical 77 * byte-array / hex conversion functions like python's bytes.hex() and 78 * bytes.fromhex(). 79 * 80 * The nice thing about the reverse-byte representation, even though it is 81 * unusual, is that if a blob contains an arithmetic number in little endian 82 * format (with least significant bytes first, and most significant bytes 83 * last), the GetHex() output will match the way the number would normally 84 * be written in base-16 (with most significant digits first and least 85 * significant digits last). 86 * 87 * This means, for example, that ArithToUint256(num).GetHex() can be used to 88 * display an arith_uint256 num value as a number, because 89 * ArithToUint256() converts the number to a blob in little-endian format, 90 * so the arith_uint256 class doesn't need to have its own number parsing 91 * and formatting functions. 92 * 93 * @{*/ 94 std::string GetHex() const; 95 std::string ToString() const; 96 /**@}*/ 97 98 constexpr const unsigned char* data() const { return m_data.data(); } 99 constexpr unsigned char* data() { return m_data.data(); } 100 101 constexpr unsigned char* begin() { return m_data.data(); } 102 constexpr unsigned char* end() { return m_data.data() + WIDTH; } 103 104 constexpr const unsigned char* begin() const { return m_data.data(); } 105 constexpr const unsigned char* end() const { return m_data.data() + WIDTH; } 106 107 static constexpr unsigned int size() { return WIDTH; } 108 109 constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); } 110 111 template<typename Stream> 112 void Serialize(Stream& s) const 113 { 114 s << std::span(m_data); 115 } 116 117 template<typename Stream> 118 void Unserialize(Stream& s) 119 { 120 s.read(MakeWritableByteSpan(m_data)); 121 } 122 }; 123 124 template <unsigned int BITS> 125 consteval base_blob<BITS>::base_blob(std::string_view hex_str) 126 { 127 if (hex_str.length() != m_data.size() * 2) throw "Hex string must fit exactly"; 128 auto str_it = hex_str.rbegin(); 129 for (auto& elem : m_data) { 130 auto lo = util::ConstevalHexDigit(*(str_it++)); 131 elem = (util::ConstevalHexDigit(*(str_it++)) << 4) | lo; 132 } 133 } 134 135 namespace detail { 136 /** 137 * Writes the hex string (in reverse byte order) into a new uintN_t object 138 * and only returns a value iff all of the checks pass: 139 * - Input length is uintN_t::size()*2 140 * - All characters are hex 141 */ 142 template <class uintN_t> 143 std::optional<uintN_t> FromHex(std::string_view str) 144 { 145 if (uintN_t::size() * 2 != str.size() || !IsHex(str)) return std::nullopt; 146 uintN_t rv; 147 unsigned char* p1 = rv.begin(); 148 unsigned char* pend = rv.end(); 149 size_t digits = str.size(); 150 while (digits > 0 && p1 < pend) { 151 *p1 = ::HexDigit(str[--digits]); 152 if (digits > 0) { 153 *p1 |= ((unsigned char)::HexDigit(str[--digits]) << 4); 154 p1++; 155 } 156 } 157 return rv; 158 } 159 /** 160 * @brief Like FromHex(std::string_view str), but allows an "0x" prefix 161 * and pads the input with leading zeroes if it is shorter than 162 * the expected length of uintN_t::size()*2. 163 * 164 * Designed to be used when dealing with user input. 165 */ 166 template <class uintN_t> 167 std::optional<uintN_t> FromUserHex(std::string_view input) 168 { 169 input = util::RemovePrefixView(input, "0x"); 170 constexpr auto expected_size{uintN_t::size() * 2}; 171 if (input.size() < expected_size) { 172 auto padded = std::string(expected_size, '0'); 173 std::copy(input.begin(), input.end(), padded.begin() + expected_size - input.size()); 174 return FromHex<uintN_t>(padded); 175 } 176 return FromHex<uintN_t>(input); 177 } 178 } // namespace detail 179 180 /** 160-bit opaque blob. 181 * @note This type is called uint160 for historical reasons only. It is an opaque 182 * blob of 160 bits and has no integer operations. 183 */ 184 class uint160 : public base_blob<160> { 185 public: 186 static std::optional<uint160> FromHex(std::string_view str) { return detail::FromHex<uint160>(str); } 187 constexpr uint160() = default; 188 constexpr explicit uint160(std::span<const unsigned char> vch) : base_blob<160>(vch) {} 189 }; 190 191 /** 256-bit opaque blob. 192 * @note This type is called uint256 for historical reasons only. It is an 193 * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if 194 * those are required. 195 */ 196 class uint256 : public base_blob<256> { 197 public: 198 static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); } 199 static std::optional<uint256> FromUserHex(std::string_view str) { return detail::FromUserHex<uint256>(str); } 200 constexpr uint256() = default; 201 consteval explicit uint256(std::string_view hex_str) : base_blob<256>(hex_str) {} 202 constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {} 203 constexpr explicit uint256(std::span<const unsigned char> vch) : base_blob<256>(vch) {} 204 static const uint256 ZERO; 205 static const uint256 ONE; 206 }; 207 208 #endif // BITCOIN_UINT256_H