/workdir/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 | | |
13 | | #include <algorithm> |
14 | | #include <array> |
15 | | #include <cassert> |
16 | | #include <cstdint> |
17 | | #include <cstring> |
18 | | #include <optional> |
19 | | #include <string> |
20 | | |
21 | | /** Template base class for fixed-sized opaque blobs. */ |
22 | | template<unsigned int BITS> |
23 | | class base_blob |
24 | | { |
25 | | protected: |
26 | | static constexpr int WIDTH = BITS / 8; |
27 | | static_assert(BITS % 8 == 0, "base_blob currently only supports whole bytes."); |
28 | | std::array<uint8_t, WIDTH> m_data; |
29 | | static_assert(WIDTH == sizeof(m_data), "Sanity check"); |
30 | | |
31 | | public: |
32 | | /* construct 0 value by default */ |
33 | 907k | constexpr base_blob() : m_data() {} base_blob<256u>::base_blob() Line | Count | Source | 33 | 907k | constexpr base_blob() : m_data() {} |
Unexecuted instantiation: base_blob<160u>::base_blob() |
34 | | |
35 | | /* constructor for constants between 1 and 255 */ |
36 | 0 | constexpr explicit base_blob(uint8_t v) : m_data{v} {} |
37 | | |
38 | | constexpr explicit base_blob(Span<const unsigned char> vch) |
39 | 0 | { |
40 | 0 | assert(vch.size() == WIDTH); |
41 | 0 | std::copy(vch.begin(), vch.end(), m_data.begin()); |
42 | 0 | } Unexecuted instantiation: base_blob<256u>::base_blob(Span<unsigned char const>) Unexecuted instantiation: base_blob<160u>::base_blob(Span<unsigned char const>) |
43 | | |
44 | | consteval explicit base_blob(std::string_view hex_str); |
45 | | |
46 | | constexpr bool IsNull() const |
47 | 113k | { |
48 | 1.90M | return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { |
49 | 1.90M | return val == 0; |
50 | 1.90M | }); base_blob<256u>::IsNull() const::{lambda(unsigned char)#1}::operator()(unsigned char) const Line | Count | Source | 48 | 1.90M | return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { | 49 | 1.90M | return val == 0; | 50 | 1.90M | }); |
Unexecuted instantiation: base_blob<160u>::IsNull() const::{lambda(unsigned char)#1}::operator()(unsigned char) const |
51 | 113k | } base_blob<256u>::IsNull() const Line | Count | Source | 47 | 113k | { | 48 | 113k | return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) { | 49 | 113k | return val == 0; | 50 | 113k | }); | 51 | 113k | } |
Unexecuted instantiation: base_blob<160u>::IsNull() const |
52 | | |
53 | | constexpr void SetNull() |
54 | 753k | { |
55 | 753k | std::fill(m_data.begin(), m_data.end(), 0); |
56 | 753k | } base_blob<256u>::SetNull() Line | Count | Source | 54 | 753k | { | 55 | 753k | std::fill(m_data.begin(), m_data.end(), 0); | 56 | 753k | } |
Unexecuted instantiation: base_blob<160u>::SetNull() |
57 | | |
58 | | /** Lexicographic ordering |
59 | | * @note Does NOT match the ordering on the corresponding \ref |
60 | | * base_uint::CompareTo, which starts comparing from the end. |
61 | | */ |
62 | 100k | constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); } base_blob<256u>::Compare(base_blob<256u> const&) const Line | Count | Source | 62 | 100k | constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); } |
Unexecuted instantiation: base_blob<160u>::Compare(base_blob<160u> const&) const |
63 | | |
64 | 22.4k | friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } operator==(base_blob<256u> const&, base_blob<256u> const&) Line | Count | Source | 64 | 22.4k | friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } |
Unexecuted instantiation: operator==(base_blob<160u> const&, base_blob<160u> const&) |
65 | 64.3k | friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } operator!=(base_blob<256u> const&, base_blob<256u> const&) Line | Count | Source | 65 | 64.3k | friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } |
Unexecuted instantiation: operator!=(base_blob<160u> const&, base_blob<160u> const&) |
66 | 13.6k | friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } operator<(base_blob<256u> const&, base_blob<256u> const&) Line | Count | Source | 66 | 13.6k | friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } |
Unexecuted instantiation: operator<(base_blob<160u> const&, base_blob<160u> const&) |
67 | | |
68 | | /** @name Hex representation |
69 | | * |
70 | | * The reverse-byte hex representation is a convenient way to view the blob |
71 | | * as a number, because it is consistent with the way the base_uint class |
72 | | * converts blobs to numbers. |
73 | | * |
74 | | * @note base_uint treats the blob as an array of bytes with the numerically |
75 | | * least significant byte first and the most significant byte last. Because |
76 | | * numbers are typically written with the most significant digit first and |
77 | | * the least significant digit last, the reverse hex display of the blob |
78 | | * corresponds to the same numeric value that base_uint interprets from the |
79 | | * blob. |
80 | | * @{*/ |
81 | | std::string GetHex() const; |
82 | | /** Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated! |
83 | | * |
84 | | * - Hex numbers that don't specify enough bytes to fill the internal array |
85 | | * will be treated as setting the beginning of it, which corresponds to |
86 | | * the least significant bytes when converted to base_uint. |
87 | | * |
88 | | * - Hex numbers specifying too many bytes will have the numerically most |
89 | | * significant bytes (the beginning of the string) narrowed away. |
90 | | * |
91 | | * - An odd count of hex digits will result in the high bits of the leftmost |
92 | | * byte being zero. |
93 | | * "0x123" => {0x23, 0x1, 0x0, ..., 0x0} |
94 | | */ |
95 | | void SetHexDeprecated(std::string_view str); |
96 | | std::string ToString() const; |
97 | | /**@}*/ |
98 | | |
99 | 0 | constexpr const unsigned char* data() const { return m_data.data(); } Unexecuted instantiation: base_blob<256u>::data() const Unexecuted instantiation: base_blob<160u>::data() const |
100 | 230k | constexpr unsigned char* data() { return m_data.data(); } Line | Count | Source | 100 | 230k | constexpr unsigned char* data() { return m_data.data(); } |
Unexecuted instantiation: base_blob<160u>::data() |
101 | | |
102 | 1.10M | constexpr unsigned char* begin() { return m_data.data(); } Line | Count | Source | 102 | 1.10M | constexpr unsigned char* begin() { return m_data.data(); } |
Unexecuted instantiation: base_blob<160u>::begin() |
103 | 0 | constexpr unsigned char* end() { return m_data.data() + WIDTH; } Unexecuted instantiation: base_blob<256u>::end() Unexecuted instantiation: base_blob<160u>::end() |
104 | | |
105 | 185k | constexpr const unsigned char* begin() const { return m_data.data(); } base_blob<256u>::begin() const Line | Count | Source | 105 | 185k | constexpr const unsigned char* begin() const { return m_data.data(); } |
Unexecuted instantiation: base_blob<160u>::begin() const |
106 | 0 | constexpr const unsigned char* end() const { return m_data.data() + WIDTH; } Unexecuted instantiation: base_blob<256u>::end() const Unexecuted instantiation: base_blob<160u>::end() const |
107 | | |
108 | 35.6k | static constexpr unsigned int size() { return WIDTH; } Line | Count | Source | 108 | 35.6k | static constexpr unsigned int size() { return WIDTH; } |
Unexecuted instantiation: base_blob<160u>::size() |
109 | | |
110 | 6.92k | constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); } |
111 | | |
112 | | template<typename Stream> |
113 | | void Serialize(Stream& s) const |
114 | 857k | { |
115 | 857k | s << Span(m_data); |
116 | 857k | } void base_blob<256u>::Serialize<ParamsStream<SizeComputer&, TransactionSerParams> >(ParamsStream<SizeComputer&, TransactionSerParams>&) const Line | Count | Source | 114 | 27.3k | { | 115 | 27.3k | s << Span(m_data); | 116 | 27.3k | } |
void base_blob<256u>::Serialize<DataStream>(DataStream&) const Line | Count | Source | 114 | 6.75k | { | 115 | 6.75k | s << Span(m_data); | 116 | 6.75k | } |
Unexecuted instantiation: void base_blob<256u>::Serialize<ParamsStream<DataStream&, TransactionSerParams> >(ParamsStream<DataStream&, TransactionSerParams>&) const Unexecuted instantiation: void base_blob<256u>::Serialize<SizeComputer>(SizeComputer&) const void base_blob<256u>::Serialize<VectorWriter>(VectorWriter&) const Line | Count | Source | 114 | 6.53k | { | 115 | 6.53k | s << Span(m_data); | 116 | 6.53k | } |
Unexecuted instantiation: void base_blob<160u>::Serialize<DataStream>(DataStream&) const void base_blob<256u>::Serialize<ParamsStream<VectorWriter&, TransactionSerParams> >(ParamsStream<VectorWriter&, TransactionSerParams>&) const Line | Count | Source | 114 | 128k | { | 115 | 128k | s << Span(m_data); | 116 | 128k | } |
void base_blob<256u>::Serialize<ParamsStream<ParamsStream<VectorWriter&, TransactionSerParams>&, TransactionSerParams> >(ParamsStream<ParamsStream<VectorWriter&, TransactionSerParams>&, TransactionSerParams>&) const Line | Count | Source | 114 | 1.68k | { | 115 | 1.68k | s << Span(m_data); | 116 | 1.68k | } |
Unexecuted instantiation: void base_blob<256u>::Serialize<AutoFile>(AutoFile&) const void base_blob<256u>::Serialize<HashWriter>(HashWriter&) const Line | Count | Source | 114 | 670k | { | 115 | 670k | s << Span(m_data); | 116 | 670k | } |
Unexecuted instantiation: void base_blob<256u>::Serialize<ParamsStream<HashedSourceWriter<AutoFile>&, CAddress::SerParams> >(ParamsStream<HashedSourceWriter<AutoFile>&, CAddress::SerParams>&) const Unexecuted instantiation: void base_blob<256u>::Serialize<ParamsStream<DataStream&, CAddress::SerParams> >(ParamsStream<DataStream&, CAddress::SerParams>&) const Unexecuted instantiation: void base_blob<256u>::Serialize<ParamsStream<AutoFile&, TransactionSerParams> >(ParamsStream<AutoFile&, TransactionSerParams>&) const void base_blob<256u>::Serialize<ParamsStream<HashWriter&, TransactionSerParams> >(ParamsStream<HashWriter&, TransactionSerParams>&) const Line | Count | Source | 114 | 17.0k | { | 115 | 17.0k | s << Span(m_data); | 116 | 17.0k | } |
|
117 | | |
118 | | template<typename Stream> |
119 | | void Unserialize(Stream& s) |
120 | 129k | { |
121 | 129k | s.read(MakeWritableByteSpan(m_data)); |
122 | 129k | } void base_blob<256u>::Unserialize<DataStream>(DataStream&) Line | Count | Source | 120 | 107k | { | 121 | 107k | s.read(MakeWritableByteSpan(m_data)); | 122 | 107k | } |
void base_blob<256u>::Unserialize<ParamsStream<DataStream&, TransactionSerParams> >(ParamsStream<DataStream&, TransactionSerParams>&) Line | Count | Source | 120 | 22.2k | { | 121 | 22.2k | s.read(MakeWritableByteSpan(m_data)); | 122 | 22.2k | } |
Unexecuted instantiation: void base_blob<256u>::Unserialize<SpanReader>(SpanReader&) Unexecuted instantiation: void base_blob<160u>::Unserialize<DataStream>(DataStream&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<SpanReader&, TransactionSerParams> >(ParamsStream<SpanReader&, TransactionSerParams>&) Unexecuted instantiation: void base_blob<256u>::Unserialize<AutoFile>(AutoFile&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<AutoFile&, CAddress::SerParams> >(ParamsStream<AutoFile&, CAddress::SerParams>&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<HashVerifier<AutoFile>&, CAddress::SerParams> >(ParamsStream<HashVerifier<AutoFile>&, CAddress::SerParams>&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<DataStream&, CAddress::SerParams> >(ParamsStream<DataStream&, CAddress::SerParams>&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<HashVerifier<DataStream>&, CAddress::SerParams> >(ParamsStream<HashVerifier<DataStream>&, CAddress::SerParams>&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<AutoFile&, TransactionSerParams> >(ParamsStream<AutoFile&, TransactionSerParams>&) Unexecuted instantiation: void base_blob<256u>::Unserialize<BufferedFile>(BufferedFile&) Unexecuted instantiation: void base_blob<256u>::Unserialize<ParamsStream<BufferedFile&, TransactionSerParams> >(ParamsStream<BufferedFile&, TransactionSerParams>&) |
123 | | }; |
124 | | |
125 | | template <unsigned int BITS> |
126 | | consteval base_blob<BITS>::base_blob(std::string_view hex_str) |
127 | | { |
128 | | // Non-lookup table version of HexDigit(). |
129 | | auto from_hex = [](const char c) -> int8_t { |
130 | | if (c >= '0' && c <= '9') return c - '0'; |
131 | | if (c >= 'a' && c <= 'f') return c - 'a' + 0xA; |
132 | | if (c >= 'A' && c <= 'F') return c - 'A' + 0xA; |
133 | | |
134 | | assert(false); // Reached if ctor is called with an invalid hex digit. |
135 | | }; |
136 | | |
137 | | assert(hex_str.length() == m_data.size() * 2); // 2 hex digits per byte. |
138 | | auto str_it = hex_str.rbegin(); |
139 | | for (auto& elem : m_data) { |
140 | | auto lo = from_hex(*(str_it++)); |
141 | | elem = (from_hex(*(str_it++)) << 4) | lo; |
142 | | } |
143 | | } |
144 | | |
145 | | namespace detail { |
146 | | /** |
147 | | * Writes the hex string (in reverse byte order) into a new uintN_t object |
148 | | * and only returns a value iff all of the checks pass: |
149 | | * - Input length is uintN_t::size()*2 |
150 | | * - All characters are hex |
151 | | */ |
152 | | template <class uintN_t> |
153 | | std::optional<uintN_t> FromHex(std::string_view str) |
154 | 0 | { |
155 | 0 | if (uintN_t::size() * 2 != str.size() || !IsHex(str)) return std::nullopt; Branch (155:9): [True: 0, False: 0]
Branch (155:46): [True: 0, False: 0]
|
156 | 0 | uintN_t rv; |
157 | 0 | rv.SetHexDeprecated(str); |
158 | 0 | return rv; |
159 | 0 | } Unexecuted instantiation: std::optional<uint160> detail::FromHex<uint160>(std::basic_string_view<char, std::char_traits<char> >) Unexecuted instantiation: std::optional<uint256> detail::FromHex<uint256>(std::basic_string_view<char, std::char_traits<char> >) |
160 | | } // namespace detail |
161 | | |
162 | | /** 160-bit opaque blob. |
163 | | * @note This type is called uint160 for historical reasons only. It is an opaque |
164 | | * blob of 160 bits and has no integer operations. |
165 | | */ |
166 | | class uint160 : public base_blob<160> { |
167 | | public: |
168 | 0 | static std::optional<uint160> FromHex(std::string_view str) { return detail::FromHex<uint160>(str); } |
169 | 0 | constexpr uint160() = default; |
170 | 0 | constexpr explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {} |
171 | | }; |
172 | | |
173 | | /** 256-bit opaque blob. |
174 | | * @note This type is called uint256 for historical reasons only. It is an |
175 | | * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if |
176 | | * those are required. |
177 | | */ |
178 | | class uint256 : public base_blob<256> { |
179 | | public: |
180 | 0 | static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); } |
181 | 907k | constexpr uint256() = default; |
182 | 0 | consteval explicit uint256(std::string_view hex_str) : base_blob<256>(hex_str) {} |
183 | 0 | constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {} |
184 | 0 | constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {} |
185 | | static const uint256 ZERO; |
186 | | static const uint256 ONE; |
187 | | }; |
188 | | |
189 | | /* uint256 from std::string_view, containing byte-reversed hex encoding. |
190 | | * DEPRECATED. Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated! |
191 | | */ |
192 | | inline uint256 uint256S(std::string_view str) |
193 | 0 | { |
194 | 0 | uint256 rv; |
195 | 0 | rv.SetHexDeprecated(str); |
196 | 0 | return rv; |
197 | 0 | } |
198 | | |
199 | | #endif // BITCOIN_UINT256_H |