mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 15:09:59 +01:00
uint256->arith_uint256 blob256->uint256
Introduce new opaque implementation of `uint256`, move old "arithmetic" implementation to `arith_uint256.
This commit is contained in:
343
src/uint256.h
343
src/uint256.h
@@ -13,217 +13,37 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class uint_error : public std::runtime_error {
|
||||
public:
|
||||
explicit uint_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
/** Template base class for unsigned big integers. */
|
||||
/** Template base class for fixed-sized opaque blobs. */
|
||||
template<unsigned int BITS>
|
||||
class base_uint
|
||||
class base_blob
|
||||
{
|
||||
protected:
|
||||
enum { WIDTH=BITS/32 };
|
||||
uint32_t pn[WIDTH];
|
||||
enum { WIDTH=BITS/8 };
|
||||
uint8_t data[WIDTH];
|
||||
public:
|
||||
|
||||
base_uint()
|
||||
base_blob()
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
memset(data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
base_uint(const base_uint& b)
|
||||
explicit base_blob(const std::vector<unsigned char>& vch);
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
base_uint& operator=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
explicit base_uint(const std::string& str);
|
||||
explicit base_uint(const std::vector<unsigned char>& vch);
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
if (pn[i] != 0)
|
||||
if (data[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const base_uint operator~() const
|
||||
void SetNull()
|
||||
{
|
||||
base_uint ret;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
ret.pn[i] = ~pn[i];
|
||||
return ret;
|
||||
memset(data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
const base_uint operator-() const
|
||||
{
|
||||
base_uint ret;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
ret.pn[i] = ~pn[i];
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
double getdouble() const;
|
||||
|
||||
base_uint& operator=(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator^=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] ^= b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator&=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] &= b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator|=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] |= b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator^=(uint64_t b)
|
||||
{
|
||||
pn[0] ^= (unsigned int)b;
|
||||
pn[1] ^= (unsigned int)(b >> 32);
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator|=(uint64_t b)
|
||||
{
|
||||
pn[0] |= (unsigned int)b;
|
||||
pn[1] |= (unsigned int)(b >> 32);
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator<<=(unsigned int shift);
|
||||
base_uint& operator>>=(unsigned int shift);
|
||||
|
||||
base_uint& operator+=(const base_uint& b)
|
||||
{
|
||||
uint64_t carry = 0;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
uint64_t n = carry + pn[i] + b.pn[i];
|
||||
pn[i] = n & 0xffffffff;
|
||||
carry = n >> 32;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator-=(const base_uint& b)
|
||||
{
|
||||
*this += -b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator+=(uint64_t b64)
|
||||
{
|
||||
base_uint b;
|
||||
b = b64;
|
||||
*this += b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator-=(uint64_t b64)
|
||||
{
|
||||
base_uint b;
|
||||
b = b64;
|
||||
*this += -b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator*=(uint32_t b32);
|
||||
base_uint& operator*=(const base_uint& b);
|
||||
base_uint& operator/=(const base_uint& b);
|
||||
|
||||
base_uint& operator++()
|
||||
{
|
||||
// prefix operator
|
||||
int i = 0;
|
||||
while (++pn[i] == 0 && i < WIDTH-1)
|
||||
i++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base_uint operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
const base_uint ret = *this;
|
||||
++(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
base_uint& operator--()
|
||||
{
|
||||
// prefix operator
|
||||
int i = 0;
|
||||
while (--pn[i] == (uint32_t)-1 && i < WIDTH-1)
|
||||
i++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base_uint operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
const base_uint ret = *this;
|
||||
--(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CompareTo(const base_uint& b) const;
|
||||
bool EqualTo(uint64_t b) const;
|
||||
|
||||
friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
|
||||
friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
|
||||
friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; }
|
||||
friend inline const base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; }
|
||||
friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; }
|
||||
friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; }
|
||||
friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; }
|
||||
friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
|
||||
friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
|
||||
friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
|
||||
friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; }
|
||||
friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; }
|
||||
friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; }
|
||||
friend inline bool operator<(const base_uint& a, const base_uint& b) { return a.CompareTo(b) < 0; }
|
||||
friend inline bool operator>=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) >= 0; }
|
||||
friend inline bool operator<=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) <= 0; }
|
||||
friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); }
|
||||
friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); }
|
||||
friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; }
|
||||
friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; }
|
||||
friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; }
|
||||
|
||||
std::string GetHex() const;
|
||||
void SetHex(const char* psz);
|
||||
@@ -232,122 +52,107 @@ public:
|
||||
|
||||
unsigned char* begin()
|
||||
{
|
||||
return (unsigned char*)&pn[0];
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
unsigned char* end()
|
||||
{
|
||||
return (unsigned char*)&pn[WIDTH];
|
||||
return &data[WIDTH];
|
||||
}
|
||||
|
||||
const unsigned char* begin() const
|
||||
{
|
||||
return (unsigned char*)&pn[0];
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
const unsigned char* end() const
|
||||
{
|
||||
return (unsigned char*)&pn[WIDTH];
|
||||
return &data[WIDTH];
|
||||
}
|
||||
|
||||
unsigned int size() const
|
||||
{
|
||||
return sizeof(pn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the highest bit set plus one, or zero if the
|
||||
* value is zero.
|
||||
*/
|
||||
unsigned int bits() const;
|
||||
|
||||
uint64_t GetLow64() const
|
||||
{
|
||||
assert(WIDTH >= 2);
|
||||
return pn[0] | (uint64_t)pn[1] << 32;
|
||||
return sizeof(data);
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const
|
||||
{
|
||||
return sizeof(pn);
|
||||
return sizeof(data);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType, int nVersion) const
|
||||
{
|
||||
s.write((char*)pn, sizeof(pn));
|
||||
s.write((char*)data, sizeof(data));
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType, int nVersion)
|
||||
{
|
||||
s.read((char*)pn, sizeof(pn));
|
||||
}
|
||||
|
||||
// Temporary for migration to opaque uint160/256
|
||||
uint64_t GetCheapHash() const
|
||||
{
|
||||
return GetLow64();
|
||||
}
|
||||
void SetNull()
|
||||
{
|
||||
memset(pn, 0, sizeof(pn));
|
||||
}
|
||||
bool IsNull() const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
if (pn[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
s.read((char*)data, sizeof(data));
|
||||
}
|
||||
};
|
||||
|
||||
/** 160-bit unsigned big integer. */
|
||||
class uint160 : public base_uint<160> {
|
||||
/** 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:
|
||||
uint160() {}
|
||||
uint160(const base_uint<160>& b) : base_uint<160>(b) {}
|
||||
uint160(uint64_t b) : base_uint<160>(b) {}
|
||||
explicit uint160(const std::string& str) : base_uint<160>(str) {}
|
||||
explicit uint160(const std::vector<unsigned char>& vch) : base_uint<160>(vch) {}
|
||||
uint160(const base_blob<160>& b) : base_blob<160>(b) {}
|
||||
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {}
|
||||
};
|
||||
|
||||
/** 256-bit unsigned big integer. */
|
||||
class uint256 : public base_uint<256> {
|
||||
/** 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:
|
||||
uint256() {}
|
||||
uint256(const base_uint<256>& b) : base_uint<256>(b) {}
|
||||
uint256(uint64_t b) : base_uint<256>(b) {}
|
||||
explicit uint256(const std::string& str) : base_uint<256>(str) {}
|
||||
explicit uint256(const std::vector<unsigned char>& vch) : base_uint<256>(vch) {}
|
||||
|
||||
/**
|
||||
* The "compact" format is a representation of a whole
|
||||
* number N using an unsigned 32bit number similar to a
|
||||
* floating point format.
|
||||
* The most significant 8 bits are the unsigned exponent of base 256.
|
||||
* This exponent can be thought of as "number of bytes of N".
|
||||
* The lower 23 bits are the mantissa.
|
||||
* Bit number 24 (0x800000) represents the sign of N.
|
||||
* N = (-1^sign) * mantissa * 256^(exponent-3)
|
||||
*
|
||||
* Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn().
|
||||
* MPI uses the most significant bit of the first byte as sign.
|
||||
* Thus 0x1234560000 is compact (0x05123456)
|
||||
* and 0xc0de000000 is compact (0x0600c0de)
|
||||
*
|
||||
* Bitcoin only uses this "compact" format for encoding difficulty
|
||||
* targets, which are unsigned 256bit quantities. Thus, all the
|
||||
* complexities of the sign bit and using base 256 are probably an
|
||||
* implementation accident.
|
||||
*/
|
||||
uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL);
|
||||
uint32_t GetCompact(bool fNegative = false) const;
|
||||
uint256(const base_blob<256>& b) : base_blob<256>(b) {}
|
||||
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
|
||||
|
||||
/** A cheap hash function that just returns 64 bits from the result, it can be
|
||||
* used when the contents are considered uniformly random. It is not appropriate
|
||||
* when the value can easily be influenced from outside as e.g. a network adversary could
|
||||
* provide values to trigger worst-case behavior.
|
||||
* @note The result of this function is not stable between little and big endian.
|
||||
*/
|
||||
uint64_t GetCheapHash() const
|
||||
{
|
||||
uint64_t result;
|
||||
memcpy((void*)&result, (void*)data, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** A more secure, salted hash function.
|
||||
* @note This hash is not stable between little and big endian.
|
||||
*/
|
||||
uint64_t GetHash(const uint256& salt) const;
|
||||
};
|
||||
|
||||
// Temporary for migration to opaque uint160/256
|
||||
inline uint256 uint256S(const std::string &x) { return uint256(x); }
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif // BITCOIN_UINT256_H
|
||||
|
||||
Reference in New Issue
Block a user