Skip to content

Commit 5d0b7f9

Browse files
author
MarcoFalke
committed
Merge bitcoin#17670: Move events_hasher into RNGState()
8bda096 Move events_hasher into RNGState() (Pieter Wuille) Pull request description: This moves `events_hasher` and `events_mutex` into `RNGState()` in random.cpp. This guarantees (through the existing `GetRNGState()` function) that the mutex is always created before any events are added, even when that happens inside global initializers. Fixes the issue reported here: bitcoin#17573 (comment), and includes the annotation from bitcoin#17666). ACKs for top commit: MarcoFalke: re-ACK 8bda096 🥈 sipsorcery: re-ACK 8bda096. Tree-SHA512: 78702d668764df19e9d61d87d82eca71cceca87d5351b740e13e732a1c18a3d53d7fbaaf63245266da597370bfebec9fa6a4749c15ec5a78dcfe6122c33553ed
2 parents 910a430 + 8bda096 commit 5d0b7f9

File tree

2 files changed

+40
-33
lines changed

2 files changed

+40
-33
lines changed

src/random.cpp

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ class RNGState {
360360
uint64_t m_counter GUARDED_BY(m_mutex) = 0;
361361
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
362362

363+
Mutex m_events_mutex;
364+
CSHA256 m_events_hasher GUARDED_BY(m_events_mutex);
365+
363366
public:
364367
RNGState() noexcept
365368
{
@@ -370,6 +373,35 @@ class RNGState {
370373
{
371374
}
372375

376+
void AddEvent(uint32_t event_info) noexcept
377+
{
378+
LOCK(m_events_mutex);
379+
380+
m_events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info));
381+
// Get the low four bytes of the performance counter. This translates to roughly the
382+
// subsecond part.
383+
uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
384+
m_events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
385+
}
386+
387+
/**
388+
* Feed (the hash of) all events added through AddEvent() to hasher.
389+
*/
390+
void SeedEvents(CSHA512& hasher) noexcept
391+
{
392+
// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
393+
// since we want it to be fast as network peers may be able to trigger it repeatedly.
394+
LOCK(m_events_mutex);
395+
396+
unsigned char events_hash[32];
397+
m_events_hasher.Finalize(events_hash);
398+
hasher.Write(events_hash, 32);
399+
400+
// Re-initialize the hasher with the finalized state to use later.
401+
m_events_hasher.Reset();
402+
m_events_hasher.Write(events_hash, 32);
403+
}
404+
373405
/** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
374406
*
375407
* If this function has never been called with strong_seed = true, false is returned.
@@ -440,24 +472,7 @@ static void SeedFast(CSHA512& hasher) noexcept
440472
SeedTimestamp(hasher);
441473
}
442474

443-
// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
444-
// since we want it to be fast as network peers may be able to trigger it repeatedly.
445-
static Mutex events_mutex;
446-
static CSHA256 events_hasher;
447-
static void SeedEvents(CSHA512& hasher)
448-
{
449-
LOCK(events_mutex);
450-
451-
unsigned char events_hash[32];
452-
events_hasher.Finalize(events_hash);
453-
hasher.Write(events_hash, 32);
454-
455-
// Re-initialize the hasher with the finalized state to use later.
456-
events_hasher.Reset();
457-
events_hasher.Write(events_hash, 32);
458-
}
459-
460-
static void SeedSlow(CSHA512& hasher) noexcept
475+
static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
461476
{
462477
unsigned char buffer[32];
463478

@@ -469,7 +484,7 @@ static void SeedSlow(CSHA512& hasher) noexcept
469484
hasher.Write(buffer, sizeof(buffer));
470485

471486
// Add the events hasher into the mix
472-
SeedEvents(hasher);
487+
rng.SeedEvents(hasher);
473488

474489
// High-precision timestamp.
475490
//
@@ -497,7 +512,7 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
497512
SeedTimestamp(hasher);
498513

499514
// Add the events hasher into the mix
500-
SeedEvents(hasher);
515+
rng.SeedEvents(hasher);
501516

502517
// Dynamic environment data (performance monitoring, ...)
503518
auto old_size = hasher.Size();
@@ -514,7 +529,7 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
514529
SeedHardwareSlow(hasher);
515530

516531
// Everything that the 'slow' seeder includes.
517-
SeedSlow(hasher);
532+
SeedSlow(hasher, rng);
518533

519534
// Dynamic environment data (performance monitoring, ...)
520535
auto old_size = hasher.Size();
@@ -534,7 +549,7 @@ enum class RNGLevel {
534549
PERIODIC, //!< Called by RandAddPeriodic()
535550
};
536551

537-
static void ProcRand(unsigned char* out, int num, RNGLevel level)
552+
static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
538553
{
539554
// Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
540555
RNGState& rng = GetRNGState();
@@ -547,7 +562,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
547562
SeedFast(hasher);
548563
break;
549564
case RNGLevel::SLOW:
550-
SeedSlow(hasher);
565+
SeedSlow(hasher, rng);
551566
break;
552567
case RNGLevel::PERIODIC:
553568
SeedPeriodic(hasher, rng);
@@ -566,15 +581,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
566581
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
567582
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
568583
void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
569-
570-
void RandAddEvent(const uint32_t event_info) {
571-
LOCK(events_mutex);
572-
events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info));
573-
// Get the low four bytes of the performance counter. This translates to roughly the
574-
// subsecond part.
575-
uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
576-
events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
577-
}
584+
void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
578585

579586
bool g_mock_deterministic_tests{false};
580587

src/random.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void RandAddPeriodic() noexcept;
9595
*
9696
* Thread-safe.
9797
*/
98-
void RandAddEvent(const uint32_t event_info);
98+
void RandAddEvent(const uint32_t event_info) noexcept;
9999

100100
/**
101101
* Fast randomness source. This is seeded once with secure random data, but

0 commit comments

Comments
 (0)