/Users/eugenesiegel/btc/bitcoin/src/uint256.h
Line | Count | Source (jump to first uncovered line) |
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 | 52.9G | constexpr base_blob() : m_data() {} _ZN9base_blobILj256EEC2Ev Line | Count | Source | 35 | 52.9G | constexpr base_blob() : m_data() {} |
_ZN9base_blobILj160EEC2Ev Line | Count | Source | 35 | 207k | 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 | | constexpr explicit base_blob(std::span<const unsigned char> vch) |
41 | 777k | { |
42 | 777k | assert(vch.size() == WIDTH); |
43 | 777k | std::copy(vch.begin(), vch.end(), m_data.begin()); |
44 | 777k | } _ZN9base_blobILj256EEC2ENSt3__14spanIKhLm18446744073709551615EEE Line | Count | Source | 41 | 777k | { | 42 | 777k | assert(vch.size() == WIDTH); | 43 | 777k | std::copy(vch.begin(), vch.end(), m_data.begin()); | 44 | 777k | } |
Unexecuted instantiation: _ZN9base_blobILj160EEC2ENSt3__14spanIKhLm18446744073709551615EEE |
45 | | |
46 | | consteval explicit base_blob(std::string_view hex_str); |
47 | | |
48 | | constexpr bool IsNull() const |
49 | 231M | { |
50 | 6.48G | return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { |
51 | 6.48G | return val == 0; |
52 | 6.48G | }); _ZZNK9base_blobILj256EE6IsNullEvENKUlhE_clEh Line | Count | Source | 50 | 6.48G | return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { | 51 | 6.48G | return val == 0; | 52 | 6.48G | }); |
Unexecuted instantiation: _ZZNK9base_blobILj160EE6IsNullEvENKUlhE_clEh |
53 | 231M | } _ZNK9base_blobILj256EE6IsNullEv Line | Count | Source | 49 | 231M | { | 50 | 231M | return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { | 51 | 231M | return val == 0; | 52 | 231M | }); | 53 | 231M | } |
Unexecuted instantiation: _ZNK9base_blobILj160EE6IsNullEv |
54 | | |
55 | | constexpr void SetNull() |
56 | 76.6M | { |
57 | 76.6M | std::fill(m_data.begin(), m_data.end(), 0); |
58 | 76.6M | } _ZN9base_blobILj256EE7SetNullEv Line | Count | Source | 56 | 76.6M | { | 57 | 76.6M | std::fill(m_data.begin(), m_data.end(), 0); | 58 | 76.6M | } |
Unexecuted instantiation: _ZN9base_blobILj160EE7SetNullEv |
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 | 182M | constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); } _ZNK9base_blobILj256EE7CompareERKS0_ Line | Count | Source | 64 | 182M | constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); } |
Unexecuted instantiation: _ZNK9base_blobILj160EE7CompareERKS0_ |
65 | | |
66 | 141M | friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } _ZeqRK9base_blobILj256EES2_ Line | Count | Source | 66 | 141M | friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } |
Unexecuted instantiation: _ZeqRK9base_blobILj160EES2_ |
67 | 40.2M | friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } _ZneRK9base_blobILj256EES2_ Line | Count | Source | 67 | 40.2M | friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } |
Unexecuted instantiation: _ZneRK9base_blobILj160EES2_ |
68 | 1.18M | friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } _ZltRK9base_blobILj256EES2_ Line | Count | Source | 68 | 1.18M | friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } |
Unexecuted instantiation: _ZltRK9base_blobILj160EES2_ |
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 | 121M | constexpr const unsigned char* data() const { return m_data.data(); } Unexecuted instantiation: _ZNK9base_blobILj160EE4dataEv _ZNK9base_blobILj256EE4dataEv Line | Count | Source | 98 | 121M | constexpr const unsigned char* data() const { return m_data.data(); } |
|
99 | 204M | constexpr unsigned char* data() { return m_data.data(); } Unexecuted instantiation: _ZN9base_blobILj160EE4dataEv _ZN9base_blobILj256EE4dataEv Line | Count | Source | 99 | 204M | constexpr unsigned char* data() { return m_data.data(); } |
|
100 | | |
101 | 545M | constexpr unsigned char* begin() { return m_data.data(); } Unexecuted instantiation: _ZN9base_blobILj160EE5beginEv _ZN9base_blobILj256EE5beginEv Line | Count | Source | 101 | 545M | constexpr unsigned char* begin() { return m_data.data(); } |
|
102 | 0 | constexpr unsigned char* end() { return m_data.data() + WIDTH; } Unexecuted instantiation: _ZN9base_blobILj160EE3endEv Unexecuted instantiation: _ZN9base_blobILj256EE3endEv |
103 | | |
104 | 361M | constexpr const unsigned char* begin() const { return m_data.data(); } Unexecuted instantiation: _ZNK9base_blobILj160EE5beginEv _ZNK9base_blobILj256EE5beginEv Line | Count | Source | 104 | 361M | constexpr const unsigned char* begin() const { return m_data.data(); } |
|
105 | 33.0k | constexpr const unsigned char* end() const { return m_data.data() + WIDTH; } Unexecuted instantiation: _ZNK9base_blobILj160EE3endEv _ZNK9base_blobILj256EE3endEv Line | Count | Source | 105 | 33.0k | constexpr const unsigned char* end() const { return m_data.data() + WIDTH; } |
|
106 | | |
107 | 284M | static constexpr unsigned int size() { return WIDTH; } Unexecuted instantiation: _ZN9base_blobILj160EE4sizeEv _ZN9base_blobILj256EE4sizeEv Line | Count | Source | 107 | 284M | static constexpr unsigned int size() { return WIDTH; } |
|
108 | | |
109 | 601M | 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 | 713M | { |
114 | 713M | s << std::span(m_data); |
115 | 713M | } _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR12SizeComputer20TransactionSerParamsEEEvRT_ Line | Count | Source | 113 | 330M | { | 114 | 330M | s << std::span(m_data); | 115 | 330M | } |
_ZNK9base_blobILj256EE9SerializeI12VectorWriterEEvRT_ Line | Count | Source | 113 | 944k | { | 114 | 944k | s << std::span(m_data); | 115 | 944k | } |
_ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR12VectorWriter20TransactionSerParamsEEEvRT_ Line | Count | Source | 113 | 1.48M | { | 114 | 1.48M | s << std::span(m_data); | 115 | 1.48M | } |
_ZNK9base_blobILj256EE9SerializeI10DataStreamEEvRT_ Line | Count | Source | 113 | 41.0M | { | 114 | 41.0M | s << std::span(m_data); | 115 | 41.0M | } |
Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR10DataStream20TransactionSerParamsEEEvRT_ Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI12SizeComputerEEvRT_ Unexecuted instantiation: _ZNK9base_blobILj160EE9SerializeI10DataStreamEEvRT_ Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIRS2_IR12VectorWriter20TransactionSerParamsES5_EEEvRT_ Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI8AutoFileEEvRT_ _ZNK9base_blobILj256EE9SerializeI10HashWriterEEvRT_ Line | Count | Source | 113 | 254M | { | 114 | 254M | s << std::span(m_data); | 115 | 254M | } |
Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR18HashedSourceWriterI8AutoFileEN8CAddress9SerParamsEEEEvRT_ Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR10DataStreamN8CAddress9SerParamsEEEEvRT_ _ZNK9base_blobILj256EE9SerializeI14BufferedWriterI8AutoFileEEEvRT_ Line | Count | Source | 113 | 9.99M | { | 114 | 9.99M | s << std::span(m_data); | 115 | 9.99M | } |
_ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR14BufferedWriterI8AutoFileE20TransactionSerParamsEEEvRT_ Line | Count | Source | 113 | 30.1M | { | 114 | 30.1M | s << std::span(m_data); | 115 | 30.1M | } |
Unexecuted instantiation: _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR8AutoFile20TransactionSerParamsEEEvRT_ _ZNK9base_blobILj256EE9SerializeI12ParamsStreamIR10HashWriter20TransactionSerParamsEEEvRT_ Line | Count | Source | 113 | 43.9M | { | 114 | 43.9M | s << std::span(m_data); | 115 | 43.9M | } |
|
116 | | |
117 | | template<typename Stream> |
118 | | void Unserialize(Stream& s) |
119 | 1.74M | { |
120 | 1.74M | s.read(MakeWritableByteSpan(m_data)); |
121 | 1.74M | } _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR10DataStream20TransactionSerParamsEEEvRT_ Line | Count | Source | 119 | 1.17M | { | 120 | 1.17M | s.read(MakeWritableByteSpan(m_data)); | 121 | 1.17M | } |
_ZN9base_blobILj256EE11UnserializeI10DataStreamEEvRT_ Line | Count | Source | 119 | 412k | { | 120 | 412k | s.read(MakeWritableByteSpan(m_data)); | 121 | 412k | } |
Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI10SpanReaderEEvRT_ Unexecuted instantiation: _ZN9base_blobILj160EE11UnserializeI10DataStreamEEvRT_ _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR10SpanReader20TransactionSerParamsEEEvRT_ Line | Count | Source | 119 | 152k | { | 120 | 152k | s.read(MakeWritableByteSpan(m_data)); | 121 | 152k | } |
Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI8AutoFileEEvRT_ Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR8AutoFileN8CAddress9SerParamsEEEEvRT_ Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR12HashVerifierI8AutoFileEN8CAddress9SerParamsEEEEvRT_ Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR10DataStreamN8CAddress9SerParamsEEEEvRT_ Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR12HashVerifierI10DataStreamEN8CAddress9SerParamsEEEEvRT_ Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR8AutoFile20TransactionSerParamsEEEvRT_ _ZN9base_blobILj256EE11UnserializeI14BufferedReaderI8AutoFileEEEvRT_ Line | Count | Source | 119 | 55 | { | 120 | 55 | s.read(MakeWritableByteSpan(m_data)); | 121 | 55 | } |
Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12BufferedFileEEvRT_ Unexecuted instantiation: _ZN9base_blobILj256EE11UnserializeI12ParamsStreamIR12BufferedFile20TransactionSerParamsEEEvRT_ |
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 | 0 | { |
145 | 0 | if (uintN_t::size() * 2 != str.size() || !IsHex(str)) return std::nullopt; |
146 | 0 | uintN_t rv; |
147 | 0 | unsigned char* p1 = rv.begin(); |
148 | 0 | unsigned char* pend = rv.end(); |
149 | 0 | size_t digits = str.size(); |
150 | 0 | while (digits > 0 && p1 < pend) { |
151 | 0 | *p1 = ::HexDigit(str[--digits]); |
152 | 0 | if (digits > 0) { |
153 | 0 | *p1 |= ((unsigned char)::HexDigit(str[--digits]) << 4); |
154 | 0 | p1++; |
155 | 0 | } |
156 | 0 | } |
157 | 0 | return rv; |
158 | 0 | } Unexecuted instantiation: _ZN6detail7FromHexI7uint160EENSt3__18optionalIT_EENS2_17basic_string_viewIcNS2_11char_traitsIcEEEE Unexecuted instantiation: _ZN6detail7FromHexI7uint256EENSt3__18optionalIT_EENS2_17basic_string_viewIcNS2_11char_traitsIcEEEE |
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 | 0 | { |
169 | 0 | input = util::RemovePrefixView(input, "0x"); |
170 | 0 | constexpr auto expected_size{uintN_t::size() * 2}; |
171 | 0 | if (input.size() < expected_size) { |
172 | 0 | auto padded = std::string(expected_size, '0'); |
173 | 0 | std::copy(input.begin(), input.end(), padded.begin() + expected_size - input.size()); |
174 | 0 | return FromHex<uintN_t>(padded); |
175 | 0 | } |
176 | 0 | return FromHex<uintN_t>(input); |
177 | 0 | } |
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 | 0 | static std::optional<uint160> FromHex(std::string_view str) { return detail::FromHex<uint160>(str); } |
187 | 207k | constexpr uint160() = default; |
188 | 0 | 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 | 0 | static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); } |
199 | 0 | static std::optional<uint256> FromUserHex(std::string_view str) { return detail::FromUserHex<uint256>(str); } |
200 | 52.9G | constexpr uint256() = default; |
201 | 0 | consteval explicit uint256(std::string_view hex_str) : base_blob<256>(hex_str) {} |
202 | 0 | constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {} |
203 | 777k | 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 |