16
16
17
17
#include < stdlib.h>
18
18
#include < limits>
19
+ #include < chrono>
20
+ #include < thread>
19
21
20
22
#ifndef WIN32
21
23
#include < sys/time.h>
@@ -43,15 +45,22 @@ static void RandFailure()
43
45
44
46
static inline int64_t GetPerformanceCounter ()
45
47
{
46
- int64_t nCounter = 0 ;
47
- #ifdef WIN32
48
- QueryPerformanceCounter ((LARGE_INTEGER*)&nCounter);
48
+ // Read the hardware time stamp counter when available.
49
+ // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
50
+ #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
51
+ return __rdtsc ();
52
+ #elif !defined(_MSC_VER) && defined(__i386__)
53
+ uint64_t r = 0 ;
54
+ __asm__ volatile (" rdtsc" : " =A" (r)); // Constrain the r variable to the eax:edx pair.
55
+ return r;
56
+ #elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
57
+ uint64_t r1 = 0 , r2 = 0 ;
58
+ __asm__ volatile (" rdtsc" : " =a" (r1), " =d" (r2)); // Constrain r1 to rax and r2 to rdx.
59
+ return (r2 << 32 ) | r1;
49
60
#else
50
- timeval t;
51
- gettimeofday (&t, NULL );
52
- nCounter = (int64_t )(t.tv_sec * 1000000 + t.tv_usec );
61
+ // Fall back to using C++11 clock (usually microsecond or nanosecond precision)
62
+ return std::chrono::high_resolution_clock::now ().time_since_epoch ().count ();
53
63
#endif
54
- return nCounter;
55
64
}
56
65
57
66
void RandAddSeed ()
@@ -254,6 +263,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false)
254
263
255
264
bool Random_SanityCheck ()
256
265
{
266
+ uint64_t start = GetPerformanceCounter ();
267
+
257
268
/* This does not measure the quality of randomness, but it does test that
258
269
* OSRandom() overwrites all 32 bytes of the output given a maximum
259
270
* number of tries.
@@ -280,7 +291,18 @@ bool Random_SanityCheck()
280
291
281
292
tries += 1 ;
282
293
} while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
283
- return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
294
+ if (num_overwritten != NUM_OS_RANDOM_BYTES) return false ; /* If this failed, bailed out after too many tries */
295
+
296
+ // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.
297
+ std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
298
+ uint64_t stop = GetPerformanceCounter ();
299
+ if (stop == start) return false ;
300
+
301
+ // We called GetPerformanceCounter. Use it as entropy.
302
+ RAND_add ((const unsigned char *)&start, sizeof (start), 1 );
303
+ RAND_add ((const unsigned char *)&stop, sizeof (stop), 1 );
304
+
305
+ return true ;
284
306
}
285
307
286
308
FastRandomContext::FastRandomContext (bool fDeterministic ) : requires_seed(!fDeterministic ), bytebuf_size(0 ), bitbuf_size(0 )
0 commit comments