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