]> Git Repo - VerusCoin.git/blame - src/random.cpp
Apply clang-format on some infrequently-updated files
[VerusCoin.git] / src / random.cpp
CommitLineData
6354935c
PK
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2014 The Bitcoin developers
3// Distributed under the MIT/X11 software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "random.h"
7
8#ifdef WIN32
9#include "compat.h" // for Windows API
10#endif
20e01b1a
PW
11#include "serialize.h" // for begin_ptr(vec)
12#include "util.h" // for LogPrint()
ad49c256 13#include "utilstrencodings.h" // for GetTime()
6354935c 14
611116d4
PK
15#include <limits>
16
6354935c
PK
17#ifndef WIN32
18#include <sys/time.h>
19#endif
611116d4 20
6354935c
PK
21#include <openssl/crypto.h>
22#include <openssl/err.h>
23#include <openssl/rand.h>
24
25static inline int64_t GetPerformanceCounter()
26{
27 int64_t nCounter = 0;
28#ifdef WIN32
29 QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
30#else
31 timeval t;
32 gettimeofday(&t, NULL);
33 nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
34#endif
35 return nCounter;
36}
37
38void RandAddSeed()
39{
40 // Seed with CPU performance counter
41 int64_t nCounter = GetPerformanceCounter();
42 RAND_add(&nCounter, sizeof(nCounter), 1.5);
4eedf4ff 43 OPENSSL_cleanse((void*)&nCounter, sizeof(nCounter));
6354935c
PK
44}
45
46void RandAddSeedPerfmon()
47{
48 RandAddSeed();
49
50 // This can take up to 2 seconds, so only do it every 10 minutes
51 static int64_t nLastPerfmon;
52 if (GetTime() < nLastPerfmon + 10 * 60)
53 return;
54 nLastPerfmon = GetTime();
55
56#ifdef WIN32
57 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
58 // Seed with the entire set of perfmon data
20e01b1a 59 std::vector<unsigned char> vData(250000, 0);
6354935c
PK
60 long ret = 0;
61 unsigned long nSize = 0;
62 const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
20e01b1a 63 while (true) {
6354935c
PK
64 nSize = vData.size();
65 ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
66 if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
67 break;
20e01b1a 68 vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
6354935c
PK
69 }
70 RegCloseKey(HKEY_PERFORMANCE_DATA);
20e01b1a
PW
71 if (ret == ERROR_SUCCESS) {
72 RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
6354935c
PK
73 OPENSSL_cleanse(begin_ptr(vData), nSize);
74 LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
75 } else {
76 static bool warned = false; // Warn only once
20e01b1a 77 if (!warned) {
6354935c
PK
78 LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
79 warned = true;
80 }
81 }
82#endif
83}
84
20e01b1a 85bool GetRandBytes(unsigned char* buf, int num)
6354935c
PK
86{
87 if (RAND_bytes(buf, num) != 1) {
88 LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
89 return false;
90 }
91 return true;
92}
93
94uint64_t GetRand(uint64_t nMax)
95{
96 if (nMax == 0)
97 return 0;
98
99 // The range of the random source must be a multiple of the modulus
100 // to give every possible output value an equal possibility
101 uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
102 uint64_t nRand = 0;
103 do {
104 GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
105 } while (nRand >= nRange);
106 return (nRand % nMax);
107}
108
109int GetRandInt(int nMax)
110{
111 return GetRand(nMax);
112}
113
114uint256 GetRandHash()
115{
116 uint256 hash;
117 GetRandBytes((unsigned char*)&hash, sizeof(hash));
118 return hash;
119}
120
121uint32_t insecure_rand_Rz = 11;
122uint32_t insecure_rand_Rw = 11;
123void seed_insecure_rand(bool fDeterministic)
124{
125 // The seed values have some unlikely fixed points which we avoid.
20e01b1a 126 if (fDeterministic) {
6354935c
PK
127 insecure_rand_Rz = insecure_rand_Rw = 11;
128 } else {
129 uint32_t tmp;
130 do {
131 GetRandBytes((unsigned char*)&tmp, 4);
20e01b1a 132 } while (tmp == 0 || tmp == 0x9068ffffU);
6354935c
PK
133 insecure_rand_Rz = tmp;
134 do {
135 GetRandBytes((unsigned char*)&tmp, 4);
20e01b1a 136 } while (tmp == 0 || tmp == 0x464fffffU);
6354935c
PK
137 insecure_rand_Rw = tmp;
138 }
139}
This page took 0.052277 seconds and 4 git commands to generate.