mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
79a20f96a5
5fc4939e17509534eb36727b27ac0afb941e44f7 Added static_assert to check that base_blob is using whole bytes. (Brotcrunsher) Pull request description: Prior to this commit it was possible to create base_blobs with any arbitrary amount of bits, like base_blob<9>. One could assume that this would be a valid way to create a bit field that guarantees to have at least 9 bits. However, in such a case, base_blob would not behave as expected because the WIDTH is rounded down to the closest whole byte (simple integer division by 8). This commit makes sure that this oddity is detected and blocked by the compiler. ACKs for top commit: MarcoFalke: lgtm ACK 5fc4939e17509534eb36727b27ac0afb941e44f7 theStack: ACK 5fc4939e17509534eb36727b27ac0afb941e44f7 stickies-v: ACK 5fc4939e17509534eb36727b27ac0afb941e44f7 Tree-SHA512: 6a06760f09d4a9e6f0b9338d4dddd4091f2ac59a843a443d9302959936d72c55f7cccd55a51ec3a5a799921f68be1b87968ef3c9c11d3389cbd369b5045bb50a
155 lines
4.7 KiB
C++
155 lines
4.7 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
|
// Copyright (c) 2014-2024 The Dash Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef BITCOIN_UINT256_H
|
|
#define BITCOIN_UINT256_H
|
|
|
|
#include <crypto/common.h>
|
|
#include <span.h>
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <stdint.h>
|
|
#include <string>
|
|
|
|
/** Template base class for fixed-sized opaque blobs. */
|
|
template<unsigned int BITS>
|
|
class base_blob
|
|
{
|
|
protected:
|
|
static constexpr int WIDTH = BITS / 8;
|
|
static_assert(BITS % 8 == 0, "base_blob currently only supports whole bytes.");
|
|
std::array<uint8_t, WIDTH> m_data;
|
|
static_assert(WIDTH == sizeof(m_data), "Sanity check");
|
|
|
|
public:
|
|
/* construct 0 value by default */
|
|
constexpr base_blob() : m_data() {}
|
|
|
|
/* constructor for constants between 1 and 255 */
|
|
constexpr explicit base_blob(uint8_t v) : m_data{v} {}
|
|
|
|
constexpr explicit base_blob(Span<const unsigned char> vch)
|
|
{
|
|
assert(vch.size() == WIDTH);
|
|
std::copy(vch.begin(), vch.end(), m_data.begin());
|
|
}
|
|
|
|
constexpr bool IsNull() const
|
|
{
|
|
return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
|
|
return val == 0;
|
|
});
|
|
}
|
|
|
|
constexpr void SetNull()
|
|
{
|
|
std::fill(m_data.begin(), m_data.end(), 0);
|
|
}
|
|
|
|
constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); }
|
|
|
|
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;
|
|
void SetHex(const char* psz);
|
|
void SetHex(const std::string& str);
|
|
std::string ToString() const;
|
|
|
|
constexpr const unsigned char* data() const { return m_data.data(); }
|
|
constexpr unsigned char* data() { return m_data.data(); }
|
|
|
|
constexpr unsigned char* begin() { return m_data.data(); }
|
|
constexpr unsigned char* end() { return m_data.data() + WIDTH; }
|
|
|
|
constexpr const unsigned char* begin() const { return m_data.data(); }
|
|
constexpr const unsigned char* end() const { return m_data.data() + WIDTH; }
|
|
|
|
static constexpr unsigned int size() { return WIDTH; }
|
|
|
|
constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); }
|
|
|
|
template<typename Stream>
|
|
void Serialize(Stream& s) const
|
|
{
|
|
s.write(MakeByteSpan(m_data));
|
|
}
|
|
|
|
template<typename Stream>
|
|
void Unserialize(Stream& s)
|
|
{
|
|
s.read(MakeWritableByteSpan(m_data));
|
|
}
|
|
};
|
|
|
|
/** 160-bit opaque blob.
|
|
* @note This type is called uint160 for historical reasons only. It is an opaque
|
|
* blob of 160 bits and has no integer operations.
|
|
*/
|
|
class uint160 : public base_blob<160> {
|
|
public:
|
|
constexpr uint160() = default;
|
|
constexpr explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {}
|
|
};
|
|
|
|
/** 256-bit opaque blob.
|
|
* @note This type is called uint256 for historical reasons only. It is an
|
|
* opaque blob of 256 bits and has no integer operations. Use arith_uint256 if
|
|
* those are required.
|
|
*/
|
|
class uint256 : public base_blob<256> {
|
|
public:
|
|
constexpr uint256() = default;
|
|
constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {}
|
|
constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {}
|
|
static const uint256 ZERO;
|
|
static const uint256 ONE;
|
|
static const uint256 TWO;
|
|
};
|
|
|
|
/* uint256 from const char *.
|
|
* This is a separate function because the constructor uint256(const char*) can result
|
|
* in dangerously catching uint256(0).
|
|
*/
|
|
inline uint256 uint256S(const char *str)
|
|
{
|
|
uint256 rv;
|
|
rv.SetHex(str);
|
|
return rv;
|
|
}
|
|
/* uint256 from std::string.
|
|
* This is a separate function because the constructor uint256(const std::string &str) can result
|
|
* in dangerously catching uint256(0) via std::string(const char*).
|
|
*/
|
|
inline uint256 uint256S(const std::string& str)
|
|
{
|
|
uint256 rv;
|
|
rv.SetHex(str);
|
|
return rv;
|
|
}
|
|
|
|
/** 512-bit unsigned big integer. */
|
|
class uint512 : public base_blob<512> {
|
|
public:
|
|
constexpr uint512() = default;
|
|
constexpr uint512(const base_blob<512>& b) : base_blob<512>(b) {}
|
|
constexpr explicit uint512(Span<unsigned char> vch) : base_blob<512>(vch) {}
|
|
|
|
uint256 trim256() const
|
|
{
|
|
uint256 result;
|
|
memcpy((void*)&result, (void*)m_data.data(), 32);
|
|
return result;
|
|
}
|
|
};
|
|
|
|
|
|
#endif // BITCOIN_UINT256_H
|