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: [PATCH] uint256->arith_uint256 blob256->uint256 Introduce new opaque implementation of `uint256`, move old "arithmetic" implementation to `arith_uint256. --- src/Makefile.am | 31 +- src/Makefile.test.include | 2 +- src/arith_uint256.cpp | 357 ++++++++++++++++++ src/arith_uint256.h | 351 ++++++++++++++++- ...t256_tests.cpp => arith_uint256_tests.cpp} | 331 ++++++++-------- src/uint256.cpp | 281 ++------------ src/uint256.h | 343 ++++------------- 7 files changed, 990 insertions(+), 706 deletions(-) create mode 100644 src/arith_uint256.cpp rename src/test/{uint256_tests.cpp => arith_uint256_tests.cpp} (75%) diff --git a/src/Makefile.am b/src/Makefile.am index d6ac6e12..bc2b1aff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,11 +74,12 @@ BITCOIN_CORE_H = \ alert.h \ allocators.h \ amount.h \ + arith_uint256.h \ base58.h \ bloom.h \ chain.h \ - chainparams.h \ chainparamsbase.h \ + chainparams.h \ chainparamsseeds.h \ checkpoints.h \ checkqueue.h \ @@ -87,8 +88,6 @@ BITCOIN_CORE_H = \ coins.h \ compat.h \ compressor.h \ - primitives/block.h \ - primitives/transaction.h \ core_io.h \ crypter.h \ db.h \ @@ -108,6 +107,8 @@ BITCOIN_CORE_H = \ net.h \ noui.h \ pow.h \ + primitives/block.h \ + primitives/transaction.h \ protocol.h \ pubkey.h \ random.h \ @@ -115,11 +116,11 @@ BITCOIN_CORE_H = \ rpcprotocol.h \ rpcserver.h \ script/interpreter.h \ + script/script_error.h \ script/script.h \ script/sigcache.h \ script/sign.h \ script/standard.h \ - script/script_error.h \ serialize.h \ streams.h \ sync.h \ @@ -132,13 +133,13 @@ BITCOIN_CORE_H = \ uint256.h \ undo.h \ util.h \ - utilstrencodings.h \ utilmoneystr.h \ + utilstrencodings.h \ utiltime.h \ version.h \ + walletdb.h \ wallet.h \ wallet_ismine.h \ - walletdb.h \ compat/sanity.h JSON_H = \ @@ -261,18 +262,19 @@ libbitcoin_common_a_SOURCES = \ # backward-compatibility objects and their sanity checks are linked. libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_util_a_SOURCES = \ - compat/strnlen.cpp \ - compat/glibc_sanity.cpp \ - compat/glibcxx_sanity.cpp \ + arith_uint256.cpp \ chainparamsbase.cpp \ clientversion.cpp \ + compat/glibc_sanity.cpp \ + compat/glibcxx_sanity.cpp \ + compat/strnlen.cpp \ random.cpp \ rpcprotocol.cpp \ sync.cpp \ uint256.cpp \ util.cpp \ - utilstrencodings.cpp \ utilmoneystr.cpp \ + utilstrencodings.cpp \ utiltime.cpp \ $(BITCOIN_CORE_H) @@ -352,19 +354,20 @@ bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if BUILD_BITCOIN_LIBS include_HEADERS = script/bitcoinconsensus.h libbitcoinconsensus_la_SOURCES = \ - primitives/transaction.cpp \ + arith_uint256.cpp \ crypto/hmac_sha512.cpp \ + crypto/ripemd160.cpp \ crypto/sha1.cpp \ crypto/sha256.cpp \ crypto/sha512.cpp \ - crypto/ripemd160.cpp \ eccryptoverify.cpp \ ecwrapper.cpp \ hash.cpp \ + primitives/transaction.cpp \ pubkey.cpp \ - script/script.cpp \ - script/interpreter.cpp \ script/bitcoinconsensus.cpp \ + script/interpreter.cpp \ + script/script.cpp \ uint256.cpp \ utilstrencodings.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 5f388e28..21d91acc 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -34,6 +34,7 @@ RAW_TEST_FILES = test/data/alertTests.raw GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TESTS =\ + test/arith_uint256_tests.cpp \ test/bignum.h \ test/alert_tests.cpp \ test/allocator_tests.cpp \ @@ -67,7 +68,6 @@ BITCOIN_TESTS =\ test/test_bitcoin.cpp \ test/timedata_tests.cpp \ test/transaction_tests.cpp \ - test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp new file mode 100644 index 00000000..0dba429a --- /dev/null +++ b/src/arith_uint256.cpp @@ -0,0 +1,357 @@ +// 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. + +#include "arith_uint256.h" + +#include "utilstrencodings.h" + +#include +#include + +template +base_uint::base_uint(const std::string& str) +{ + SetHex(str); +} + +template +base_uint::base_uint(const std::vector& vch) +{ + if (vch.size() != sizeof(pn)) + throw uint_error("Converting vector of wrong size to base_uint"); + memcpy(pn, &vch[0], sizeof(pn)); +} + +template +base_uint& base_uint::operator<<=(unsigned int shift) +{ + base_uint a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) { + if (i + k + 1 < WIDTH && shift != 0) + pn[i + k + 1] |= (a.pn[i] >> (32 - shift)); + if (i + k < WIDTH) + pn[i + k] |= (a.pn[i] << shift); + } + return *this; +} + +template +base_uint& base_uint::operator>>=(unsigned int shift) +{ + base_uint a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) { + if (i - k - 1 >= 0 && shift != 0) + pn[i - k - 1] |= (a.pn[i] << (32 - shift)); + if (i - k >= 0) + pn[i - k] |= (a.pn[i] >> shift); + } + return *this; +} + +template +base_uint& base_uint::operator*=(uint32_t b32) +{ + uint64_t carry = 0; + for (int i = 0; i < WIDTH; i++) { + uint64_t n = carry + (uint64_t)b32 * pn[i]; + pn[i] = n & 0xffffffff; + carry = n >> 32; + } + return *this; +} + +template +base_uint& base_uint::operator*=(const base_uint& b) +{ + base_uint a = *this; + *this = 0; + for (int j = 0; j < WIDTH; j++) { + uint64_t carry = 0; + for (int i = 0; i + j < WIDTH; i++) { + uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i]; + pn[i + j] = n & 0xffffffff; + carry = n >> 32; + } + } + return *this; +} + +template +base_uint& base_uint::operator/=(const base_uint& b) +{ + base_uint div = b; // make a copy, so we can shift. + base_uint num = *this; // make a copy, so we can subtract. + *this = 0; // the quotient. + int num_bits = num.bits(); + int div_bits = div.bits(); + if (div_bits == 0) + throw uint_error("Division by zero"); + if (div_bits > num_bits) // the result is certainly 0. + return *this; + int shift = num_bits - div_bits; + div <<= shift; // shift so that div and num align. + while (shift >= 0) { + if (num >= div) { + num -= div; + pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result. + } + div >>= 1; // shift back. + shift--; + } + // num now contains the remainder of the division. + return *this; +} + +template +int base_uint::CompareTo(const base_uint& b) const +{ + for (int i = WIDTH - 1; i >= 0; i--) { + if (pn[i] < b.pn[i]) + return -1; + if (pn[i] > b.pn[i]) + return 1; + } + return 0; +} + +template +bool base_uint::EqualTo(uint64_t b) const +{ + for (int i = WIDTH - 1; i >= 2; i--) { + if (pn[i]) + return false; + } + if (pn[1] != (b >> 32)) + return false; + if (pn[0] != (b & 0xfffffffful)) + return false; + return true; +} + +template +double base_uint::getdouble() const +{ + double ret = 0.0; + double fact = 1.0; + for (int i = 0; i < WIDTH; i++) { + ret += fact * pn[i]; + fact *= 4294967296.0; + } + return ret; +} + +template +std::string base_uint::GetHex() const +{ + char psz[sizeof(pn) * 2 + 1]; + for (unsigned int i = 0; i < sizeof(pn); i++) + sprintf(psz + i * 2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); + return std::string(psz, psz + sizeof(pn) * 2); +} + +template +void base_uint::SetHex(const char* psz) +{ + memset(pn, 0, sizeof(pn)); + + // skip leading spaces + while (isspace(*psz)) + psz++; + + // skip 0x + if (psz[0] == '0' && tolower(psz[1]) == 'x') + psz += 2; + + // hex string to uint + const char* pbegin = psz; + while (::HexDigit(*psz) != -1) + psz++; + psz--; + unsigned char* p1 = (unsigned char*)pn; + unsigned char* pend = p1 + WIDTH * 4; + while (psz >= pbegin && p1 < pend) { + *p1 = ::HexDigit(*psz--); + if (psz >= pbegin) { + *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); + p1++; + } + } +} + +template +void base_uint::SetHex(const std::string& str) +{ + SetHex(str.c_str()); +} + +template +std::string base_uint::ToString() const +{ + return (GetHex()); +} + +template +unsigned int base_uint::bits() const +{ + for (int pos = WIDTH - 1; pos >= 0; pos--) { + if (pn[pos]) { + for (int bits = 31; bits > 0; bits--) { + if (pn[pos] & 1 << bits) + return 32 * pos + bits + 1; + } + return 32 * pos + 1; + } + } + return 0; +} + +// Explicit instantiations for base_uint<160> +template base_uint<160>::base_uint(const std::string&); +template base_uint<160>::base_uint(const std::vector&); +template base_uint<160>& base_uint<160>::operator<<=(unsigned int); +template base_uint<160>& base_uint<160>::operator>>=(unsigned int); +template base_uint<160>& base_uint<160>::operator*=(uint32_t b32); +template base_uint<160>& base_uint<160>::operator*=(const base_uint<160>& b); +template base_uint<160>& base_uint<160>::operator/=(const base_uint<160>& b); +template int base_uint<160>::CompareTo(const base_uint<160>&) const; +template bool base_uint<160>::EqualTo(uint64_t) const; +template double base_uint<160>::getdouble() const; +template std::string base_uint<160>::GetHex() const; +template std::string base_uint<160>::ToString() const; +template void base_uint<160>::SetHex(const char*); +template void base_uint<160>::SetHex(const std::string&); +template unsigned int base_uint<160>::bits() const; + +// Explicit instantiations for base_uint<256> +template base_uint<256>::base_uint(const std::string&); +template base_uint<256>::base_uint(const std::vector&); +template base_uint<256>& base_uint<256>::operator<<=(unsigned int); +template base_uint<256>& base_uint<256>::operator>>=(unsigned int); +template base_uint<256>& base_uint<256>::operator*=(uint32_t b32); +template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b); +template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b); +template int base_uint<256>::CompareTo(const base_uint<256>&) const; +template bool base_uint<256>::EqualTo(uint64_t) const; +template double base_uint<256>::getdouble() const; +template std::string base_uint<256>::GetHex() const; +template std::string base_uint<256>::ToString() const; +template void base_uint<256>::SetHex(const char*); +template void base_uint<256>::SetHex(const std::string&); +template unsigned int base_uint<256>::bits() const; + +// This implementation directly uses shifts instead of going +// through an intermediate MPI representation. +arith_uint256& arith_uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow) +{ + int nSize = nCompact >> 24; + uint32_t nWord = nCompact & 0x007fffff; + if (nSize <= 3) { + nWord >>= 8 * (3 - nSize); + *this = nWord; + } else { + *this = nWord; + *this <<= 8 * (nSize - 3); + } + if (pfNegative) + *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; + if (pfOverflow) + *pfOverflow = nWord != 0 && ((nSize > 34) || + (nWord > 0xff && nSize > 33) || + (nWord > 0xffff && nSize > 32)); + return *this; +} + +uint32_t arith_uint256::GetCompact(bool fNegative) const +{ + int nSize = (bits() + 7) / 8; + uint32_t nCompact = 0; + if (nSize <= 3) { + nCompact = GetLow64() << 8 * (3 - nSize); + } else { + arith_uint256 bn = *this >> 8 * (nSize - 3); + nCompact = bn.GetLow64(); + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if (nCompact & 0x00800000) { + nCompact >>= 8; + nSize++; + } + assert((nCompact & ~0x007fffff) == 0); + assert(nSize < 256); + nCompact |= nSize << 24; + nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); + return nCompact; +} + +static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c) +{ + // Taken from lookup3, by Bob Jenkins. + a -= c; + a ^= ((c << 4) | (c >> 28)); + c += b; + b -= a; + b ^= ((a << 6) | (a >> 26)); + a += c; + c -= b; + c ^= ((b << 8) | (b >> 24)); + b += a; + a -= c; + a ^= ((c << 16) | (c >> 16)); + c += b; + b -= a; + b ^= ((a << 19) | (a >> 13)); + a += c; + c -= b; + c ^= ((b << 4) | (b >> 28)); + b += a; +} + +static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c) +{ + // Taken from lookup3, by Bob Jenkins. + c ^= b; + c -= ((b << 14) | (b >> 18)); + a ^= c; + a -= ((c << 11) | (c >> 21)); + b ^= a; + b -= ((a << 25) | (a >> 7)); + c ^= b; + c -= ((b << 16) | (b >> 16)); + a ^= c; + a -= ((c << 4) | (c >> 28)); + b ^= a; + b -= ((a << 14) | (a >> 18)); + c ^= b; + c -= ((b << 24) | (b >> 8)); +} + +uint64_t arith_uint256::GetHash(const arith_uint256& salt) const +{ + uint32_t a, b, c; + a = b = c = 0xdeadbeef + (WIDTH << 2); + + a += pn[0] ^ salt.pn[0]; + b += pn[1] ^ salt.pn[1]; + c += pn[2] ^ salt.pn[2]; + HashMix(a, b, c); + a += pn[3] ^ salt.pn[3]; + b += pn[4] ^ salt.pn[4]; + c += pn[5] ^ salt.pn[5]; + HashMix(a, b, c); + a += pn[6] ^ salt.pn[6]; + b += pn[7] ^ salt.pn[7]; + HashFinal(a, b, c); + + return ((((uint64_t)b) << 32) | c); +} diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 3bb384ca..9e32b124 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) {} }; -#define ArithToUint256(x) (x) -#define UintToArith256(x) (x) +/** 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; + } +}; + +/** 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 diff --git a/src/test/uint256_tests.cpp b/src/test/arith_uint256_tests.cpp similarity index 75% rename from src/test/uint256_tests.cpp rename to src/test/arith_uint256_tests.cpp index d05b2895..f5f71da6 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -8,65 +8,65 @@ #include #include #include -#include "uint256.h" +#include "arith_uint256.h" #include #include "version.h" -BOOST_AUTO_TEST_SUITE(uint256_tests) - -const unsigned char R1Array[] = +BOOST_AUTO_TEST_SUITE(arith_uint256_tests) + +const unsigned char R1Array[] = "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2" "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d"; const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c"; const double R1Ldouble = 0.4887374590559308955; // R1L equals roughly R1Ldouble * 2^256 -const double R1Sdouble = 0.7096329412477836074; -const uint256 R1L = uint256(std::vector(R1Array,R1Array+32)); -const uint160 R1S = uint160(std::vector(R1Array,R1Array+20)); +const double R1Sdouble = 0.7096329412477836074; +const arith_uint256 R1L = arith_uint256(std::vector(R1Array,R1Array+32)); +const arith_uint160 R1S = arith_uint160(std::vector(R1Array,R1Array+20)); const uint64_t R1LLow64 = 0x121156cfdb4a529cULL; -const unsigned char R2Array[] = +const unsigned char R2Array[] = "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf" "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7"; -const uint256 R2L = uint256(std::vector(R2Array,R2Array+32)); -const uint160 R2S = uint160(std::vector(R2Array,R2Array+20)); +const arith_uint256 R2L = arith_uint256(std::vector(R2Array,R2Array+32)); +const arith_uint160 R2S = arith_uint160(std::vector(R2Array,R2Array+20)); const char R1LplusR2L[] = "549FB09FEA236A1EA3E31D4D58F1B1369288D204211CA751527CFC175767850C"; -const unsigned char ZeroArray[] = +const unsigned char ZeroArray[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; -const uint256 ZeroL = uint256(std::vector(ZeroArray,ZeroArray+32)); -const uint160 ZeroS = uint160(std::vector(ZeroArray,ZeroArray+20)); - -const unsigned char OneArray[] = +const arith_uint256 ZeroL = arith_uint256(std::vector(ZeroArray,ZeroArray+32)); +const arith_uint160 ZeroS = arith_uint160(std::vector(ZeroArray,ZeroArray+20)); + +const unsigned char OneArray[] = "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; -const uint256 OneL = uint256(std::vector(OneArray,OneArray+32)); -const uint160 OneS = uint160(std::vector(OneArray,OneArray+20)); +const arith_uint256 OneL = arith_uint256(std::vector(OneArray,OneArray+32)); +const arith_uint160 OneS = arith_uint160(std::vector(OneArray,OneArray+20)); -const unsigned char MaxArray[] = +const unsigned char MaxArray[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; -const uint256 MaxL = uint256(std::vector(MaxArray,MaxArray+32)); -const uint160 MaxS = uint160(std::vector(MaxArray,MaxArray+20)); +const arith_uint256 MaxL = arith_uint256(std::vector(MaxArray,MaxArray+32)); +const arith_uint160 MaxS = arith_uint160(std::vector(MaxArray,MaxArray+20)); -const uint256 HalfL = (OneL << 255); -const uint160 HalfS = (OneS << 159); +const arith_uint256 HalfL = (OneL << 255); +const arith_uint160 HalfS = (OneS << 159); std::string ArrayToString(const unsigned char A[], unsigned int width) { std::stringstream Stream; Stream << std::hex; - for (unsigned int i = 0; i < width; ++i) + for (unsigned int i = 0; i < width; ++i) { Stream<): + // constructor arith_uint256(vector): BOOST_CHECK(R1L.ToString() == ArrayToString(R1Array,32)); BOOST_CHECK(R1S.ToString() == ArrayToString(R1Array,20)); BOOST_CHECK(R2L.ToString() == ArrayToString(R2Array,32)); @@ -88,104 +88,104 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality BOOST_CHECK(~MaxL == ZeroL && ~MaxS == ZeroS); BOOST_CHECK( ((R1L ^ R2L) ^ R1L) == R2L); BOOST_CHECK( ((R1S ^ R2S) ^ R1S) == R2S); - - uint64_t Tmp64 = 0xc4dab720d9c7acaaULL; - for (unsigned int i = 0; i < 256; ++i) - { - BOOST_CHECK(ZeroL != (OneL << i)); - BOOST_CHECK((OneL << i) != ZeroL); - BOOST_CHECK(R1L != (R1L ^ (OneL << i))); - BOOST_CHECK(((uint256(Tmp64) ^ (OneL << i) ) != Tmp64 )); - } - BOOST_CHECK(ZeroL == (OneL << 256)); - for (unsigned int i = 0; i < 160; ++i) + uint64_t Tmp64 = 0xc4dab720d9c7acaaULL; + for (unsigned int i = 0; i < 256; ++i) { - BOOST_CHECK(ZeroS != (OneS << i)); - BOOST_CHECK((OneS << i) != ZeroS); - BOOST_CHECK(R1S != (R1S ^ (OneS << i))); - BOOST_CHECK(((uint160(Tmp64) ^ (OneS << i) ) != Tmp64 )); + BOOST_CHECK(ZeroL != (OneL << i)); + BOOST_CHECK((OneL << i) != ZeroL); + BOOST_CHECK(R1L != (R1L ^ (OneL << i))); + BOOST_CHECK(((arith_uint256(Tmp64) ^ (OneL << i) ) != Tmp64 )); } - BOOST_CHECK(ZeroS == (OneS << 256)); + BOOST_CHECK(ZeroL == (OneL << 256)); + + for (unsigned int i = 0; i < 160; ++i) + { + BOOST_CHECK(ZeroS != (OneS << i)); + BOOST_CHECK((OneS << i) != ZeroS); + BOOST_CHECK(R1S != (R1S ^ (OneS << i))); + BOOST_CHECK(((arith_uint160(Tmp64) ^ (OneS << i) ) != Tmp64 )); + } + BOOST_CHECK(ZeroS == (OneS << 256)); // String Constructor and Copy Constructor - BOOST_CHECK(uint256("0x"+R1L.ToString()) == R1L); - BOOST_CHECK(uint256("0x"+R2L.ToString()) == R2L); - BOOST_CHECK(uint256("0x"+ZeroL.ToString()) == ZeroL); - BOOST_CHECK(uint256("0x"+OneL.ToString()) == OneL); - BOOST_CHECK(uint256("0x"+MaxL.ToString()) == MaxL); - BOOST_CHECK(uint256(R1L.ToString()) == R1L); - BOOST_CHECK(uint256(" 0x"+R1L.ToString()+" ") == R1L); - BOOST_CHECK(uint256("") == ZeroL); - BOOST_CHECK(R1L == uint256(R1ArrayHex)); - BOOST_CHECK(uint256(R1L) == R1L); - BOOST_CHECK((uint256(R1L^R2L)^R2L) == R1L); - BOOST_CHECK(uint256(ZeroL) == ZeroL); - BOOST_CHECK(uint256(OneL) == OneL); + BOOST_CHECK(arith_uint256("0x"+R1L.ToString()) == R1L); + BOOST_CHECK(arith_uint256("0x"+R2L.ToString()) == R2L); + BOOST_CHECK(arith_uint256("0x"+ZeroL.ToString()) == ZeroL); + BOOST_CHECK(arith_uint256("0x"+OneL.ToString()) == OneL); + BOOST_CHECK(arith_uint256("0x"+MaxL.ToString()) == MaxL); + BOOST_CHECK(arith_uint256(R1L.ToString()) == R1L); + BOOST_CHECK(arith_uint256(" 0x"+R1L.ToString()+" ") == R1L); + BOOST_CHECK(arith_uint256("") == ZeroL); + BOOST_CHECK(R1L == arith_uint256(R1ArrayHex)); + BOOST_CHECK(arith_uint256(R1L) == R1L); + BOOST_CHECK((arith_uint256(R1L^R2L)^R2L) == R1L); + BOOST_CHECK(arith_uint256(ZeroL) == ZeroL); + BOOST_CHECK(arith_uint256(OneL) == OneL); - BOOST_CHECK(uint160("0x"+R1S.ToString()) == R1S); - BOOST_CHECK(uint160("0x"+R2S.ToString()) == R2S); - BOOST_CHECK(uint160("0x"+ZeroS.ToString()) == ZeroS); - BOOST_CHECK(uint160("0x"+OneS.ToString()) == OneS); - BOOST_CHECK(uint160("0x"+MaxS.ToString()) == MaxS); - BOOST_CHECK(uint160(R1S.ToString()) == R1S); - BOOST_CHECK(uint160(" 0x"+R1S.ToString()+" ") == R1S); - BOOST_CHECK(uint160("") == ZeroS); - BOOST_CHECK(R1S == uint160(R1ArrayHex)); + BOOST_CHECK(arith_uint160("0x"+R1S.ToString()) == R1S); + BOOST_CHECK(arith_uint160("0x"+R2S.ToString()) == R2S); + BOOST_CHECK(arith_uint160("0x"+ZeroS.ToString()) == ZeroS); + BOOST_CHECK(arith_uint160("0x"+OneS.ToString()) == OneS); + BOOST_CHECK(arith_uint160("0x"+MaxS.ToString()) == MaxS); + BOOST_CHECK(arith_uint160(R1S.ToString()) == R1S); + BOOST_CHECK(arith_uint160(" 0x"+R1S.ToString()+" ") == R1S); + BOOST_CHECK(arith_uint160("") == ZeroS); + BOOST_CHECK(R1S == arith_uint160(R1ArrayHex)); - BOOST_CHECK(uint160(R1S) == R1S); - BOOST_CHECK((uint160(R1S^R2S)^R2S) == R1S); - BOOST_CHECK(uint160(ZeroS) == ZeroS); - BOOST_CHECK(uint160(OneS) == OneS); + BOOST_CHECK(arith_uint160(R1S) == R1S); + BOOST_CHECK((arith_uint160(R1S^R2S)^R2S) == R1S); + BOOST_CHECK(arith_uint160(ZeroS) == ZeroS); + BOOST_CHECK(arith_uint160(OneS) == OneS); // uint64_t constructor - BOOST_CHECK( (R1L & uint256("0xffffffffffffffff")) == uint256(R1LLow64)); - BOOST_CHECK(ZeroL == uint256(0)); - BOOST_CHECK(OneL == uint256(1)); - BOOST_CHECK(uint256("0xffffffffffffffff") = uint256(0xffffffffffffffffULL)); - BOOST_CHECK( (R1S & uint160("0xffffffffffffffff")) == uint160(R1LLow64)); - BOOST_CHECK(ZeroS == uint160(0)); - BOOST_CHECK(OneS == uint160(1)); - BOOST_CHECK(uint160("0xffffffffffffffff") = uint160(0xffffffffffffffffULL)); + BOOST_CHECK( (R1L & arith_uint256("0xffffffffffffffff")) == arith_uint256(R1LLow64)); + BOOST_CHECK(ZeroL == arith_uint256(0)); + BOOST_CHECK(OneL == arith_uint256(1)); + BOOST_CHECK(arith_uint256("0xffffffffffffffff") = arith_uint256(0xffffffffffffffffULL)); + BOOST_CHECK( (R1S & arith_uint160("0xffffffffffffffff")) == arith_uint160(R1LLow64)); + BOOST_CHECK(ZeroS == arith_uint160(0)); + BOOST_CHECK(OneS == arith_uint160(1)); + BOOST_CHECK(arith_uint160("0xffffffffffffffff") = arith_uint160(0xffffffffffffffffULL)); // Assignment (from base_uint) - uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); + arith_uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); tmpL = ~OneL; BOOST_CHECK(tmpL == ~OneL); tmpL = ~R1L; BOOST_CHECK(tmpL == ~R1L); tmpL = ~R2L; BOOST_CHECK(tmpL == ~R2L); tmpL = ~MaxL; BOOST_CHECK(tmpL == ~MaxL); - uint160 tmpS = ~ZeroS; BOOST_CHECK(tmpS == ~ZeroS); + arith_uint160 tmpS = ~ZeroS; BOOST_CHECK(tmpS == ~ZeroS); tmpS = ~OneS; BOOST_CHECK(tmpS == ~OneS); tmpS = ~R1S; BOOST_CHECK(tmpS == ~R1S); tmpS = ~R2S; BOOST_CHECK(tmpS == ~R2S); tmpS = ~MaxS; BOOST_CHECK(tmpS == ~MaxS); // Wrong length must throw exception. - BOOST_CHECK_THROW(uint256(std::vector(OneArray,OneArray+31)), uint_error); - BOOST_CHECK_THROW(uint256(std::vector(OneArray,OneArray+20)), uint_error); - BOOST_CHECK_THROW(uint160(std::vector(OneArray,OneArray+32)), uint_error); - BOOST_CHECK_THROW(uint160(std::vector(OneArray,OneArray+19)), uint_error); + BOOST_CHECK_THROW(arith_uint256(std::vector(OneArray,OneArray+31)), uint_error); + BOOST_CHECK_THROW(arith_uint256(std::vector(OneArray,OneArray+20)), uint_error); + BOOST_CHECK_THROW(arith_uint160(std::vector(OneArray,OneArray+32)), uint_error); + BOOST_CHECK_THROW(arith_uint160(std::vector(OneArray,OneArray+19)), uint_error); } -void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) +void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) { - for (unsigned int T=0; T < arrayLength; ++T) + for (unsigned int T=0; T < arrayLength; ++T) { unsigned int F = (T+bitsToShift/8); - if (F < arrayLength) + if (F < arrayLength) to[T] = from[F] >> (bitsToShift%8); else to[T] = 0; - if (F + 1 < arrayLength) + if (F + 1 < arrayLength) to[T] |= from[(F+1)] << (8-bitsToShift%8); } } -void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) +void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) { - for (unsigned int T=0; T < arrayLength; ++T) + for (unsigned int T=0; T < arrayLength; ++T) { - if (T >= bitsToShift/8) + if (T >= bitsToShift/8) { unsigned int F = T-bitsToShift/8; to[T] = from[F] << (bitsToShift%8); @@ -200,39 +200,39 @@ void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int a BOOST_AUTO_TEST_CASE( shifts ) { // "<<" ">>" "<<=" ">>=" unsigned char TmpArray[32]; - uint256 TmpL; + arith_uint256 TmpL; for (unsigned int i = 0; i < 256; ++i) { shiftArrayLeft(TmpArray, OneArray, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (OneL << i)); + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (OneL << i)); TmpL = OneL; TmpL <<= i; BOOST_CHECK(TmpL == (OneL << i)); BOOST_CHECK((HalfL >> (255-i)) == (OneL << i)); TmpL = HalfL; TmpL >>= (255-i); BOOST_CHECK(TmpL == (OneL << i)); - + shiftArrayLeft(TmpArray, R1Array, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (R1L << i)); + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (R1L << i)); TmpL = R1L; TmpL <<= i; BOOST_CHECK(TmpL == (R1L << i)); shiftArrayRight(TmpArray, R1Array, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (R1L >> i)); + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (R1L >> i)); TmpL = R1L; TmpL >>= i; BOOST_CHECK(TmpL == (R1L >> i)); shiftArrayLeft(TmpArray, MaxArray, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (MaxL << i)); + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (MaxL << i)); TmpL = MaxL; TmpL <<= i; BOOST_CHECK(TmpL == (MaxL << i)); shiftArrayRight(TmpArray, MaxArray, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (MaxL >> i)); + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (MaxL >> i)); TmpL = MaxL; TmpL >>= i; BOOST_CHECK(TmpL == (MaxL >> i)); } - uint256 c1L = uint256(0x0123456789abcdefULL); - uint256 c2L = c1L << 128; + arith_uint256 c1L = arith_uint256(0x0123456789abcdefULL); + arith_uint256 c2L = c1L << 128; for (unsigned int i = 0; i < 128; ++i) { BOOST_CHECK((c1L << i) == (c2L >> (128-i))); } @@ -240,39 +240,39 @@ BOOST_AUTO_TEST_CASE( shifts ) { // "<<" ">>" "<<=" ">>=" BOOST_CHECK((c1L << i) == (c2L << (i-128))); } - uint160 TmpS; + arith_uint160 TmpS; for (unsigned int i = 0; i < 160; ++i) { shiftArrayLeft(TmpArray, OneArray, 20, i); - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (OneS << i)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (OneS << i)); TmpS = OneS; TmpS <<= i; BOOST_CHECK(TmpS == (OneS << i)); BOOST_CHECK((HalfS >> (159-i)) == (OneS << i)); TmpS = HalfS; TmpS >>= (159-i); BOOST_CHECK(TmpS == (OneS << i)); - + shiftArrayLeft(TmpArray, R1Array, 20, i); - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (R1S << i)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (R1S << i)); TmpS = R1S; TmpS <<= i; BOOST_CHECK(TmpS == (R1S << i)); shiftArrayRight(TmpArray, R1Array, 20, i); - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (R1S >> i)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (R1S >> i)); TmpS = R1S; TmpS >>= i; BOOST_CHECK(TmpS == (R1S >> i)); shiftArrayLeft(TmpArray, MaxArray, 20, i); - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (MaxS << i)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (MaxS << i)); TmpS = MaxS; TmpS <<= i; BOOST_CHECK(TmpS == (MaxS << i)); shiftArrayRight(TmpArray, MaxArray, 20, i); - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (MaxS >> i)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (MaxS >> i)); TmpS = MaxS; TmpS >>= i; BOOST_CHECK(TmpS == (MaxS >> i)); } - uint160 c1S = uint160(0x0123456789abcdefULL); - uint160 c2S = c1S << 80; + arith_uint160 c1S = arith_uint160(0x0123456789abcdefULL); + arith_uint160 c2S = c1S << 80; for (unsigned int i = 0; i < 80; ++i) { BOOST_CHECK((c1S << i) == (c2S >> (80-i))); } @@ -285,47 +285,47 @@ BOOST_AUTO_TEST_CASE( unaryOperators ) // ! ~ - { BOOST_CHECK(!ZeroL); BOOST_CHECK(!ZeroS); BOOST_CHECK(!(!OneL));BOOST_CHECK(!(!OneS)); - for (unsigned int i = 0; i < 256; ++i) + for (unsigned int i = 0; i < 256; ++i) BOOST_CHECK(!(!(OneL<(TmpArray,TmpArray+32)) == (~R1L)); - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (~R1S)); + for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = ~R1Array[i]; } + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (~R1L)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (~R1S)); BOOST_CHECK(-ZeroL == ZeroL); BOOST_CHECK(-ZeroS == ZeroS); BOOST_CHECK(-R1L == (~R1L)+1); BOOST_CHECK(-R1S == (~R1S)+1); - for (unsigned int i = 0; i < 256; ++i) + for (unsigned int i = 0; i < 256; ++i) BOOST_CHECK(-(OneL<(TmpArray,TmpArray+32)) == (_A_##L _OP_ _B_##L)); \ + BOOST_CHECK(arith_uint256(std::vector(TmpArray,TmpArray+32)) == (_A_##L _OP_ _B_##L)); \ for (unsigned int i = 0; i < 20; ++i) { TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; } \ - BOOST_CHECK(uint160(std::vector(TmpArray,TmpArray+20)) == (_A_##S _OP_ _B_##S)); + BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (_A_##S _OP_ _B_##S)); #define CHECKASSIGNMENTOPERATOR(_A_,_B_,_OP_) \ TmpL = _A_##L; TmpL _OP_##= _B_##L; BOOST_CHECK(TmpL == (_A_##L _OP_ _B_##L)); \ TmpS = _A_##S; TmpS _OP_##= _B_##S; BOOST_CHECK(TmpS == (_A_##S _OP_ _B_##S)); -BOOST_AUTO_TEST_CASE( bitwiseOperators ) +BOOST_AUTO_TEST_CASE( bitwiseOperators ) { unsigned char TmpArray[32]; - + CHECKBITWISEOPERATOR(R1,R2,|) CHECKBITWISEOPERATOR(R1,R2,^) CHECKBITWISEOPERATOR(R1,R2,&) @@ -342,8 +342,8 @@ BOOST_AUTO_TEST_CASE( bitwiseOperators ) CHECKBITWISEOPERATOR(Max,R1,^) CHECKBITWISEOPERATOR(Max,R1,&) - uint256 TmpL; - uint160 TmpS; + arith_uint256 TmpL; + arith_uint160 TmpS; CHECKASSIGNMENTOPERATOR(R1,R2,|) CHECKASSIGNMENTOPERATOR(R1,R2,^) CHECKASSIGNMENTOPERATOR(R1,R2,&) @@ -360,20 +360,20 @@ BOOST_AUTO_TEST_CASE( bitwiseOperators ) CHECKASSIGNMENTOPERATOR(Max,R1,^) CHECKASSIGNMENTOPERATOR(Max,R1,&) - uint64_t Tmp64 = 0xe1db685c9a0b47a2ULL; - TmpL = R1L; TmpL |= Tmp64; BOOST_CHECK(TmpL == (R1L | uint256(Tmp64))); - TmpS = R1S; TmpS |= Tmp64; BOOST_CHECK(TmpS == (R1S | uint160(Tmp64))); + uint64_t Tmp64 = 0xe1db685c9a0b47a2ULL; + TmpL = R1L; TmpL |= Tmp64; BOOST_CHECK(TmpL == (R1L | arith_uint256(Tmp64))); + TmpS = R1S; TmpS |= Tmp64; BOOST_CHECK(TmpS == (R1S | arith_uint160(Tmp64))); TmpL = R1L; TmpL |= 0; BOOST_CHECK(TmpL == R1L); TmpS = R1S; TmpS |= 0; BOOST_CHECK(TmpS == R1S); TmpL ^= 0; BOOST_CHECK(TmpL == R1L); TmpS ^= 0; BOOST_CHECK(TmpS == R1S); - TmpL ^= Tmp64; BOOST_CHECK(TmpL == (R1L ^ uint256(Tmp64))); - TmpS ^= Tmp64; BOOST_CHECK(TmpS == (R1S ^ uint160(Tmp64))); + TmpL ^= Tmp64; BOOST_CHECK(TmpL == (R1L ^ arith_uint256(Tmp64))); + TmpS ^= Tmp64; BOOST_CHECK(TmpS == (R1S ^ arith_uint160(Tmp64))); } BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > { - uint256 TmpL; + arith_uint256 TmpL; for (unsigned int i = 0; i < 256; ++i) { TmpL= OneL<< i; BOOST_CHECK( TmpL >= ZeroL && TmpL > ZeroL && ZeroL < TmpL && ZeroL <= TmpL); @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > BOOST_CHECK( R1L <= TmpL ); BOOST_CHECK( (R1L == TmpL) != (R1L < TmpL)); BOOST_CHECK( (TmpL == R1L) || !( R1L >= TmpL)); BOOST_CHECK(! (TmpL < R1L)); BOOST_CHECK(! (R1L > TmpL)); } - uint160 TmpS; + arith_uint160 TmpS; for (unsigned int i = 0; i < 160; ++i) { TmpS= OneS<< i; BOOST_CHECK( TmpS >= ZeroS && TmpS > ZeroS && ZeroS < TmpS && ZeroS <= TmpS); @@ -395,10 +395,10 @@ BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > } } -BOOST_AUTO_TEST_CASE( plusMinus ) +BOOST_AUTO_TEST_CASE( plusMinus ) { - uint256 TmpL = 0; - BOOST_CHECK(R1L+R2L == uint256(R1LplusR2L)); + arith_uint256 TmpL = 0; + BOOST_CHECK(R1L+R2L == arith_uint256(R1LplusR2L)); TmpL += R1L; BOOST_CHECK(TmpL == R1L); TmpL += R2L; @@ -412,13 +412,13 @@ BOOST_AUTO_TEST_CASE( plusMinus ) BOOST_CHECK( TmpL == (HalfL >> (i-1)) ); TmpL = (MaxL>>i); TmpL += 1; BOOST_CHECK( TmpL == (HalfL >> (i-1)) ); - TmpL = (MaxL>>i); + TmpL = (MaxL>>i); BOOST_CHECK( TmpL++ == (MaxL>>i) ); BOOST_CHECK( TmpL == (HalfL >> (i-1))); } - BOOST_CHECK(uint256(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); - TmpL = uint256(0xbedc77e27940a7ULL); TmpL += 0xee8d836fce66fbULL; - BOOST_CHECK(TmpL == uint256(0xbedc77e27940a7ULL+0xee8d836fce66fbULL)); + BOOST_CHECK(arith_uint256(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == arith_uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); + TmpL = arith_uint256(0xbedc77e27940a7ULL); TmpL += 0xee8d836fce66fbULL; + BOOST_CHECK(TmpL == arith_uint256(0xbedc77e27940a7ULL+0xee8d836fce66fbULL)); TmpL -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == 0xbedc77e27940a7ULL); TmpL = R1L; BOOST_CHECK(++TmpL == R1L+1); @@ -439,8 +439,8 @@ BOOST_AUTO_TEST_CASE( plusMinus ) BOOST_CHECK(--TmpL == R1L-1); // 160-bit; copy-pasted - uint160 TmpS = 0; - BOOST_CHECK(R1S+R2S == uint160(R1LplusR2L)); + arith_uint160 TmpS = 0; + BOOST_CHECK(R1S+R2S == arith_uint160(R1LplusR2L)); TmpS += R1S; BOOST_CHECK(TmpS == R1S); TmpS += R2S; @@ -454,13 +454,13 @@ BOOST_AUTO_TEST_CASE( plusMinus ) BOOST_CHECK( TmpS == (HalfS >> (i-1)) ); TmpS = (MaxS>>i); TmpS += 1; BOOST_CHECK( TmpS == (HalfS >> (i-1)) ); - TmpS = (MaxS>>i); + TmpS = (MaxS>>i); BOOST_CHECK( TmpS++ == (MaxS>>i) ); BOOST_CHECK( TmpS == (HalfS >> (i-1))); } - BOOST_CHECK(uint160(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == uint160(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); - TmpS = uint160(0xbedc77e27940a7ULL); TmpS += 0xee8d836fce66fbULL; - BOOST_CHECK(TmpS == uint160(0xbedc77e27940a7ULL+0xee8d836fce66fbULL)); + BOOST_CHECK(arith_uint160(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == arith_uint160(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); + TmpS = arith_uint160(0xbedc77e27940a7ULL); TmpS += 0xee8d836fce66fbULL; + BOOST_CHECK(TmpS == arith_uint160(0xbedc77e27940a7ULL+0xee8d836fce66fbULL)); TmpS -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpS == 0xbedc77e27940a7ULL); TmpS = R1S; BOOST_CHECK(++TmpS == R1S+1); @@ -521,8 +521,8 @@ BOOST_AUTO_TEST_CASE( multiply ) BOOST_AUTO_TEST_CASE( divide ) { - uint256 D1L("AD7133AC1977FA2B7"); - uint256 D2L("ECD751716"); + arith_uint256 D1L("AD7133AC1977FA2B7"); + arith_uint256 D2L("ECD751716"); BOOST_CHECK((R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a"); BOOST_CHECK((R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a"); BOOST_CHECK(R1L / OneL == R1L); @@ -536,8 +536,8 @@ BOOST_AUTO_TEST_CASE( divide ) BOOST_CHECK(MaxL / R2L == 1); BOOST_CHECK_THROW(R2L / ZeroL, uint_error); - uint160 D1S("D3C5EDCDEA54EB92679F0A4B4"); - uint160 D2S("13037"); + arith_uint160 D1S("D3C5EDCDEA54EB92679F0A4B4"); + arith_uint160 D2S("13037"); BOOST_CHECK((R1S / D1S).ToString() == "0000000000000000000000000db9af3beade6c02"); BOOST_CHECK((R1S / D2S).ToString() == "000098dfb6cc40ca592bf74366794f298ada205c"); BOOST_CHECK(R1S / OneS == R1S); @@ -553,7 +553,7 @@ BOOST_AUTO_TEST_CASE( divide ) } -bool almostEqual(double d1, double d2) +bool almostEqual(double d1, double d2) { return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits::epsilon(); } @@ -564,7 +564,7 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(R2L.GetHex() == R2L.ToString()); BOOST_CHECK(OneL.GetHex() == OneL.ToString()); BOOST_CHECK(MaxL.GetHex() == MaxL.ToString()); - uint256 TmpL(R1L); + arith_uint256 TmpL(R1L); BOOST_CHECK(TmpL == R1L); TmpL.SetHex(R2L.ToString()); BOOST_CHECK(TmpL == R2L); TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == 0); @@ -612,7 +612,7 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(R2S.GetHex() == R2S.ToString()); BOOST_CHECK(OneS.GetHex() == OneS.ToString()); BOOST_CHECK(MaxS.GetHex() == MaxS.ToString()); - uint160 TmpS(R1S); + arith_uint160 TmpS(R1S); BOOST_CHECK(TmpS == R1S); TmpS.SetHex(R2S.ToString()); BOOST_CHECK(TmpS == R2S); TmpS.SetHex(ZeroS.ToString()); BOOST_CHECK(TmpS == 0); @@ -634,7 +634,7 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(MaxS.begin() + 20 == MaxS.end()); BOOST_CHECK(TmpS.begin() + 20 == TmpS.end()); BOOST_CHECK(R1S.GetLow64() == R1LLow64); - BOOST_CHECK(HalfS.GetLow64() ==0x0000000000000000ULL); + BOOST_CHECK(HalfS.GetLow64() ==0x0000000000000000ULL); BOOST_CHECK(OneS.GetLow64() ==0x0000000000000001ULL); BOOST_CHECK(R1S.GetSerializeSize(0,PROTOCOL_VERSION) == 20); BOOST_CHECK(ZeroS.GetSerializeSize(0,PROTOCOL_VERSION) == 20); @@ -654,17 +654,17 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G TmpS.Unserialize(ss,0,PROTOCOL_VERSION); BOOST_CHECK(MaxS == TmpS); ss.str(""); - - for (unsigned int i = 0; i < 255; ++i) + + for (unsigned int i = 0; i < 255; ++i) { BOOST_CHECK((OneL << i).getdouble() == ldexp(1.0,i)); if (i < 160) BOOST_CHECK((OneS << i).getdouble() == ldexp(1.0,i)); } BOOST_CHECK(ZeroL.getdouble() == 0.0); BOOST_CHECK(ZeroS.getdouble() == 0.0); - for (int i = 256; i > 53; --i) + for (int i = 256; i > 53; --i) BOOST_CHECK(almostEqual((R1L>>(256-i)).getdouble(), ldexp(R1Ldouble,i))); - for (int i = 160; i > 53; --i) + for (int i = 160; i > 53; --i) BOOST_CHECK(almostEqual((R1S>>(160-i)).getdouble(), ldexp(R1Sdouble,i))); uint64_t R1L64part = (R1L>>192).GetLow64(); uint64_t R1S64part = (R1S>>96).GetLow64(); @@ -677,7 +677,7 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_AUTO_TEST_CASE(bignum_SetCompact) { - uint256 num; + arith_uint256 num; bool fNegative; bool fOverflow; num.SetCompact(0, &fNegative, &fOverflow); @@ -809,21 +809,21 @@ BOOST_AUTO_TEST_CASE( getmaxcoverage ) // some more tests just to get 100% cover // ~R1L give a base_uint<256> BOOST_CHECK((~~R1L >> 10) == (R1L >> 10)); BOOST_CHECK((~~R1S >> 10) == (R1S >> 10)); BOOST_CHECK((~~R1L << 10) == (R1L << 10)); BOOST_CHECK((~~R1S << 10) == (R1S << 10)); - BOOST_CHECK(!(~~R1L < R1L)); BOOST_CHECK(!(~~R1S < R1S)); - BOOST_CHECK(~~R1L <= R1L); BOOST_CHECK(~~R1S <= R1S); - BOOST_CHECK(!(~~R1L > R1L)); BOOST_CHECK(!(~~R1S > R1S)); - BOOST_CHECK(~~R1L >= R1L); BOOST_CHECK(~~R1S >= R1S); - BOOST_CHECK(!(R1L < ~~R1L)); BOOST_CHECK(!(R1S < ~~R1S)); - BOOST_CHECK(R1L <= ~~R1L); BOOST_CHECK(R1S <= ~~R1S); - BOOST_CHECK(!(R1L > ~~R1L)); BOOST_CHECK(!(R1S > ~~R1S)); - BOOST_CHECK(R1L >= ~~R1L); BOOST_CHECK(R1S >= ~~R1S); - + BOOST_CHECK(!(~~R1L < R1L)); BOOST_CHECK(!(~~R1S < R1S)); + BOOST_CHECK(~~R1L <= R1L); BOOST_CHECK(~~R1S <= R1S); + BOOST_CHECK(!(~~R1L > R1L)); BOOST_CHECK(!(~~R1S > R1S)); + BOOST_CHECK(~~R1L >= R1L); BOOST_CHECK(~~R1S >= R1S); + BOOST_CHECK(!(R1L < ~~R1L)); BOOST_CHECK(!(R1S < ~~R1S)); + BOOST_CHECK(R1L <= ~~R1L); BOOST_CHECK(R1S <= ~~R1S); + BOOST_CHECK(!(R1L > ~~R1L)); BOOST_CHECK(!(R1S > ~~R1S)); + BOOST_CHECK(R1L >= ~~R1L); BOOST_CHECK(R1S >= ~~R1S); + BOOST_CHECK(~~R1L + R2L == R1L + ~~R2L); BOOST_CHECK(~~R1S + R2S == R1S + ~~R2S); BOOST_CHECK(~~R1L - R2L == R1L - ~~R2L); BOOST_CHECK(~~R1S - R2S == R1S - ~~R2S); - BOOST_CHECK(~R1L != R1L); BOOST_CHECK(R1L != ~R1L); - BOOST_CHECK(~R1S != R1S); BOOST_CHECK(R1S != ~R1S); + BOOST_CHECK(~R1L != R1L); BOOST_CHECK(R1L != ~R1L); + BOOST_CHECK(~R1S != R1S); BOOST_CHECK(R1S != ~R1S); unsigned char TmpArray[32]; CHECKBITWISEOPERATOR(~R1,R2,|) CHECKBITWISEOPERATOR(~R1,R2,^) @@ -834,4 +834,3 @@ BOOST_AUTO_TEST_CASE( getmaxcoverage ) // some more tests just to get 100% cover } BOOST_AUTO_TEST_SUITE_END() - diff --git a/src/uint256.cpp b/src/uint256.cpp index 918c1a7c..3b1334a0 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -11,158 +11,25 @@ #include template -base_uint::base_uint(const std::string& str) +base_blob::base_blob(const std::vector& vch) { - SetHex(str); + assert(vch.size() == sizeof(data)); + memcpy(data, &vch[0], sizeof(data)); } template -base_uint::base_uint(const std::vector& vch) +std::string base_blob::GetHex() const { - if (vch.size() != sizeof(pn)) - throw uint_error("Converting vector of wrong size to base_uint"); - memcpy(pn, &vch[0], sizeof(pn)); + char psz[sizeof(data) * 2 + 1]; + for (unsigned int i = 0; i < sizeof(data); i++) + sprintf(psz + i * 2, "%02x", data[sizeof(data) - i - 1]); + return std::string(psz, psz + sizeof(data) * 2); } template -base_uint& base_uint::operator<<=(unsigned int shift) +void base_blob::SetHex(const char* psz) { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) { - if (i + k + 1 < WIDTH && shift != 0) - pn[i + k + 1] |= (a.pn[i] >> (32 - shift)); - if (i + k < WIDTH) - pn[i + k] |= (a.pn[i] << shift); - } - return *this; -} - -template -base_uint& base_uint::operator>>=(unsigned int shift) -{ - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) { - if (i - k - 1 >= 0 && shift != 0) - pn[i - k - 1] |= (a.pn[i] << (32 - shift)); - if (i - k >= 0) - pn[i - k] |= (a.pn[i] >> shift); - } - return *this; -} - -template -base_uint& base_uint::operator*=(uint32_t b32) -{ - uint64_t carry = 0; - for (int i = 0; i < WIDTH; i++) { - uint64_t n = carry + (uint64_t)b32 * pn[i]; - pn[i] = n & 0xffffffff; - carry = n >> 32; - } - return *this; -} - -template -base_uint& base_uint::operator*=(const base_uint& b) -{ - base_uint a = *this; - *this = 0; - for (int j = 0; j < WIDTH; j++) { - uint64_t carry = 0; - for (int i = 0; i + j < WIDTH; i++) { - uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i]; - pn[i + j] = n & 0xffffffff; - carry = n >> 32; - } - } - return *this; -} - -template -base_uint& base_uint::operator/=(const base_uint& b) -{ - base_uint div = b; // make a copy, so we can shift. - base_uint num = *this; // make a copy, so we can subtract. - *this = 0; // the quotient. - int num_bits = num.bits(); - int div_bits = div.bits(); - if (div_bits == 0) - throw uint_error("Division by zero"); - if (div_bits > num_bits) // the result is certainly 0. - return *this; - int shift = num_bits - div_bits; - div <<= shift; // shift so that div and num align. - while (shift >= 0) { - if (num >= div) { - num -= div; - pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result. - } - div >>= 1; // shift back. - shift--; - } - // num now contains the remainder of the division. - return *this; -} - -template -int base_uint::CompareTo(const base_uint& b) const -{ - for (int i = WIDTH - 1; i >= 0; i--) { - if (pn[i] < b.pn[i]) - return -1; - if (pn[i] > b.pn[i]) - return 1; - } - return 0; -} - -template -bool base_uint::EqualTo(uint64_t b) const -{ - for (int i = WIDTH - 1; i >= 2; i--) { - if (pn[i]) - return false; - } - if (pn[1] != (b >> 32)) - return false; - if (pn[0] != (b & 0xfffffffful)) - return false; - return true; -} - -template -double base_uint::getdouble() const -{ - double ret = 0.0; - double fact = 1.0; - for (int i = 0; i < WIDTH; i++) { - ret += fact * pn[i]; - fact *= 4294967296.0; - } - return ret; -} - -template -std::string base_uint::GetHex() const -{ - char psz[sizeof(pn) * 2 + 1]; - for (unsigned int i = 0; i < sizeof(pn); i++) - sprintf(psz + i * 2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); - return std::string(psz, psz + sizeof(pn) * 2); -} - -template -void base_uint::SetHex(const char* psz) -{ - memset(pn, 0, sizeof(pn)); + memset(data, 0, sizeof(data)); // skip leading spaces while (isspace(*psz)) @@ -177,7 +44,7 @@ void base_uint::SetHex(const char* psz) while (::HexDigit(*psz) != -1) psz++; psz--; - unsigned char* p1 = (unsigned char*)pn; + unsigned char* p1 = (unsigned char*)data; unsigned char* pend = p1 + WIDTH * 4; while (psz >= pbegin && p1 < pend) { *p1 = ::HexDigit(*psz--); @@ -189,110 +56,30 @@ void base_uint::SetHex(const char* psz) } template -void base_uint::SetHex(const std::string& str) +void base_blob::SetHex(const std::string& str) { SetHex(str.c_str()); } template -std::string base_uint::ToString() const +std::string base_blob::ToString() const { return (GetHex()); } -template -unsigned int base_uint::bits() const -{ - for (int pos = WIDTH - 1; pos >= 0; pos--) { - if (pn[pos]) { - for (int bits = 31; bits > 0; bits--) { - if (pn[pos] & 1 << bits) - return 32 * pos + bits + 1; - } - return 32 * pos + 1; - } - } - return 0; -} +// Explicit instantiations for base_blob<160> +template base_blob<160>::base_blob(const std::vector&); +template std::string base_blob<160>::GetHex() const; +template std::string base_blob<160>::ToString() const; +template void base_blob<160>::SetHex(const char*); +template void base_blob<160>::SetHex(const std::string&); -// Explicit instantiations for base_uint<160> -template base_uint<160>::base_uint(const std::string&); -template base_uint<160>::base_uint(const std::vector&); -template base_uint<160>& base_uint<160>::operator<<=(unsigned int); -template base_uint<160>& base_uint<160>::operator>>=(unsigned int); -template base_uint<160>& base_uint<160>::operator*=(uint32_t b32); -template base_uint<160>& base_uint<160>::operator*=(const base_uint<160>& b); -template base_uint<160>& base_uint<160>::operator/=(const base_uint<160>& b); -template int base_uint<160>::CompareTo(const base_uint<160>&) const; -template bool base_uint<160>::EqualTo(uint64_t) const; -template double base_uint<160>::getdouble() const; -template std::string base_uint<160>::GetHex() const; -template std::string base_uint<160>::ToString() const; -template void base_uint<160>::SetHex(const char*); -template void base_uint<160>::SetHex(const std::string&); -template unsigned int base_uint<160>::bits() const; - -// Explicit instantiations for base_uint<256> -template base_uint<256>::base_uint(const std::string&); -template base_uint<256>::base_uint(const std::vector&); -template base_uint<256>& base_uint<256>::operator<<=(unsigned int); -template base_uint<256>& base_uint<256>::operator>>=(unsigned int); -template base_uint<256>& base_uint<256>::operator*=(uint32_t b32); -template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b); -template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b); -template int base_uint<256>::CompareTo(const base_uint<256>&) const; -template bool base_uint<256>::EqualTo(uint64_t) const; -template double base_uint<256>::getdouble() const; -template std::string base_uint<256>::GetHex() const; -template std::string base_uint<256>::ToString() const; -template void base_uint<256>::SetHex(const char*); -template void base_uint<256>::SetHex(const std::string&); -template unsigned int base_uint<256>::bits() const; - -// This implementation directly uses shifts instead of going -// through an intermediate MPI representation. -uint256& uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow) -{ - int nSize = nCompact >> 24; - uint32_t nWord = nCompact & 0x007fffff; - if (nSize <= 3) { - nWord >>= 8 * (3 - nSize); - *this = nWord; - } else { - *this = nWord; - *this <<= 8 * (nSize - 3); - } - if (pfNegative) - *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; - if (pfOverflow) - *pfOverflow = nWord != 0 && ((nSize > 34) || - (nWord > 0xff && nSize > 33) || - (nWord > 0xffff && nSize > 32)); - return *this; -} - -uint32_t uint256::GetCompact(bool fNegative) const -{ - int nSize = (bits() + 7) / 8; - uint32_t nCompact = 0; - if (nSize <= 3) { - nCompact = GetLow64() << 8 * (3 - nSize); - } else { - uint256 bn = *this >> 8 * (nSize - 3); - nCompact = bn.GetLow64(); - } - // The 0x00800000 bit denotes the sign. - // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. - if (nCompact & 0x00800000) { - nCompact >>= 8; - nSize++; - } - assert((nCompact & ~0x007fffff) == 0); - assert(nSize < 256); - nCompact |= nSize << 24; - nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); - return nCompact; -} +// Explicit instantiations for base_blob<256> +template base_blob<256>::base_blob(const std::vector&); +template std::string base_blob<256>::GetHex() const; +template std::string base_blob<256>::ToString() const; +template void base_blob<256>::SetHex(const char*); +template void base_blob<256>::SetHex(const std::string&); static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c) { @@ -339,18 +126,20 @@ static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c) uint64_t uint256::GetHash(const uint256& salt) const { uint32_t a, b, c; + const uint32_t *pn = (const uint32_t*)data; + const uint32_t *salt_pn = (const uint32_t*)salt.data; a = b = c = 0xdeadbeef + (WIDTH << 2); - a += pn[0] ^ salt.pn[0]; - b += pn[1] ^ salt.pn[1]; - c += pn[2] ^ salt.pn[2]; + a += pn[0] ^ salt_pn[0]; + b += pn[1] ^ salt_pn[1]; + c += pn[2] ^ salt_pn[2]; HashMix(a, b, c); - a += pn[3] ^ salt.pn[3]; - b += pn[4] ^ salt.pn[4]; - c += pn[5] ^ salt.pn[5]; + a += pn[3] ^ salt_pn[3]; + b += pn[4] ^ salt_pn[4]; + c += pn[5] ^ salt_pn[5]; HashMix(a, b, c); - a += pn[6] ^ salt.pn[6]; - b += pn[7] ^ salt.pn[7]; + a += pn[6] ^ salt_pn[6]; + b += pn[7] ^ salt_pn[7]; HashFinal(a, b, c); return ((((uint64_t)b) << 32) | c); diff --git a/src/uint256.h b/src/uint256.h index 8189b27c..6d016ab1 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -13,217 +13,37 @@ #include #include -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 -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& 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& 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 void Serialize(Stream& s, int nType, int nVersion) const { - s.write((char*)pn, sizeof(pn)); + s.write((char*)data, sizeof(data)); } template 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& vch) : base_uint<160>(vch) {} + uint160(const base_blob<160>& b) : base_blob<160>(b) {} + explicit uint160(const std::vector& 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& 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& 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