@@ -365,6 +365,9 @@ class RNGState {
365365 uint64_t m_counter GUARDED_BY (m_mutex) = 0;
366366 bool m_strongly_seeded GUARDED_BY (m_mutex) = false;
367367
368+ Mutex m_events_mutex;
369+ CSHA256 m_events_hasher GUARDED_BY (m_events_mutex);
370+
368371public:
369372 RNGState () noexcept
370373 {
@@ -375,6 +378,35 @@ class RNGState {
375378 {
376379 }
377380
381+ void AddEvent (uint32_t event_info) noexcept
382+ {
383+ LOCK (m_events_mutex);
384+
385+ m_events_hasher.Write ((const unsigned char *)&event_info, sizeof (event_info));
386+ // Get the low four bytes of the performance counter. This translates to roughly the
387+ // subsecond part.
388+ uint32_t perfcounter = (GetPerformanceCounter () & 0xffffffff );
389+ m_events_hasher.Write ((const unsigned char *)&perfcounter, sizeof (perfcounter));
390+ }
391+
392+ /* *
393+ * Feed (the hash of) all events added through AddEvent() to hasher.
394+ */
395+ void SeedEvents (CSHA512& hasher) noexcept
396+ {
397+ // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
398+ // since we want it to be fast as network peers may be able to trigger it repeatedly.
399+ LOCK (m_events_mutex);
400+
401+ unsigned char events_hash[32 ];
402+ m_events_hasher.Finalize (events_hash);
403+ hasher.Write (events_hash, 32 );
404+
405+ // Re-initialize the hasher with the finalized state to use later.
406+ m_events_hasher.Reset ();
407+ m_events_hasher.Write (events_hash, 32 );
408+ }
409+
378410 /* * Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
379411 *
380412 * If this function has never been called with strong_seed = true, false is returned.
@@ -445,24 +477,7 @@ static void SeedFast(CSHA512& hasher) noexcept
445477 SeedTimestamp (hasher);
446478}
447479
448- // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
449- // since we want it to be fast as network peers may be able to trigger it repeatedly.
450- static Mutex events_mutex;
451- static CSHA256 events_hasher;
452- static void SeedEvents (CSHA512& hasher)
453- {
454- LOCK (events_mutex);
455-
456- unsigned char events_hash[32 ];
457- events_hasher.Finalize (events_hash);
458- hasher.Write (events_hash, 32 );
459-
460- // Re-initialize the hasher with the finalized state to use later.
461- events_hasher.Reset ();
462- events_hasher.Write (events_hash, 32 );
463- }
464-
465- static void SeedSlow (CSHA512& hasher) noexcept
480+ static void SeedSlow (CSHA512& hasher, RNGState& rng) noexcept
466481{
467482 unsigned char buffer[32 ];
468483
@@ -474,7 +489,7 @@ static void SeedSlow(CSHA512& hasher) noexcept
474489 hasher.Write (buffer, sizeof (buffer));
475490
476491 // Add the events hasher into the mix
477- SeedEvents (hasher);
492+ rng. SeedEvents (hasher);
478493
479494 // High-precision timestamp.
480495 //
@@ -502,7 +517,7 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
502517 SeedTimestamp (hasher);
503518
504519 // Add the events hasher into the mix
505- SeedEvents (hasher);
520+ rng. SeedEvents (hasher);
506521
507522 // Dynamic environment data (performance monitoring, ...)
508523 auto old_size = hasher.Size ();
@@ -519,7 +534,7 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
519534 SeedHardwareSlow (hasher);
520535
521536 // Everything that the 'slow' seeder includes.
522- SeedSlow (hasher);
537+ SeedSlow (hasher, rng );
523538
524539 // Dynamic environment data (performance monitoring, ...)
525540 auto old_size = hasher.Size ();
@@ -539,7 +554,7 @@ enum class RNGLevel {
539554 PERIODIC, // !< Called by RandAddPeriodic()
540555};
541556
542- static void ProcRand (unsigned char * out, int num, RNGLevel level)
557+ static void ProcRand (unsigned char * out, int num, RNGLevel level) noexcept
543558{
544559 // Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
545560 RNGState& rng = GetRNGState ();
@@ -552,7 +567,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
552567 SeedFast (hasher);
553568 break ;
554569 case RNGLevel::SLOW:
555- SeedSlow (hasher);
570+ SeedSlow (hasher, rng );
556571 break ;
557572 case RNGLevel::PERIODIC:
558573 SeedPeriodic (hasher, rng);
@@ -581,15 +596,7 @@ std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max)
581596void GetRandBytes (unsigned char * buf, int num) noexcept { ProcRand (buf, num, RNGLevel::FAST); }
582597void GetStrongRandBytes (unsigned char * buf, int num) noexcept { ProcRand (buf, num, RNGLevel::SLOW); }
583598void RandAddPeriodic () noexcept { ProcRand (nullptr , 0 , RNGLevel::PERIODIC); }
584-
585- void RandAddEvent (const uint32_t event_info) {
586- LOCK (events_mutex);
587- events_hasher.Write ((const unsigned char *)&event_info, sizeof (event_info));
588- // Get the low four bytes of the performance counter. This translates to roughly the
589- // subsecond part.
590- uint32_t perfcounter = (GetPerformanceCounter () & 0xffffffff );
591- events_hasher.Write ((const unsigned char *)&perfcounter, sizeof (perfcounter));
592- }
599+ void RandAddEvent (const uint32_t event_info) noexcept { GetRNGState ().AddEvent (event_info); }
593600
594601bool g_mock_deterministic_tests{false };
595602
0 commit comments