From edbfc61d401c0bd9f4b85dd49d1a1e77c1b2eb02 Mon Sep 17 00:00:00 2001 From: svost Date: Sun, 13 Feb 2022 14:33:15 +0300 Subject: [PATCH] Move rand functions from util to new random.h/.cpp --- CMakeLists.txt | 1 + src/CMakeLists.txt | 1 + src/addrman.cpp | 11 +++++ src/addrman.h | 13 +------ src/bitcoinrpc.cpp | 2 +- src/db.cpp | 2 +- src/net.cpp | 2 +- src/net.h | 9 ++-- src/random.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/random.h | 27 +++++++++++++ src/script.cpp | 1 + src/uint256.cpp | 10 ----- src/uint256.h | 2 - src/util.cpp | 62 +------------------------------ src/util.h | 30 --------------- src/wallet.cpp | 4 +- 16 files changed, 158 insertions(+), 125 deletions(-) create mode 100644 src/random.cpp create mode 100644 src/random.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 45ba823..4167062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,7 @@ set(generic_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/streams.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/miner.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/random.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/init.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/net.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/stun.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 230defa..183d941 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,6 +100,7 @@ set(generic_sources ${CMAKE_CURRENT_SOURCE_DIR}/noui.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ntp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/protocol.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/random.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rpcblockchain.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rpcdump.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rpcmining.cpp diff --git a/src/addrman.cpp b/src/addrman.cpp index a754926..6c3f394 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -4,6 +4,7 @@ #include "addrman.h" #include "hash.h" +#include "random.h" #include "streams.h" using namespace std; @@ -538,3 +539,13 @@ void CAddrMan::Connected_(const CService &addr, int64_t nTime) if (nTime - info.nTime > nUpdateInterval) info.nTime = nTime; } + +CAddrMan::CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set()) +{ + nKey.resize(32); + GetRandBytes(&nKey[0], 32); + + nIdCount = 0; + nTried = 0; + nNew = 0; +} diff --git a/src/addrman.h b/src/addrman.h index 69a1271..80ef713 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -10,12 +10,9 @@ #include "util.h" #include "sync.h" - #include #include -#include - /** Extended statistics about a CAddress */ class CAddrInfo : public CAddress @@ -421,15 +418,7 @@ public: ) - CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set()) - { - nKey.resize(32); - RAND_bytes(&nKey[0], 32); - - nIdCount = 0; - nTried = 0; - nNew = 0; - } + CAddrMan(); // Return the number of (unique) addresses in all tables. int size() diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index dafacef..a0342c0 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -473,7 +473,7 @@ void StartRPCServer() if (mapArgs["-rpcpassword"].empty()) { unsigned char rand_pwd[32]; - RAND_bytes(rand_pwd, 32); + GetRandBytes(rand_pwd, 32); std::string strWhatAmI = "To use novacoind"; if (mapArgs.count("-server")) strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); diff --git a/src/db.cpp b/src/db.cpp index 946454d..78e2495 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -497,7 +497,7 @@ bool CAddrDB::Write(const CAddrMan& addr) { // Generate random temporary filename unsigned short randv = 0; - RAND_bytes((unsigned char *)&randv, sizeof(randv)); + GetRandBytes((unsigned char *)&randv, sizeof(randv)); std::string tmpfn = strprintf("peers.dat.%04x", randv); // serialize addresses, checksum data up to that point, then append csum diff --git a/src/net.cpp b/src/net.cpp index 28f40b8..cd89567 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -528,7 +528,7 @@ void CNode::PushVersion() addrMe = GetLocalAddress(&addr); } - RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); + GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str()); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), nBestHeight); diff --git a/src/net.h b/src/net.h index 11963b0..fd8174b 100644 --- a/src/net.h +++ b/src/net.h @@ -10,8 +10,7 @@ #include "addrman.h" #include "hash.h" #include "streams.h" - -#include +#include "random.h" #ifndef WIN32 #include @@ -477,7 +476,7 @@ public: void (*fn)(void*, CDataStream&), void* param1) { uint256 hashReply; - RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); + GetRandBytes((unsigned char*)&hashReply, sizeof(hashReply)); { LOCK(cs_mapRequests); @@ -492,7 +491,7 @@ public: void (*fn)(void*, CDataStream&), void* param1) { uint256 hashReply; - RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); + GetRandBytes((unsigned char*)&hashReply, sizeof(hashReply)); { LOCK(cs_mapRequests); @@ -507,7 +506,7 @@ public: void (*fn)(void*, CDataStream&), void* param1) { uint256 hashReply; - RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); + GetRandBytes((unsigned char*)&hashReply, sizeof(hashReply)); { LOCK(cs_mapRequests); diff --git a/src/random.cpp b/src/random.cpp new file mode 100644 index 0000000..00af04f --- /dev/null +++ b/src/random.cpp @@ -0,0 +1,106 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 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 "random.h" +#include "uint256.h" +#include "util.h" // for printf() + +#ifdef WIN32 +#include "compat.h" // for Windows API +#endif + +#ifndef WIN32 +#include +#endif + +#include +#include +#include + +#include + + +static inline int64_t GetPerformanceCounter() +{ + int64_t nCounter = 0; +#ifdef WIN32 + QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); +#else + timeval t{}; + gettimeofday(&t, nullptr); + nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec; +#endif + return nCounter; +} + +void RandAddSeed() +{ + // Seed with CPU performance counter + int64_t nCounter = GetPerformanceCounter(); + RAND_add(&nCounter, sizeof(nCounter), 1.5); + memset(&nCounter, 0, sizeof(nCounter)); +} + +void RandAddSeedPerfmon() +{ + RandAddSeed(); + +#ifdef WIN32 + // This can take up to 2 seconds, so only do it every 10 minutes + static int64_t nLastPerfmon; + if (GetTime() < nLastPerfmon + 10 * 60) + return; + nLastPerfmon = GetTime(); + + // Don't need this on Linux, OpenSSL automatically uses /dev/urandom + // Seed with the entire set of perfmon data + unsigned char pdata[250000]; + memset(pdata, 0, sizeof(pdata)); + unsigned long nSize = sizeof(pdata); + long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); + RegCloseKey(HKEY_PERFORMANCE_DATA); + if (ret == ERROR_SUCCESS) + { + RAND_add(pdata, nSize, nSize/100.0); + OPENSSL_cleanse(pdata, nSize); + printf("RandAddSeed() %lu bytes\n", nSize); + } +#endif +} + +void GetRandBytes(unsigned char *buf, int num) +{ + if (RAND_bytes(buf, num) != 1) { + printf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), nullptr)); + assert(false); + } +} + +uint64_t GetRand(uint64_t nMax) +{ + if (nMax == 0) + return 0; + + // The range of the random source must be a multiple of the modulus + // to give every possible output value an equal possibility + uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; + uint64_t nRand = 0; + do + RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); + while (nRand >= nRange); + return (nRand % nMax); +} + +int GetRandInt(int nMax) +{ + return static_cast(GetRand(nMax)); +} + +uint256 GetRandHash() +{ + uint256 hash; + RAND_bytes(hash.begin(), hash.size()); + return hash; +} diff --git a/src/random.h b/src/random.h new file mode 100644 index 0000000..41c2d34 --- /dev/null +++ b/src/random.h @@ -0,0 +1,27 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RANDOM_H +#define BITCOIN_RANDOM_H + +#include + +class uint256; + +/** + * Seed OpenSSL PRNG with additional entropy data + */ +void RandAddSeed(); +void RandAddSeedPerfmon(); + +/** + * Functions to gather random data via the OpenSSL PRNG + */ +void GetRandBytes(unsigned char *buf, int num); +uint64_t GetRand(uint64_t nMax); +int GetRandInt(int nMax); +uint256 GetRandHash(); + +#endif // BITCOIN_RANDOM_H diff --git a/src/script.cpp b/src/script.cpp index a72868a..aa3fe8c 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -7,6 +7,7 @@ #include "keystore.h" #include "key.h" #include "main.h" +#include "random.h" #include "sync.h" #include "util.h" #include "base58.h" diff --git a/src/uint256.cpp b/src/uint256.cpp index 2d65072..8faf052 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -3,11 +3,8 @@ // 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 @@ -216,10 +213,3 @@ uint256::uint256(const std::vector& vch) 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 4d60835..d6cd23f 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -584,6 +584,4 @@ 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 2c5ec84..cd750ab 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6,6 +6,7 @@ #include "util.h" #include "allocators.h" #include "interface.h" +#include "random.h" #include "sync.h" #include "version.h" @@ -114,67 +115,6 @@ public: instance_of_cinit; - - - - - - -void RandAddSeed() -{ - // Seed with CPU performance counter - int64_t nCounter = GetPerformanceCounter(); - RAND_add(&nCounter, sizeof(nCounter), 1.5); - memset(&nCounter, 0, sizeof(nCounter)); -} - -void RandAddSeedPerfmon() -{ - RandAddSeed(); - - // This can take up to 2 seconds, so only do it every 10 minutes - static int64_t nLastPerfmon; - if (GetTime() < nLastPerfmon + 10 * 60) - return; - nLastPerfmon = GetTime(); - -#ifdef WIN32 - // Don't need this on Linux, OpenSSL automatically uses /dev/urandom - // Seed with the entire set of perfmon data - unsigned char pdata[250000]; - memset(pdata, 0, sizeof(pdata)); - unsigned long nSize = sizeof(pdata); - long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); - RegCloseKey(HKEY_PERFORMANCE_DATA); - if (ret == ERROR_SUCCESS) - { - RAND_add(pdata, nSize, nSize/100.0); - OPENSSL_cleanse(pdata, nSize); - printf("RandAddSeed() %lu bytes\n", nSize); - } -#endif -} - -uint64_t GetRand(uint64_t nMax) -{ - if (nMax == 0) - return 0; - - // The range of the random source must be a multiple of the modulus - // to give every possible output value an equal possibility - uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; - uint64_t nRand = 0; - do - RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); - while (nRand >= nRange); - return (nRand % nMax); -} - -int GetRandInt(int nMax) -{ - return static_cast(GetRand(nMax)); -} - static FILE* fileout = NULL; inline int OutputDebugStringF(const char* pszFormat, ...) diff --git a/src/util.h b/src/util.h index d350ed4..8a37c03 100644 --- a/src/util.h +++ b/src/util.h @@ -142,12 +142,6 @@ inline void Sleep(int64_t n) #endif - - - - - - extern std::map mapArgs; extern std::map > mapMultiArgs; extern bool fDebug; @@ -165,8 +159,6 @@ extern bool fNoListen; extern bool fLogTimestamps; extern bool fReopenDebugLog; -void RandAddSeed(); -void RandAddSeedPerfmon(); int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...); /* @@ -235,8 +227,6 @@ void ReadConfigFile(std::map& mapSettingsRet, std::map boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif void ShrinkDebugFile(); -int GetRandInt(int nMax); -uint64_t GetRand(uint64_t nMax); int64_t GetTime(); int64_t GetTimeMillis(); int64_t GetTimeMicros(); @@ -245,13 +235,6 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const void runCommand(std::string strCommand); - - - - - - - inline std::string i64tostr(int64_t n) { return strprintf("%" PRId64, n); @@ -365,19 +348,6 @@ inline void PrintHex(const std::vector& vch, const char* pszForma printf(pszFormat, HexStr(vch, fSpaces).c_str()); } -inline int64_t GetPerformanceCounter() -{ - int64_t nCounter = 0; -#ifdef WIN32 - QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); -#else - timeval t; - gettimeofday(&t, NULL); - nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec; -#endif - return nCounter; -} - inline int64_t GetTimeMillis() { return (boost::posix_time::microsec_clock::universal_time() - diff --git a/src/wallet.cpp b/src/wallet.cpp index 75c9f31..1602479 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -379,13 +379,13 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) RandAddSeedPerfmon(); vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); - RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); + GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); CMasterKey kMasterKey; RandAddSeedPerfmon(); kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); - RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); + GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); CCrypter crypter; int64_t nStartTime = GetTimeMillis(); -- 1.7.1