Skip to content

Commit 6354935

Browse files
author
Philip Kaufmann
committed
move rand functions from util to new random.h/.cpp
1 parent 001a53d commit 6354935

16 files changed

+220
-185
lines changed

src/Makefile.am

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ BITCOIN_CORE_H = \
9191
noui.h \
9292
pow.h \
9393
protocol.h \
94+
random.h \
9495
rpcclient.h \
9596
rpcprotocol.h \
9697
rpcserver.h \
@@ -197,14 +198,15 @@ libbitcoin_common_a_SOURCES = \
197198
# backward-compatibility objects and their sanity checks are linked.
198199
libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
199200
libbitcoin_util_a_SOURCES = \
201+
compat/glibc_sanity.cpp \
202+
compat/glibcxx_sanity.cpp \
200203
chainparamsbase.cpp \
204+
random.cpp \
201205
rpcprotocol.cpp \
202206
sync.cpp \
203207
uint256.cpp \
204208
util.cpp \
205209
version.cpp \
206-
compat/glibc_sanity.cpp \
207-
compat/glibcxx_sanity.cpp \
208210
$(BITCOIN_CORE_H)
209211

210212
if GLIBC_BACK_COMPAT

src/addrman.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "netbase.h"
99
#include "protocol.h"
10+
#include "random.h"
1011
#include "sync.h"
1112
#include "timedata.h"
1213
#include "util.h"

src/chainparams.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "chainparams.h"
77

88
#include "assert.h"
9+
#include "random.h"
910
#include "util.h"
1011

1112
#include <boost/assign/list_of.hpp>

src/net.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "mruset.h"
1414
#include "netbase.h"
1515
#include "protocol.h"
16+
#include "random.h"
1617
#include "sync.h"
1718
#include "uint256.h"
1819
#include "util.h"
@@ -26,7 +27,6 @@
2627

2728
#include <boost/foreach.hpp>
2829
#include <boost/signals2/signal.hpp>
29-
#include <openssl/rand.h>
3030

3131
class CAddrMan;
3232
class CBlockIndex;

src/random.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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
11+
#include "util.h" // for LogPrint()
12+
13+
#ifndef WIN32
14+
#include <sys/time.h>
15+
#endif
16+
#include <cstring> // for memset()
17+
18+
#include <openssl/crypto.h>
19+
#include <openssl/err.h>
20+
#include <openssl/rand.h>
21+
22+
static inline int64_t GetPerformanceCounter()
23+
{
24+
int64_t nCounter = 0;
25+
#ifdef WIN32
26+
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
27+
#else
28+
timeval t;
29+
gettimeofday(&t, NULL);
30+
nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
31+
#endif
32+
return nCounter;
33+
}
34+
35+
void RandAddSeed()
36+
{
37+
// Seed with CPU performance counter
38+
int64_t nCounter = GetPerformanceCounter();
39+
RAND_add(&nCounter, sizeof(nCounter), 1.5);
40+
memset(&nCounter, 0, sizeof(nCounter));
41+
}
42+
43+
void RandAddSeedPerfmon()
44+
{
45+
RandAddSeed();
46+
47+
// This can take up to 2 seconds, so only do it every 10 minutes
48+
static int64_t nLastPerfmon;
49+
if (GetTime() < nLastPerfmon + 10 * 60)
50+
return;
51+
nLastPerfmon = GetTime();
52+
53+
#ifdef WIN32
54+
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
55+
// Seed with the entire set of perfmon data
56+
std::vector <unsigned char> vData(250000,0);
57+
long ret = 0;
58+
unsigned long nSize = 0;
59+
const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
60+
while (true)
61+
{
62+
nSize = vData.size();
63+
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
64+
if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
65+
break;
66+
vData.resize(std::max((vData.size()*3)/2, nMaxSize)); // Grow size of buffer exponentially
67+
}
68+
RegCloseKey(HKEY_PERFORMANCE_DATA);
69+
if (ret == ERROR_SUCCESS)
70+
{
71+
RAND_add(begin_ptr(vData), nSize, nSize/100.0);
72+
OPENSSL_cleanse(begin_ptr(vData), nSize);
73+
LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
74+
} else {
75+
static bool warned = false; // Warn only once
76+
if (!warned)
77+
{
78+
LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
79+
warned = true;
80+
}
81+
}
82+
#endif
83+
}
84+
85+
bool GetRandBytes(unsigned char *buf, int num)
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+
94+
uint64_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+
109+
int GetRandInt(int nMax)
110+
{
111+
return GetRand(nMax);
112+
}
113+
114+
uint256 GetRandHash()
115+
{
116+
uint256 hash;
117+
GetRandBytes((unsigned char*)&hash, sizeof(hash));
118+
return hash;
119+
}
120+
121+
uint32_t insecure_rand_Rz = 11;
122+
uint32_t insecure_rand_Rw = 11;
123+
void seed_insecure_rand(bool fDeterministic)
124+
{
125+
// The seed values have some unlikely fixed points which we avoid.
126+
if(fDeterministic)
127+
{
128+
insecure_rand_Rz = insecure_rand_Rw = 11;
129+
} else {
130+
uint32_t tmp;
131+
do {
132+
GetRandBytes((unsigned char*)&tmp, 4);
133+
} while(tmp == 0 || tmp == 0x9068ffffU);
134+
insecure_rand_Rz = tmp;
135+
do {
136+
GetRandBytes((unsigned char*)&tmp, 4);
137+
} while(tmp == 0 || tmp == 0x464fffffU);
138+
insecure_rand_Rw = tmp;
139+
}
140+
}

