6
6
#include < random.h>
7
7
8
8
#include < compat/cpuid.h>
9
+ #include < crypto/sha256.h>
9
10
#include < crypto/sha512.h>
10
11
#include < support/cleanse.h>
11
12
#ifdef WIN32
@@ -449,6 +450,23 @@ static void SeedFast(CSHA512& hasher) noexcept
449
450
SeedTimestamp (hasher);
450
451
}
451
452
453
+ // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
454
+ // since we want it to be fast as network peers may be able to trigger it repeatedly.
455
+ static Mutex events_mutex;
456
+ static CSHA256 events_hasher;
457
+ static void SeedEvents (CSHA512& hasher)
458
+ {
459
+ LOCK (events_mutex);
460
+
461
+ unsigned char events_hash[32 ];
462
+ events_hasher.Finalize (events_hash);
463
+ hasher.Write (events_hash, 32 );
464
+
465
+ // Re-initialize the hasher with the finalized state to use later.
466
+ events_hasher.Reset ();
467
+ events_hasher.Write (events_hash, 32 );
468
+ }
469
+
452
470
static void SeedSlow (CSHA512& hasher) noexcept
453
471
{
454
472
unsigned char buffer[32 ];
@@ -460,6 +478,9 @@ static void SeedSlow(CSHA512& hasher) noexcept
460
478
GetOSRand (buffer);
461
479
hasher.Write (buffer, sizeof (buffer));
462
480
481
+ // Add the events hasher into the mix
482
+ SeedEvents (hasher);
483
+
463
484
// High-precision timestamp.
464
485
//
465
486
// 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)
485
506
// High-precision timestamp
486
507
SeedTimestamp (hasher);
487
508
509
+ // Add the events hasher into the mix
510
+ SeedEvents (hasher);
511
+
488
512
// Dynamic environment data (performance monitoring, ...)
489
513
auto old_size = hasher.Size ();
490
514
RandAddDynamicEnv (hasher);
@@ -553,6 +577,15 @@ void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNG
553
577
void GetStrongRandBytes (unsigned char * buf, int num) noexcept { ProcRand (buf, num, RNGLevel::SLOW); }
554
578
void RandAddPeriodic () { ProcRand (nullptr , 0 , RNGLevel::PERIODIC); }
555
579
580
+ void RandAddEvent (const uint32_t event_info) {
581
+ LOCK (events_mutex);
582
+ events_hasher.Write ((const unsigned char *)&event_info, sizeof (event_info));
583
+ // Get the low four bytes of the performance counter. This translates to roughly the
584
+ // subsecond part.
585
+ uint32_t perfcounter = (GetPerformanceCounter () & 0xffffffff );
586
+ events_hasher.Write ((const unsigned char *)&perfcounter, sizeof (perfcounter));
587
+ }
588
+
556
589
bool g_mock_deterministic_tests{false };
557
590
558
591
uint64_t GetRand (uint64_t nMax) noexcept
0 commit comments