From 82597c35e97568d9d53983211cdf29621cefdb51 Mon Sep 17 00:00:00 2001 From: svost Date: Tue, 4 Jan 2022 16:16:39 +0300 Subject: [PATCH] port code from +17 branch, fix operator *= --- CMakeLists.txt | 1 + src/CMakeLists.txt | 1 + src/bignum.h | 8 ++- src/uint256.cpp | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/uint256.h | 182 ++++++++++++++++-------------------------- src/util.cpp | 14 +--- src/util.h | 3 - 7 files changed, 305 insertions(+), 129 deletions(-) create mode 100644 src/uint256.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 51631de..94e65fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,7 @@ set(generic_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/addrman.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/db.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/walletdb.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/uint256.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/qt/clientmodel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/qt/guiutil.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/qt/transactionrecord.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3535a6a..366fcd6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -113,6 +113,7 @@ set(generic_sources ${CMAKE_CURRENT_SOURCE_DIR}/script.cpp ${CMAKE_CURRENT_SOURCE_DIR}/stun.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sync.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/uint256.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util.cpp ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wallet.cpp diff --git a/src/bignum.h b/src/bignum.h index 6ab5a6d..e3838bc 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -5,10 +5,14 @@ #ifndef BITCOIN_BIGNUM_H #define BITCOIN_BIGNUM_H + +#include "util.h" +#include "uint256.h" + +#include + #include #include -#include -#include "util.h" /** Errors thrown by the bignum class */ class bignum_error : public std::runtime_error diff --git a/src/uint256.cpp b/src/uint256.cpp new file mode 100644 index 0000000..2d65072 --- /dev/null +++ b/src/uint256.cpp @@ -0,0 +1,225 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +#include "uint256.h" + +#include + +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////////////////// +// +// uint160 +// + +uint160::uint160() +{ + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; +} + +uint160::uint160(const basetype& b) +{ + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; +} + +uint160& uint160::operator=(const basetype& b) +{ + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + return *this; +} + +uint160::uint160(uint64_t b) +{ + pn[0] = (uint32_t)b; + pn[1] = (uint32_t)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; +} + +uint160& uint160::operator=(uint64_t b) +{ + pn[0] = (uint32_t)b; + pn[1] = (uint32_t)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + return *this; +} + +uint160::uint160(const std::string& str) +{ + SetHex(str); +} + +uint160::uint160(const std::vector& vch) +{ + if (vch.size() == sizeof(pn)) + memcpy(pn, &vch[0], sizeof(pn)); + else + *this = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// +// uint256 +// + +uint256::uint256() +{ + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; +} + +uint256::uint256(const basetype& b) +{ + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; +} + +uint256& uint256::operator=(const basetype& b) +{ + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + return *this; +} + +uint256::uint256(uint64_t b) +{ + pn[0] = (uint32_t)b; + pn[1] = (uint32_t)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; +} + +uint256& uint256::operator=(uint64_t b) +{ + pn[0] = (uint32_t)b; + pn[1] = (uint32_t)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + return *this; +} + +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 = Get64(0) << 8*(3-nSize); + } else { + uint256 n = *this; + uint256 bn = n >> 8*(nSize-3); + nCompact = bn.Get64(0); + } + // 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; +} + +uint256& uint256::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; +} + +uint256& uint256::operator*=(const uint256& b) +{ + uint256 a; + 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; + } + } + *this = a; + return *this; +} + +uint256& uint256::operator/=(const uint256& b) +{ + uint256 div = b; // make a copy, so we can shift. + uint256 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 uint256_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; +} + +uint256::uint256(const std::string& str) +{ + SetHex(str); +} + +uint256::uint256(const std::vector& vch) +{ + if (vch.size() == sizeof(pn)) + memcpy(pn, &vch[0], sizeof(pn)); + else + *this = 0; +} + +uint256 GetRandHash() +{ + uint256 hash; + RAND_bytes(hash.begin(), hash.size()); + return hash; +} diff --git a/src/uint256.h b/src/uint256.h index 3bb0167..4d60835 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -5,15 +5,11 @@ #ifndef BITCOIN_UINT256_H #define BITCOIN_UINT256_H -#include -#include -#include +#include #include #include -#include - -inline int Testuint256AdHoc(std::vector vArg); - +#include +#include /** Base class without constructors for uint256 and uint160. @@ -27,6 +23,14 @@ protected: uint32_t pn[WIDTH]; public: + const base_uint max() + { + base_uint ret; + for (int i = 0; i < WIDTH; i++) + ret.pn[i] = std::numeric_limits::max(); + return ret; + } + bool operator!() const { for (int i = 0; i < WIDTH; i++) @@ -291,10 +295,11 @@ public: std::string 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); + std::stringstream ss; + size_t pn_size = sizeof(pn) / sizeof(pn[0]); + for (size_t i = 1; i <= pn_size; i++) + ss << std::setfill('0') << std::setw(8) << std::setbase(16) << pn[pn_size-i]; + return ss.str(); } void SetHex(const char* psz) @@ -339,12 +344,12 @@ public: return (GetHex()); } - unsigned char* begin() + unsigned char* begin() const { return (unsigned char*)&pn[0]; } - unsigned char* end() + unsigned char* end() const { return (unsigned char*)&pn[WIDTH]; } @@ -354,7 +359,7 @@ public: return std::vector(begin(), end()); } - size_t size() + size_t size() const { return sizeof(pn); } @@ -374,6 +379,20 @@ public: return sizeof(pn); } + unsigned int 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; + } + template void Serialize(Stream& s, int nType, int nVersion) const { @@ -388,7 +407,6 @@ public: friend class uint160; friend class uint256; - friend inline int Testuint256AdHoc(std::vector vArg); }; typedef base_uint<160> base_uint160; @@ -412,54 +430,13 @@ class uint160 : public base_uint160 public: typedef base_uint160 basetype; - uint160() - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - } - - uint160(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - } - - uint160& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - return *this; - } - - uint160(uint64_t b) - { - pn[0] = (uint32_t)b; - pn[1] = (uint32_t)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - } - - uint160& operator=(uint64_t b) - { - pn[0] = (uint32_t)b; - pn[1] = (uint32_t)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - explicit uint160(const std::string& str) - { - SetHex(str); - } - - explicit uint160(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - *this = 0; - } + uint160(); + uint160(const basetype& b); + uint160& operator=(const basetype& b); + uint160(uint64_t b); + uint160& operator=(uint64_t b); + explicit uint160(const std::string& str); + explicit uint160(const std::vector& vch); }; inline bool operator==(const uint160& a, uint64_t b) { return (base_uint160)a == b; } @@ -521,60 +498,37 @@ inline const uint160 operator-(const uint160& a, const uint160& b) { return // uint256 // + +/** Errors thrown by the uint256 class */ +class uint256_error : public std::exception +{ +public: + explicit uint256_error(const std::string& error_message) : what_(error_message) {} + + virtual const char* what() const throw () { return what_.c_str(); } + virtual ~uint256_error() throw () {} +private: + std::string what_; +}; + /** 256-bit unsigned integer */ class uint256 : public base_uint256 { public: typedef base_uint256 basetype; - uint256() - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - } - - uint256(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - } - - uint256& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - return *this; - } - - uint256(uint64_t b) - { - pn[0] = (uint32_t)b; - pn[1] = (uint32_t)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - } - - uint256& operator=(uint64_t b) - { - pn[0] = (uint32_t)b; - pn[1] = (uint32_t)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - explicit uint256(const std::string& str) - { - SetHex(str); - } - - explicit uint256(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - *this = 0; - } + uint256(); + uint256(const basetype& b); + uint256& operator=(const basetype& b); + uint256(uint64_t b); + uint256& operator=(uint64_t b); + uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); + uint32_t GetCompact(bool fNegative = false) const; + uint256& operator*=(uint32_t b32); + uint256& operator*=(const uint256& b); + uint256& operator/=(const uint256& b); + explicit uint256(const std::string& str); + explicit uint256(const std::vector& vch); }; inline bool operator==(const uint256& a, uint64_t b) { return (base_uint256)a == b; } @@ -588,6 +542,8 @@ inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { r inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; } inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; } inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; } +inline const uint256 operator*(const base_uint256& a, const base_uint256& b) { return uint256(a) *= b; } +inline const uint256 operator/(const base_uint256& a, const base_uint256& b) { return uint256(a) /= b; } inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; } inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } @@ -600,6 +556,8 @@ inline const uint256 operator^(const base_uint256& a, const uint256& b) { return inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } +inline const uint256 operator*(const base_uint256& a, const uint256& b) { return (base_uint256)a * (base_uint256)b; } +inline const uint256 operator/(const base_uint256& a, const uint256& b) { return (base_uint256)a / (base_uint256)b; } inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; } @@ -626,4 +584,6 @@ inline const uint256 operator|(const uint256& a, const uint256& b) { return inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } +uint256 GetRandHash(); + #endif diff --git a/src/util.cpp b/src/util.cpp index b1e1607..afb0324 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -4,9 +4,9 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "util.h" +#include "interface.h" #include "sync.h" #include "version.h" -#include "interface.h" #include #include // for to_lower() @@ -178,18 +178,6 @@ int GetRandInt(int nMax) return static_cast(GetRand(nMax)); } -uint256 GetRandHash() -{ - uint256 hash; - RAND_bytes((unsigned char*)&hash, sizeof(hash)); - return hash; -} - - - - - - static FILE* fileout = NULL; inline int OutputDebugStringF(const char* pszFormat, ...) diff --git a/src/util.h b/src/util.h index 6cf2070..868a840 100644 --- a/src/util.h +++ b/src/util.h @@ -6,8 +6,6 @@ #define BITCOIN_UTIL_H -#include "uint256.h" - #ifndef WIN32 #include #include @@ -236,7 +234,6 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); void ShrinkDebugFile(); int GetRandInt(int nMax); uint64_t GetRand(uint64_t nMax); -uint256 GetRandHash(); int64_t GetTime(); int64_t GetTimeMillis(); int64_t GetTimeMicros(); -- 1.7.1