Branch data Line data Source code
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 <span.h>
11 : : #include <util/strencodings.h>
12 : : #include <util/string.h>
13 : :
14 : : #include <algorithm>
15 : : #include <array>
16 : : #include <cassert>
17 : : #include <cstdint>
18 : : #include <cstring>
19 : : #include <optional>
20 : : #include <string>
21 : : #include <string_view>
22 : :
23 : : /** Template base class for fixed-sized opaque blobs. */
24 : : template<unsigned int BITS>
25 : : class base_blob
26 : : {
27 : : protected:
28 : : static constexpr int WIDTH = BITS / 8;
29 : : static_assert(BITS % 8 == 0, "base_blob currently only supports whole bytes.");
30 : : std::array<uint8_t, WIDTH> m_data;
31 : : static_assert(WIDTH == sizeof(m_data), "Sanity check");
32 : :
33 : : public:
34 : : /* construct 0 value by default */
35 : 1119937 : constexpr base_blob() : m_data() {}
36 : :
37 : : /* constructor for constants between 1 and 255 */
38 : 0 : constexpr explicit base_blob(uint8_t v) : m_data{v} {}
39 : :
40 [ - + ]: 43203 : constexpr explicit base_blob(Span<const unsigned char> vch)
41 : : {
42 [ - + ]: 43203 : assert(vch.size() == WIDTH);
43 : 43203 : std::copy(vch.begin(), vch.end(), m_data.begin());
44 : 43203 : }
45 : :
46 : : consteval explicit base_blob(std::string_view hex_str);
47 : :
48 : 5442 : constexpr bool IsNull() const
49 : : {
50 : 5442 : return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
51 : : return val == 0;
52 : 5442 : });
53 : : }
54 : :
55 : 14626 : constexpr void SetNull()
56 : : {
57 [ + - ]: 24368 : std::fill(m_data.begin(), m_data.end(), 0);
58 : : }
59 : :
60 : : /** Lexicographic ordering
61 : : * @note Does NOT match the ordering on the corresponding \ref
62 : : * base_uint::CompareTo, which starts comparing from the end.
63 : : */
64 [ # # # # : 410034 : constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); }
# # ]
[ # # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # ][ # #
# # # # #
# # # #
# ][ # # #
# # # # #
# # # # #
# # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ # # #
# # # # #
# # ]
65 : :
66 [ - - - - : 757 : friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
- - - - +
+ - - - -
- - - - ]
[ # # # #
# # # # #
# # # # #
# # ][ # #
# # # # #
# # # # #
# # # # #
# ][ - + -
+ - + - +
- + - + -
+ - + - +
- + ][ # #
# # # # ]
[ # # # #
# # ][ - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - -
- - - - -
- - - - +
- + + - -
- - - -
- ][ # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ # # # #
# # # # #
# # # ]
67 [ # # ][ # # : 2 : friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
# # # # #
# ][ # # #
# # # #
# ][ - - -
- - - - -
- + ][ - +
- - # # #
# # # ]
68 [ - - - - : 409272 : 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 reverse-byte hex representation is a convenient way to view the blob
73 : : * as a number, because it is consistent with the way the base_uint class
74 : : * converts blobs to numbers.
75 : : *
76 : : * @note base_uint treats the blob as an array of bytes with the numerically
77 : : * least significant byte first and the most significant byte last. Because
78 : : * numbers are typically written with the most significant digit first and
79 : : * the least significant digit last, the reverse hex display of the blob
80 : : * corresponds to the same numeric value that base_uint interprets from the
81 : : * blob.
82 : : * @{*/
83 : : std::string GetHex() const;
84 : : /** Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated!
85 : : *
86 : : * - Hex numbers that don't specify enough bytes to fill the internal array
87 : : * will be treated as setting the beginning of it, which corresponds to
88 : : * the least significant bytes when converted to base_uint.
89 : : *
90 : : * - Hex numbers specifying too many bytes will have the numerically most
91 : : * significant bytes (the beginning of the string) narrowed away.
92 : : *
93 : : * - An odd count of hex digits will result in the high bits of the leftmost
94 : : * byte being zero.
95 : : * "0x123" => {0x23, 0x1, 0x0, ..., 0x0}
96 : : */
97 : : void SetHexDeprecated(std::string_view str);
98 : : std::string ToString() const;
99 : : /**@}*/
100 : :
101 [ # # ]: 4 : constexpr const unsigned char* data() const { return m_data.data(); }
[ # # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
102 [ # # # # ]: 205786 : constexpr unsigned char* data() { return m_data.data(); }
[ - - - - ]
[ # # # #
# # ]
103 : :
104 [ + - ][ # # : 29316 : constexpr unsigned char* begin() { return m_data.data(); }
# # # # ]
[ + - + - ]
[ - - - -
+ - + - ]
105 : 0 : constexpr unsigned char* end() { return m_data.data() + WIDTH; }
106 : :
107 [ - + ][ # # : 60509 : constexpr const unsigned char* begin() const { return m_data.data(); }
# # # # #
# # # ]
108 [ # # ][ # # : 56243 : constexpr const unsigned char* end() const { return m_data.data() + WIDTH; }
# # # # #
# # # ]
109 : :
110 : : static constexpr unsigned int size() { return WIDTH; }
111 : :
112 [ # # ]: 1 : constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); }
113 : :
114 : : template<typename Stream>
115 : 29918 : void Serialize(Stream& s) const
116 : : {
117 : 29918 : s << Span(m_data);
118 : : }
119 : :
120 : : template<typename Stream>
121 : 332 : void Unserialize(Stream& s)
122 : : {
123 : 332 : s.read(MakeWritableByteSpan(m_data));
124 : 324 : }
125 : : };
126 : :
127 : : template <unsigned int BITS>
128 : : consteval base_blob<BITS>::base_blob(std::string_view hex_str)
129 : : {
130 : : if (hex_str.length() != m_data.size() * 2) throw "Hex string must fit exactly";
131 : : auto str_it = hex_str.rbegin();
132 : : for (auto& elem : m_data) {
133 : : auto lo = util::ConstevalHexDigit(*(str_it++));
134 : : elem = (util::ConstevalHexDigit(*(str_it++)) << 4) | lo;
135 : : }
136 : : }
137 : :
138 : : namespace detail {
139 : : /**
140 : : * Writes the hex string (in reverse byte order) into a new uintN_t object
141 : : * and only returns a value iff all of the checks pass:
142 : : * - Input length is uintN_t::size()*2
143 : : * - All characters are hex
144 : : */
145 : : template <class uintN_t>
146 [ # # ]: 0 : std::optional<uintN_t> FromHex(std::string_view str)
147 : : {
148 [ # # # # ]: 0 : if (uintN_t::size() * 2 != str.size() || !IsHex(str)) return std::nullopt;
149 : 0 : uintN_t rv;
150 : 0 : rv.SetHexDeprecated(str);
151 : 0 : return rv;
152 : : }
153 : : /**
154 : : * @brief Like FromHex(std::string_view str), but allows an "0x" prefix
155 : : * and pads the input with leading zeroes if it is shorter than
156 : : * the expected length of uintN_t::size()*2.
157 : : *
158 : : * Designed to be used when dealing with user input.
159 : : */
160 : : template <class uintN_t>
161 : 0 : std::optional<uintN_t> FromUserHex(std::string_view input)
162 : : {
163 : 0 : input = util::RemovePrefixView(input, "0x");
164 [ # # ]: 0 : constexpr auto expected_size{uintN_t::size() * 2};
165 [ # # ]: 0 : if (input.size() < expected_size) {
166 : 0 : auto padded = std::string(expected_size, '0');
167 [ # # ]: 0 : std::copy(input.begin(), input.end(), padded.begin() + expected_size - input.size());
168 [ # # ]: 0 : return FromHex<uintN_t>(padded);
169 : 0 : }
170 : 0 : return FromHex<uintN_t>(input);
171 : : }
172 : : } // namespace detail
173 : :
174 : : /** 160-bit opaque blob.
175 : : * @note This type is called uint160 for historical reasons only. It is an opaque
176 : : * blob of 160 bits and has no integer operations.
177 : : */
178 : : class uint160 : public base_blob<160> {
179 : : public:
180 : : static std::optional<uint160> FromHex(std::string_view str) { return detail::FromHex<uint160>(str); }
181 [ + + + + : 61261 : constexpr uint160() = default;
+ - + ]
[ # # ]
182 : 43203 : constexpr explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {}
183 : : };
184 : :
185 : : /** 256-bit opaque blob.
186 : : * @note This type is called uint256 for historical reasons only. It is an
187 : : * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if
188 : : * those are required.
189 : : */
190 : : class uint256 : public base_blob<256> {
191 : : public:
192 [ # # # # ]: 0 : static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); }
[ # # # #
# # # # #
# # # ]
[ # # ]
193 [ # # # # ]: 0 : static std::optional<uint256> FromUserHex(std::string_view str) { return detail::FromUserHex<uint256>(str); }
194 [ + - + - : 1058668 : constexpr uint256() = default;
- - ]
[ # # # # ]
[ + - # #
# # ][ # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ + - -
- + - +
- ]
195 : : consteval explicit uint256(std::string_view hex_str) : base_blob<256>(hex_str) {}
196 [ # # ]: 0 : constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {}
197 : 0 : constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {}
198 : : static const uint256 ZERO;
199 : : static const uint256 ONE;
200 : : };
201 : :
202 : : /* uint256 from std::string_view, containing byte-reversed hex encoding.
203 : : * DEPRECATED. Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated!
204 : : */
205 : 0 : inline uint256 uint256S(std::string_view str)
206 : : {
207 : 0 : uint256 rv;
208 [ # # ]: 0 : rv.SetHexDeprecated(str);
209 [ # # ]: 0 : return rv;
210 : : }
211 : :
212 : : #endif // BITCOIN_UINT256_H
|