7
7
#include " random.h"
8
8
9
9
#include " compat/cpuid.h"
10
+ #include " crypto/sha256.h"
10
11
#include " crypto/sha512.h"
11
12
#include " support/cleanse.h"
12
13
#ifdef WIN32
@@ -489,6 +490,23 @@ static void SeedFast(CSHA512& hasher) noexcept
489
490
SeedTimestamp (hasher);
490
491
}
491
492
493
+ // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
494
+ // since we want it to be fast as network peers may be able to trigger it repeatedly.
495
+ static Mutex events_mutex;
496
+ static CSHA256 events_hasher;
497
+ static void SeedEvents (CSHA512& hasher)
498
+ {
499
+ LOCK (events_mutex);
500
+
501
+ unsigned char events_hash[32 ];
502
+ events_hasher.Finalize (events_hash);
503
+ hasher.Write (events_hash, 32 );
504
+
505
+ // Re-initialize the hasher with the finalized state to use later.
506
+ events_hasher.Reset ();
507
+ events_hasher.Write (events_hash, 32 );
508
+ }
509
+
492
510
static void SeedSlow (CSHA512& hasher) noexcept
493
511
{
494
512
unsigned char buffer[32 ];
@@ -504,6 +522,9 @@ static void SeedSlow(CSHA512& hasher) noexcept
504
522
RAND_bytes (buffer, sizeof (buffer));
505
523
hasher.Write (buffer, sizeof (buffer));
506
524
525
+ // Add the events hasher into the mix
526
+ SeedEvents (hasher);
527
+
507
528
// High-precision timestamp.
508
529
//
509
530
// Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
@@ -529,6 +550,9 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
529
550
// High-precision timestamp
530
551
SeedTimestamp (hasher);
531
552
553
+ // Add the events hasher into the mix
554
+ SeedEvents (hasher);
555
+
532
556
// Dynamic environment data (performance monitoring, ...)
533
557
RandAddDynamicEnv (hasher);
534
558
@@ -601,6 +625,15 @@ void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNG
601
625
void GetStrongRandBytes (unsigned char * buf, int num) noexcept { ProcRand (buf, num, RNGLevel::SLOW); }
602
626
void RandAddPeriodic () { ProcRand (nullptr , 0 , RNGLevel::PERIODIC); }
603
627
628
+ void RandAddEvent (const uint32_t event_info) {
629
+ LOCK (events_mutex);
630
+ events_hasher.Write ((const unsigned char *)&event_info, sizeof (event_info));
631
+ // Get the low four bytes of the performance counter. This translates to roughly the
632
+ // subsecond part.
633
+ uint32_t perfcounter = (GetPerformanceCounter () & 0xffffffff );
634
+ events_hasher.Write ((const unsigned char *)&perfcounter, sizeof (perfcounter));
635
+ }
636
+
604
637
bool g_mock_deterministic_tests{false };
605
638
606
639
uint64_t GetRand (uint64_t nMax) noexcept
0 commit comments