Merge bitcoin/bitcoin#26345: refactor: modernize the implementation of uint256.*

935acdcc79d1dc5ac04a83b92e5919ddbfa29329 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 935acdcc79d1dc5ac04a83b92e5919ddbfa29329
  hebasto:
    Approach ACK 935acdcc79d1dc5ac04a83b92e5919ddbfa29329.
  aureleoules:
    reACK 935acdcc79d1dc5ac04a83b92e5919ddbfa29329
  john-moffett:
    ACK 935acdcc79d1dc5ac04a83b92e5919ddbfa29329
  stickies-v:
    Approach ACK 935acdcc7

Tree-SHA512: 4f1ba54ff2198eea0e505d41e73d552c84c60f6878d5c85a94a8ab57f39afc94ef8d79258e7afd01fa84ec2a99f4404bb877eecd671f65e1ee9273f3129fc650
This commit is contained in:
Andrew Chow 2023-02-06 13:56:32 -05:00 committed by PastaPastaPasta
parent 44e2edff1d
commit 5ad6088c93
4 changed files with 42 additions and 64 deletions

View File

@ -10,6 +10,7 @@
#include <llmq/params.h> #include <llmq/params.h>
#include <limits> #include <limits>
#include <vector>
namespace Consensus { namespace Consensus {

View File

@ -13,6 +13,7 @@
#include <chrono> // For std::chrono::microseconds #include <chrono> // For std::chrono::microseconds
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <vector>
/** /**
* Overall design of the RNG and entropy sources. * Overall design of the RNG and entropy sources.

View File

@ -7,15 +7,6 @@
#include <util/strencodings.h> #include <util/strencodings.h>
#include <string.h>
template <unsigned int BITS>
base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch)
{
assert(vch.size() == sizeof(m_data));
memcpy(m_data, vch.data(), sizeof(m_data));
}
template <unsigned int BITS> template <unsigned int BITS>
std::string base_blob<BITS>::GetHex() const std::string base_blob<BITS>::GetHex() const
{ {
@ -29,7 +20,7 @@ std::string base_blob<BITS>::GetHex() const
template <unsigned int BITS> template <unsigned int BITS>
void base_blob<BITS>::SetHex(const char* psz) void base_blob<BITS>::SetHex(const char* psz)
{ {
memset(m_data, 0, sizeof(m_data)); std::fill(m_data.begin(), m_data.end(), 0);
// skip leading spaces // skip leading spaces
while (IsSpace(*psz)) while (IsSpace(*psz))
@ -43,7 +34,7 @@ void base_blob<BITS>::SetHex(const char* psz)
size_t digits = 0; size_t digits = 0;
while (::HexDigit(psz[digits]) != -1) while (::HexDigit(psz[digits]) != -1)
digits++; digits++;
unsigned char* p1 = (unsigned char*)m_data; unsigned char* p1 = m_data.data();
unsigned char* pend = p1 + WIDTH; unsigned char* pend = p1 + WIDTH;
while (digits > 0 && p1 < pend) { while (digits > 0 && p1 < pend) {
*p1 = ::HexDigit(psz[--digits]); *p1 = ::HexDigit(psz[--digits]);
@ -67,14 +58,12 @@ std::string base_blob<BITS>::ToString() const
} }
// Explicit instantiations for base_blob<160> // Explicit instantiations for base_blob<160>
template base_blob<160>::base_blob(const std::vector<unsigned char>&);
template std::string base_blob<160>::GetHex() const; template std::string base_blob<160>::GetHex() const;
template std::string base_blob<160>::ToString() const; template std::string base_blob<160>::ToString() const;
template void base_blob<160>::SetHex(const char*); template void base_blob<160>::SetHex(const char*);
template void base_blob<160>::SetHex(const std::string&); template void base_blob<160>::SetHex(const std::string&);
// Explicit instantiations for base_blob<256> // Explicit instantiations for base_blob<256>
template base_blob<256>::base_blob(const std::vector<unsigned char>&);
template std::string base_blob<256>::GetHex() const; template std::string base_blob<256>::GetHex() const;
template std::string base_blob<256>::ToString() const; template std::string base_blob<256>::ToString() const;
template void base_blob<256>::SetHex(const char*); template void base_blob<256>::SetHex(const char*);

View File

@ -8,12 +8,14 @@
#define BITCOIN_UINT256_H #define BITCOIN_UINT256_H
#include <crypto/common.h> #include <crypto/common.h>
#include <span.h>
#include <assert.h> #include <algorithm>
#include <array>
#include <cassert>
#include <cstring> #include <cstring>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <vector>
/** Template base class for fixed-sized opaque blobs. */ /** Template base class for fixed-sized opaque blobs. */
template<unsigned int BITS> template<unsigned int BITS>
@ -21,7 +23,9 @@ class base_blob
{ {
protected: protected:
static constexpr int WIDTH = BITS / 8; static constexpr int WIDTH = BITS / 8;
uint8_t m_data[WIDTH]; std::array<uint8_t, WIDTH> m_data;
static_assert(WIDTH == sizeof(m_data), "Sanity check");
public: public:
/* construct 0 value by default */ /* construct 0 value by default */
constexpr base_blob() : m_data() {} constexpr base_blob() : m_data() {}
@ -29,75 +33,58 @@ public:
/* constructor for constants between 1 and 255 */ /* constructor for constants between 1 and 255 */
constexpr explicit base_blob(uint8_t v) : m_data{v} {} constexpr explicit base_blob(uint8_t v) : m_data{v} {}
explicit base_blob(const std::vector<unsigned char>& vch); constexpr explicit base_blob(Span<const unsigned char> vch)
bool IsNull() const
{ {
for (int i = 0; i < WIDTH; i++) assert(vch.size() == WIDTH);
if (m_data[i] != 0) std::copy(vch.begin(), vch.end(), m_data.begin());
return false;
return true;
} }
void SetNull() constexpr bool IsNull() const
{ {
memset(m_data, 0, sizeof(m_data)); return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
return val == 0;
});
} }
inline int Compare(const base_blob& other) const { return memcmp(m_data, other.m_data, sizeof(m_data)); } constexpr void SetNull()
{
std::fill(m_data.begin(), m_data.end(), 0);
}
friend inline bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); }
friend inline bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
friend inline bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }
std::string GetHex() const; std::string GetHex() const;
void SetHex(const char* psz); void SetHex(const char* psz);
void SetHex(const std::string& str); void SetHex(const std::string& str);
std::string ToString() const; std::string ToString() const;
const unsigned char* data() const { return m_data; } constexpr const unsigned char* data() const { return m_data.data(); }
unsigned char* data() { return m_data; } constexpr unsigned char* data() { return m_data.data(); }
unsigned char* begin() constexpr unsigned char* begin() { return m_data.data(); }
{ constexpr unsigned char* end() { return m_data.data() + WIDTH; }
return &m_data[0];
}
unsigned char* end() constexpr const unsigned char* begin() const { return m_data.data(); }
{ constexpr const unsigned char* end() const { return m_data.data() + WIDTH; }
return &m_data[WIDTH];
}
const unsigned char* begin() const static constexpr unsigned int size() { return WIDTH; }
{
return &m_data[0];
}
const unsigned char* end() const constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); }
{
return &m_data[WIDTH];
}
unsigned int size() const
{
return sizeof(m_data);
}
uint64_t GetUint64(int pos) const
{
return ReadLE64(m_data + pos * 8);
}
template<typename Stream> template<typename Stream>
void Serialize(Stream& s) const void Serialize(Stream& s) const
{ {
s.write((char*)m_data, sizeof(m_data)); s.write((char*)m_data.data(), sizeof(m_data));
} }
template<typename Stream> template<typename Stream>
void Unserialize(Stream& s) void Unserialize(Stream& s)
{ {
s.read((char*)m_data, sizeof(m_data)); s.read((char*)m_data.data(), sizeof(m_data));
} }
}; };
@ -107,8 +94,8 @@ public:
*/ */
class uint160 : public base_blob<160> { class uint160 : public base_blob<160> {
public: public:
constexpr uint160() {} constexpr uint160() = default;
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {} constexpr explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {}
}; };
/** 256-bit opaque blob. /** 256-bit opaque blob.
@ -118,9 +105,9 @@ public:
*/ */
class uint256 : public base_blob<256> { class uint256 : public base_blob<256> {
public: public:
constexpr uint256() {} constexpr uint256() = default;
constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {} constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {}
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {} constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {}
static const uint256 ZERO; static const uint256 ZERO;
static const uint256 ONE; static const uint256 ONE;
static const uint256 TWO; static const uint256 TWO;
@ -157,7 +144,7 @@ public:
uint256 trim256() const uint256 trim256() const
{ {
uint256 result; uint256 result;
memcpy((void*)&result, (void*)m_data, 32); memcpy((void*)&result, (void*)m_data.data(), 32);
return result; return result;
} }
}; };