Skip to content

Commit 52ddbd5

Browse files
committed
Merge bitcoin/bitcoin#26345: refactor: modernize the implementation of uint256.*
935acdc refactor: modernize the implementation of uint256.* (pasta) Pull request description: - Constructors of uint256 to utilize Span instead of requiring a std::vector - converts m_data into a std::array - Prefers using `WIDTH` instead of `sizeof(m_data)` - make all the things constexpr - replace C style functions with c++ equivalents - memset -> std::fill This may also be replaced by std::memset, but I think that std::fill is more idiomatic of modern c++ and readable. - memcpy -> std::copy Note: In practice, implementations of std::copy avoid multiple assignments and use bulk copy functions such as std::memmove if the value type is TriviallyCopyable and the iterator types satisfy LegacyContiguousIterator. (https://en.cppreference.com/w/cpp/algorithm/copy) This could also likely be replaced by std::memcpy, but as said above, I believe the using std::copy is the more c++ way to do anything and is almost guaranteed to compile to the same asm - memcmp -> std::memcmp ACKs for top commit: achow101: ACK 935acdc hebasto: Approach ACK 935acdc. aureleoules: reACK 935acdc john-moffett: ACK 935acdc stickies-v: Approach ACK 935acdc Tree-SHA512: 4f1ba54ff2198eea0e505d41e73d552c84c60f6878d5c85a94a8ab57f39afc94ef8d79258e7afd01fa84ec2a99f4404bb877eecd671f65e1ee9273f3129fc650
2 parents aff7546 + 935acdc commit 52ddbd5

File tree

6 files changed

+39
-61
lines changed

6 files changed

+39
-61
lines changed

ci/test/06_script_b.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ if [ "${RUN_TIDY}" = "true" ]; then
6060
" src/rpc/signmessage.cpp"\
6161
" src/test/fuzz/txorphan.cpp"\
6262
" src/test/fuzz/util/"\
63+
" src/uint256.cpp"\
6364
" src/util/bip32.cpp"\
6465
" src/util/bytevectorhash.cpp"\
6566
" src/util/check.cpp"\

src/consensus/params.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <chrono>
1212
#include <limits>
1313
#include <map>
14+
#include <vector>
1415

1516
namespace Consensus {
1617

src/psbt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ struct PSBTOutput
889889
} else if (key.size() != 33) {
890890
throw std::ios_base::failure("Output Taproot BIP32 keypath key is not at 33 bytes");
891891
}
892-
XOnlyPubKey xonly(uint256({key.begin() + 1, key.begin() + 33}));
892+
XOnlyPubKey xonly(uint256(Span<uint8_t>(key).last(32)));
893893
std::set<uint256> leaf_hashes;
894894
uint64_t value_len = ReadCompactSize(s);
895895
size_t before_hashes = s.size();

src/random.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <chrono>
1616
#include <cstdint>
1717
#include <limits>
18+
#include <vector>
1819

1920
/**
2021
* Overall design of the RNG and entropy sources.

src/uint256.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,6 @@
77

88
#include <util/strencodings.h>
99

10-
#include <string.h>
11-
12-
template <unsigned int BITS>
13-
base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch)
14-
{
15-
assert(vch.size() == sizeof(m_data));
16-
memcpy(m_data, vch.data(), sizeof(m_data));
17-
}
18-
1910
template <unsigned int BITS>
2011
std::string base_blob<BITS>::GetHex() const
2112
{
@@ -29,7 +20,7 @@ std::string base_blob<BITS>::GetHex() const
2920
template <unsigned int BITS>
3021
void base_blob<BITS>::SetHex(const char* psz)
3122
{
32-
memset(m_data, 0, sizeof(m_data));
23+
std::fill(m_data.begin(), m_data.end(), 0);
3324

3425
// skip leading spaces
3526
while (IsSpace(*psz))
@@ -43,7 +34,7 @@ void base_blob<BITS>::SetHex(const char* psz)
4334
size_t digits = 0;
4435
while (::HexDigit(psz[digits]) != -1)
4536
digits++;
46-
unsigned char* p1 = (unsigned char*)m_data;
37+
unsigned char* p1 = m_data.data();
4738
unsigned char* pend = p1 + WIDTH;
4839
while (digits > 0 && p1 < pend) {
4940
*p1 = ::HexDigit(psz[--digits]);
@@ -67,14 +58,12 @@ std::string base_blob<BITS>::ToString() const
6758
}
6859

6960
// Explicit instantiations for base_blob<160>
70-
template base_blob<160>::base_blob(const std::vector<unsigned char>&);
7161
template std::string base_blob<160>::GetHex() const;
7262
template std::string base_blob<160>::ToString() const;
7363
template void base_blob<160>::SetHex(const char*);
7464
template void base_blob<160>::SetHex(const std::string&);
7565

7666
// Explicit instantiations for base_blob<256>
77-
template base_blob<256>::base_blob(const std::vector<unsigned char>&);
7867
template std::string base_blob<256>::GetHex() const;
7968
template std::string base_blob<256>::ToString() const;
8069
template void base_blob<256>::SetHex(const char*);

src/uint256.h

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,84 +9,70 @@
99
#include <crypto/common.h>
1010
#include <span.h>
1111

12-
#include <assert.h>
12+
#include <algorithm>
13+
#include <array>
14+
#include <cassert>
1315
#include <cstring>
1416
#include <stdint.h>
1517
#include <string>
16-
#include <vector>
1718

1819
/** Template base class for fixed-sized opaque blobs. */
1920
template<unsigned int BITS>
2021
class base_blob
2122
{
2223
protected:
2324
static constexpr int WIDTH = BITS / 8;
24-
uint8_t m_data[WIDTH];
25+
std::array<uint8_t, WIDTH> m_data;
26+
static_assert(WIDTH == sizeof(m_data), "Sanity check");
27+
2528
public:
2629
/* construct 0 value by default */
2730
constexpr base_blob() : m_data() {}
2831

2932
/* constructor for constants between 1 and 255 */
3033
constexpr explicit base_blob(uint8_t v) : m_data{v} {}
3134

32-
explicit base_blob(const std::vector<unsigned char>& vch);
35+
constexpr explicit base_blob(Span<const unsigned char> vch)
36+
{
37+
assert(vch.size() == WIDTH);
38+
std::copy(vch.begin(), vch.end(), m_data.begin());
39+
}
3340

34-
bool IsNull() const
41+
constexpr bool IsNull() const
3542
{
36-
for (int i = 0; i < WIDTH; i++)
37-
if (m_data[i] != 0)
38-
return false;
39-
return true;
43+
return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
44+
return val == 0;
45+
});
4046
}
4147

