From 5d3064bc44e0b608a428e230f384bd3f846dedca Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 15 Dec 2014 10:05:51 +0100 Subject: Temporarily add SetNull/IsNull/GetCheapHash to base_uint Also add a stub for arith_uint256 and its conversion functions, for now completely based on uint256. Eases step-by-step migration to blob. --- src/arith_uint256.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/arith_uint256.h (limited to 'src/arith_uint256.h') diff --git a/src/arith_uint256.h b/src/arith_uint256.h new file mode 100644 index 0000000000..3bb384ca8a --- /dev/null +++ b/src/arith_uint256.h @@ -0,0 +1,19 @@ +#ifndef BITCOIN_ARITH_UINT256_H +#define BITCOIN_ARITH_UINT256_H + +// Temporary for migration to opaque uint160/256 +#include "uint256.h" + +class arith_uint256 : public uint256 { +public: + arith_uint256() {} + arith_uint256(const base_uint<256>& b) : uint256(b) {} + arith_uint256(uint64_t b) : uint256(b) {} + explicit arith_uint256(const std::string& str) : uint256(str) {} + explicit arith_uint256(const std::vector& vch) : uint256(vch) {} +}; + +#define ArithToUint256(x) (x) +#define UintToArith256(x) (x) + +#endif // BITCOIN_UINT256_H -- cgit v1.2.3 From bfc6070342b9f43bcf125526e6a3c8ed34e29a71 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 15 Dec 2014 10:22:19 +0100 Subject: uint256->arith_uint256 blob256->uint256 Introduce new opaque implementation of `uint256`, move old "arithmetic" implementation to `arith_uint256. --- src/arith_uint256.h | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 341 insertions(+), 10 deletions(-) (limited to 'src/arith_uint256.h') diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 3bb384ca8a..9e32b124c2 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -1,19 +1,350 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_ARITH_UINT256_H #define BITCOIN_ARITH_UINT256_H -// Temporary for migration to opaque uint160/256 -#include "uint256.h" +#include +#include +#include +#include +#include +#include -class arith_uint256 : public uint256 { +class uint_error : public std::runtime_error { public: - arith_uint256() {} - arith_uint256(const base_uint<256>& b) : uint256(b) {} - arith_uint256(uint64_t b) : uint256(b) {} - explicit arith_uint256(const std::string& str) : uint256(str) {} - explicit arith_uint256(const std::vector& vch) : uint256(vch) {} + explicit uint_error(const std::string& str) : std::runtime_error(str) {} +}; + +/** Template base class for unsigned big integers. */ +template +class base_uint +{ +protected: + enum { WIDTH=BITS/32 }; + uint32_t pn[WIDTH]; +public: + + base_uint() + { + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + } + + base_uint(const base_uint& b) + { + 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& vch); + + bool operator!() const + { + for (int i = 0; i < WIDTH; i++) + if (pn[i] != 0) + return false; + return true; + } + + const base_uint operator~() const + { + base_uint ret; + for (int i = 0; i < WIDTH; i++) + ret.pn[i] = ~pn[i]; + return ret; + } + + 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); } + + std::string GetHex() const; + void SetHex(const char* psz); + void SetHex(const std::string& str); + std::string ToString() const; + + unsigned char* begin() + { + return (unsigned char*)&pn[0]; + } + + unsigned char* end() + { + return (unsigned char*)&pn[WIDTH]; + } + + const unsigned char* begin() const + { + return (unsigned char*)&pn[0]; + } + + const unsigned char* end() const + { + return (unsigned char*)&pn[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; + } + + unsigned int GetSerializeSize(int nType, int nVersion) const + { + return sizeof(pn); + } + + template + void Serialize(Stream& s, int nType, int nVersion) const + { + s.write((char*)pn, sizeof(pn)); + } + + template + void Unserialize(Stream& s, int nType, int nVersion) + { + s.read((char*)pn, sizeof(pn)); + } + + // Temporary for migration to blob160/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; + } }; -#define ArithToUint256(x) (x) -#define UintToArith256(x) (x) +/** 160-bit unsigned big integer. */ +class arith_uint160 : public base_uint<160> { +public: + arith_uint160() {} + arith_uint160(const base_uint<160>& b) : base_uint<160>(b) {} + arith_uint160(uint64_t b) : base_uint<160>(b) {} + explicit arith_uint160(const std::string& str) : base_uint<160>(str) {} + explicit arith_uint160(const std::vector& vch) : base_uint<160>(vch) {} +}; + +/** 256-bit unsigned big integer. */ +class arith_uint256 : public base_uint<256> { +public: + arith_uint256() {} + arith_uint256(const base_uint<256>& b) : base_uint<256>(b) {} + arith_uint256(uint64_t b) : base_uint<256>(b) {} + explicit arith_uint256(const std::string& str) : base_uint<256>(str) {} + explicit arith_uint256(const std::vector& 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. + */ + arith_uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); + uint32_t GetCompact(bool fNegative = false) const; + + uint64_t GetHash(const arith_uint256& salt) const; +}; #endif // BITCOIN_UINT256_H -- cgit v1.2.3 From 92cdb1aace3c7343e9c9472061508d3b01d9883d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 Dec 2014 17:29:51 +0100 Subject: Add conversion functions arith_uint256<->uint_256 --- src/arith_uint256.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/arith_uint256.h') diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 9e32b124c2..5cb04f3c3c 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -13,6 +13,8 @@ #include #include +class uint256; + class uint_error : public std::runtime_error { public: explicit uint_error(const std::string& str) : std::runtime_error(str) {} @@ -345,6 +347,12 @@ public: uint32_t GetCompact(bool fNegative = false) const; uint64_t GetHash(const arith_uint256& salt) const; + + friend uint256 ArithToUint256(const arith_uint256 &); + friend arith_uint256 UintToArith256(const uint256 &); }; +uint256 ArithToUint256(const arith_uint256 &); +arith_uint256 UintToArith256(const uint256 &); + #endif // BITCOIN_UINT256_H -- cgit v1.2.3 From edc720479d0749a000d5a6970da6d2d72657cf38 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 Dec 2014 15:44:57 +0100 Subject: Remove arith_uint160 We never do 160-bit arithmetic. --- src/arith_uint256.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src/arith_uint256.h') diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 5cb04f3c3c..b69eef6769 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -304,16 +304,6 @@ public: } }; -/** 160-bit unsigned big integer. */ -class arith_uint160 : public base_uint<160> { -public: - arith_uint160() {} - arith_uint160(const base_uint<160>& b) : base_uint<160>(b) {} - arith_uint160(uint64_t b) : base_uint<160>(b) {} - explicit arith_uint160(const std::string& str) : base_uint<160>(str) {} - explicit arith_uint160(const std::vector& vch) : base_uint<160>(vch) {} -}; - /** 256-bit unsigned big integer. */ class arith_uint256 : public base_uint<256> { public: -- cgit v1.2.3 From 30007fda76aa7ba4e4090f7a16298874a7722926 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 Dec 2014 15:47:29 +0100 Subject: Remove now-unused methods from arith_uint256 and base_uint - Methods that access the guts of arith_uint256 are removed, as these are incompatible between endians. Use uint256 instead - Serialization is no longer needed as arith_uint256's are never read or written - GetHash is never used on arith_uint256 --- src/arith_uint256.h | 56 ----------------------------------------------------- 1 file changed, 56 deletions(-) (limited to 'src/arith_uint256.h') diff --git a/src/arith_uint256.h b/src/arith_uint256.h index b69eef6769..ec8e15997f 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -232,26 +232,6 @@ public: void SetHex(const std::string& str); std::string ToString() const; - unsigned char* begin() - { - return (unsigned char*)&pn[0]; - } - - unsigned char* end() - { - return (unsigned char*)&pn[WIDTH]; - } - - const unsigned char* begin() const - { - return (unsigned char*)&pn[0]; - } - - const unsigned char* end() const - { - return (unsigned char*)&pn[WIDTH]; - } - unsigned int size() const { return sizeof(pn); @@ -268,40 +248,6 @@ public: assert(WIDTH >= 2); return pn[0] | (uint64_t)pn[1] << 32; } - - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return sizeof(pn); - } - - template - void Serialize(Stream& s, int nType, int nVersion) const - { - s.write((char*)pn, sizeof(pn)); - } - - template - void Unserialize(Stream& s, int nType, int nVersion) - { - s.read((char*)pn, sizeof(pn)); - } - - // Temporary for migration to blob160/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; - } }; /** 256-bit unsigned big integer. */ @@ -336,8 +282,6 @@ public: arith_uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); uint32_t GetCompact(bool fNegative = false) const; - uint64_t GetHash(const arith_uint256& salt) const; - friend uint256 ArithToUint256(const arith_uint256 &); friend arith_uint256 UintToArith256(const uint256 &); }; -- cgit v1.2.3 From 6bd0dc2a845b4d17d5ffabbdadda80d47d6c2dc3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 19 Dec 2014 13:07:07 +0100 Subject: arith_uint256: remove initialization from byte vector Remove initialization from vector (as this is only used in the tests). Also implement SetHex and GetHex in terms of uint256, to avoid duplicate code as well as avoid endianness issues (as they work in term of bytes). --- src/arith_uint256.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/arith_uint256.h') diff --git a/src/arith_uint256.h b/src/arith_uint256.h index ec8e15997f..b6ba3a1087 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -57,7 +57,6 @@ public: } explicit base_uint(const std::string& str); - explicit base_uint(const std::vector& vch); bool operator!() const { @@ -257,7 +256,6 @@ public: arith_uint256(const base_uint<256>& b) : base_uint<256>(b) {} arith_uint256(uint64_t b) : base_uint<256>(b) {} explicit arith_uint256(const std::string& str) : base_uint<256>(str) {} - explicit arith_uint256(const std::vector& vch) : base_uint<256>(vch) {} /** * The "compact" format is a representation of a whole -- cgit v1.2.3