Skip to content

Commit 248ad17

Browse files
MarcoFalkeknst
authored andcommitted
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
1 parent a8c13e2 commit 248ad17

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
@@ -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+
368371
public:
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)
581596
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
582597
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
583598
void 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

594601
bool g_mock_deterministic_tests{false};
595602

src/random.h

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

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

0 commit comments

Comments
 (0)