42-
void SetNull()
48+
constexpr void SetNull()
4349
{
44-
memset(m_data, 0, sizeof(m_data));
50+
std::fill(m_data.begin(), m_data.end(), 0);
4551
}
4652

47-
inline int Compare(const base_blob& other) const { return memcmp(m_data, other.m_data, sizeof(m_data)); }
53+
constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); }
4854

49-
friend inline bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
50-
friend inline bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
51-
friend inline bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }
55+
friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
56+
friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
57+
friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }
5258

5359
std::string GetHex() const;
5460
void SetHex(const char* psz);
5561
void SetHex(const std::string& str);
5662
std::string ToString() const;
5763

58-
const unsigned char* data() const { return m_data; }
59-
unsigned char* data() { return m_data; }
64+
constexpr const unsigned char* data() const { return m_data.data(); }
65+
constexpr unsigned char* data() { return m_data.data(); }
6066

61-
unsigned char* begin()
62-
{
63-
return &m_data[0];
64-
}
67+
constexpr unsigned char* begin() { return m_data.data(); }
68+
constexpr unsigned char* end() { return m_data.data() + WIDTH; }
6569

66-
unsigned char* end()
67-
{
68-
return &m_data[WIDTH];
69-
}
70+
constexpr const unsigned char* begin() const { return m_data.data(); }
71+
constexpr const unsigned char* end() const { return m_data.data() + WIDTH; }
7072

71-
const unsigned char* begin() const
72-
{
73-
return &m_data[0];
74-
}
73+
static constexpr unsigned int size() { return WIDTH; }
7574

76-
const unsigned char* end() const
77-
{
78-
return &m_data[WIDTH];
79-
}
80-
81-
static constexpr unsigned int size()
82-
{
83-
return sizeof(m_data);
84-
}
85-
86-
uint64_t GetUint64(int pos) const
87-
{
88-
return ReadLE64(m_data + pos * 8);
89-
}
75+
constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); }
9076

9177
template<typename Stream>
9278
void Serialize(Stream& s) const
@@ -107,8 +93,8 @@ class base_blob
10793
*/
10894
class uint160 : public base_blob<160> {
10995
public:
110-
constexpr uint160() {}
111-
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {}
96+
constexpr uint160() = default;
97+
constexpr explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {}
11298
};
11399

114100
/** 256-bit opaque blob.
@@ -118,9 +104,9 @@ class uint160 : public base_blob<160> {
118104
*/
119105
class uint256 : public base_blob<256> {
120106
public:
121-
constexpr uint256() {}
107+
constexpr uint256() = default;
122108
constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {}
123-
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
109+
constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {}
124110
static const uint256 ZERO;
125111
static const uint256 ONE;
126112
};

0 commit comments

Comments
 (0)