@ -6,6 +6,7 @@
# include <random.h>
# include <compat/cpuid.h>
# include <crypto/sha256.h>
# include <crypto/sha512.h>
# include <support/cleanse.h>
# ifdef WIN32
@ -449,6 +450,23 @@ static void SeedFast(CSHA512& hasher) noexcept
SeedTimestamp ( hasher ) ;
}
// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
// since we want it to be fast as network peers may be able to trigger it repeatedly.
static Mutex events_mutex ;
static CSHA256 events_hasher ;
static void SeedEvents ( CSHA512 & hasher )
{
LOCK ( events_mutex ) ;
unsigned char events_hash [ 32 ] ;
events_hasher . Finalize ( events_hash ) ;
hasher . Write ( events_hash , 32 ) ;
// Re-initialize the hasher with the finalized state to use later.
events_hasher . Reset ( ) ;
events_hasher . Write ( events_hash , 32 ) ;
}
static void SeedSlow ( CSHA512 & hasher ) noexcept
{
unsigned char buffer [ 32 ] ;
@ -460,6 +478,9 @@ static void SeedSlow(CSHA512& hasher) noexcept
GetOSRand ( buffer ) ;
hasher . Write ( buffer , sizeof ( buffer ) ) ;
// Add the events hasher into the mix
SeedEvents ( hasher ) ;
// High-precision timestamp.
//
// Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
@ -485,6 +506,9 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
// High-precision timestamp
SeedTimestamp ( hasher ) ;
// Add the events hasher into the mix
SeedEvents ( hasher ) ;
// Dynamic environment data (performance monitoring, ...)
auto old_size = hasher . Size ( ) ;
RandAddDynamicEnv ( hasher ) ;
@ -553,6 +577,15 @@ void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNG
void GetStrongRandBytes ( unsigned char * buf , int num ) noexcept { ProcRand ( buf , num , RNGLevel : : SLOW ) ; }
void RandAddPeriodic ( ) { ProcRand ( nullptr , 0 , RNGLevel : : PERIODIC ) ; }
void RandAddEvent ( const uint32_t event_info ) {
LOCK ( events_mutex ) ;
events_hasher . Write ( ( const unsigned char * ) & event_info , sizeof ( event_info ) ) ;
// Get the low four bytes of the performance counter. This translates to roughly the
// subsecond part.
uint32_t perfcounter = ( GetPerformanceCounter ( ) & 0xffffffff ) ;
events_hasher . Write ( ( const unsigned char * ) & perfcounter , sizeof ( perfcounter ) ) ;
}
bool g_mock_deterministic_tests { false } ;
uint64_t GetRand ( uint64_t nMax ) noexcept