@ -16,6 +16,8 @@
@@ -16,6 +16,8 @@
# include <stdlib.h>
# include <limits>
# include <chrono>
# include <thread>
# ifndef WIN32
# include <sys/time.h>
@ -43,15 +45,22 @@ static void RandFailure()
@@ -43,15 +45,22 @@ static void RandFailure()
static inline int64_t GetPerformanceCounter ( )
{
int64_t nCounter = 0 ;
# ifdef WIN32
QueryPerformanceCounter ( ( LARGE_INTEGER * ) & nCounter ) ;
// Read the hardware time stamp counter when available.
// See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
return __rdtsc ( ) ;
# elif !defined(_MSC_VER) && defined(__i386__)
uint64_t r = 0 ;
__asm__ volatile ( " rdtsc " : " =A " ( r ) ) ; // Constrain the r variable to the eax:edx pair.
return r ;
# elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
uint64_t r1 = 0 , r2 = 0 ;
__asm__ volatile ( " rdtsc " : " =a " ( r1 ) , " =d " ( r2 ) ) ; // Constrain r1 to rax and r2 to rdx.
return ( r2 < < 32 ) | r1 ;
# else
timeval t ;
gettimeofday ( & t , NULL ) ;
nCounter = ( int64_t ) ( t . tv_sec * 1000000 + t . tv_usec ) ;
// Fall back to using C++11 clock (usually microsecond or nanosecond precision)
return std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) . count ( ) ;
# endif
return nCounter ;
}
void RandAddSeed ( )
@ -254,6 +263,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false)
@@ -254,6 +263,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false)
bool Random_SanityCheck ( )
{
uint64_t start = GetPerformanceCounter ( ) ;
/* This does not measure the quality of randomness, but it does test that
* OSRandom ( ) overwrites all 32 bytes of the output given a maximum
* number of tries .
@ -280,7 +291,18 @@ bool Random_SanityCheck()
@@ -280,7 +291,18 @@ bool Random_SanityCheck()
tries + = 1 ;
} while ( num_overwritten < NUM_OS_RANDOM_BYTES & & tries < MAX_TRIES ) ;
return ( num_overwritten = = NUM_OS_RANDOM_BYTES ) ; /* If this failed, bailed out after too many tries */
if ( num_overwritten ! = NUM_OS_RANDOM_BYTES ) return false ; /* If this failed, bailed out after too many tries */
// Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
uint64_t stop = GetPerformanceCounter ( ) ;
if ( stop = = start ) return false ;
// We called GetPerformanceCounter. Use it as entropy.
RAND_add ( ( const unsigned char * ) & start , sizeof ( start ) , 1 ) ;
RAND_add ( ( const unsigned char * ) & stop , sizeof ( stop ) , 1 ) ;
return true ;
}
FastRandomContext : : FastRandomContext ( bool fDeterministic ) : requires_seed ( ! fDeterministic ) , bytebuf_size ( 0 ) , bitbuf_size ( 0 )