src/random.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
#ifndef BITCOIN_RANDOM_H
7+
#define BITCOIN_RANDOM_H
8+
9+
#include "uint256.h"
10+
11+
#include <stdint.h>
12+
13+
/**
14+
* Seed OpenSSL PRNG with additional entropy data
15+
*/
16+
void RandAddSeed();
17+
void RandAddSeedPerfmon();
18+
19+
/**
20+
* Functions to gather random data via the OpenSSL PRNG
21+
*/
22+
bool GetRandBytes(unsigned char *buf, int num);
23+
uint64_t GetRand(uint64_t nMax);
24+
int GetRandInt(int nMax);
25+
uint256 GetRandHash();
26+
27+
/**
28+
* Seed insecure_rand using the random pool.
29+
* @param Deterministic Use a determinstic seed
30+
*/
31+
void seed_insecure_rand(bool fDeterministic = false);
32+
33+
/**
34+
* MWC RNG of George Marsaglia
35+
* This is intended to be fast. It has a period of 2^59.3, though the
36+
* least significant 16 bits only have a period of about 2^30.1.
37+
*
38+
* @return random value
39+
*/
40+
extern uint32_t insecure_rand_Rz;
41+
extern uint32_t insecure_rand_Rw;
42+
static inline uint32_t insecure_rand(void)
43+
{
44+
insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
45+
insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
46+
return (insecure_rand_Rw << 16) + insecure_rand_Rz;
47+
}
48+
49+
#endif // BITCOIN_RANDOM_H

src/script.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55

66
#include "script.h"
77

8+
#include "crypto/ripemd160.h"
9+
#include "crypto/sha1.h"
10+
#include "crypto/sha2.h"
811
#include "core.h"
912
#include "hash.h"
1013
#include "key.h"
1114
#include "keystore.h"
12-
#include "crypto/sha1.h"
13-
#include "crypto/sha2.h"
14-
#include "crypto/ripemd160.h"
15+
#include "random.h"
1516
#include "sync.h"
1617
#include "uint256.h"
1718
#include "util.h"
@@ -1097,7 +1098,6 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig
10971098
// Valid signature cache, to avoid doing expensive ECDSA signature checking
10981099
// twice for every transaction (once when accepted into memory pool, and
10991100
// again when accepted into the block chain)
1100-
11011101
class CSignatureCache
11021102
{
11031103
private:

src/test/canonical_tests.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
// Unit tests for canonical signatures
77
//
88

9-
10-
11-
#include "script.h"
12-
#include "util.h"
139
#include "data/sig_noncanonical.json.h"
1410
#include "data/sig_canonical.json.h"
11+
#include "random.h"
12+
#include "script.h"
13+
#include "util.h"
1514

1615
#include <boost/foreach.hpp>
1716
#include <boost/test/unit_test.hpp>
@@ -21,7 +20,6 @@
2120
using namespace std;
2221
using namespace json_spirit;
2322

24-
2523
// In script_tests.cpp
2624
extern Array read_json(const std::string& jsondata);
2725

src/test/crypto_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "crypto/ripemd160.h"
66
#include "crypto/sha1.h"
77
#include "crypto/sha2.h"
8+
#include "random.h"
89
#include "util.h"
910

1011
#include <vector>

src/test/mruset_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "mruset.h"
66

7+
#include "random.h"
78
#include "util.h"
89

910
#include <set>

0 commit comments

Comments
 (0)