aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/random.cpp71
-rw-r--r--src/random.h2
2 files changed, 40 insertions, 33 deletions
diff --git a/src/random.cpp b/src/random.cpp
index fd1dfe506f..50b8477733 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -360,6 +360,9 @@ class RNGState {
uint64_t m_counter GUARDED_BY(m_mutex) = 0;
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
+ Mutex m_events_mutex;
+ CSHA256 m_events_hasher GUARDED_BY(m_events_mutex);
+
public:
RNGState() noexcept
{
@@ -370,6 +373,35 @@ public:
{
}
+ void AddEvent(uint32_t event_info) noexcept
+ {
+ LOCK(m_events_mutex);
+
+ m_events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info));
+ // Get the low four bytes of the performance counter. This translates to roughly the
+ // subsecond part.
+ uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
+ m_events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
+ }
+
+ /**
+ * Feed (the hash of) all events added through AddEvent() to hasher.
+ */
+ void SeedEvents(CSHA512& hasher) noexcept
+ {
+ // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
+ // since we want it to be fast as network peers may be able to trigger it repeatedly.
+ LOCK(m_events_mutex);
+
+ unsigned char events_hash[32];
+ m_events_hasher.Finalize(events_hash);
+ hasher.Write(events_hash, 32);
+
+ // Re-initialize the hasher with the finalized state to use later.
+ m_events_hasher.Reset();
+ m_events_hasher.Write(events_hash, 32);
+ }
+
/** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
*
* If this function has never been called with strong_seed = true, false is returned.
@@ -440,24 +472,7 @@ static void SeedFast(CSHA512& hasher) noexcept
SeedTimestamp(hasher);
}
-// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
-// since we want it to be fast as network peers may be able to trigger it repeatedly.
-static Mutex events_mutex;
-static CSHA256 events_hasher;
-static void SeedEvents(CSHA512& hasher)
-{
- LOCK(events_mutex);
-
- unsigned char events_hash[32];
- events_hasher.Finalize(events_hash);
- hasher.Write(events_hash, 32);
-
- // Re-initialize the hasher with the finalized state to use later.
- events_hasher.Reset();
- events_hasher.Write(events_hash, 32);
-}
-
-static void SeedSlow(CSHA512& hasher) noexcept
+static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
{
unsigned char buffer[32];
@@ -469,7 +484,7 @@ static void SeedSlow(CSHA512& hasher) noexcept
hasher.Write(buffer, sizeof(buffer));
// Add the events hasher into the mix
- SeedEvents(hasher);
+ rng.SeedEvents(hasher);
// High-precision timestamp.
//
@@ -497,7 +512,7 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
SeedTimestamp(hasher);
// Add the events hasher into the mix
- SeedEvents(hasher);
+ rng.SeedEvents(hasher);
// Dynamic environment data (performance monitoring, ...)
auto old_size = hasher.Size();
@@ -514,7 +529,7 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
SeedHardwareSlow(hasher);
// Everything that the 'slow' seeder includes.
- SeedSlow(hasher);
+ SeedSlow(hasher, rng);
// Dynamic environment data (performance monitoring, ...)
auto old_size = hasher.Size();
@@ -534,7 +549,7 @@ enum class RNGLevel {
PERIODIC, //!< Called by RandAddPeriodic()
};
-static void ProcRand(unsigned char* out, int num, RNGLevel level)
+static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
{
// Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
RNGState& rng = GetRNGState();
@@ -547,7 +562,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
SeedFast(hasher);
break;
case RNGLevel::SLOW:
- SeedSlow(hasher);
+ SeedSlow(hasher, rng);
break;
case RNGLevel::PERIODIC:
SeedPeriodic(hasher, rng);
@@ -566,15 +581,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
-
-void RandAddEvent(const uint32_t event_info) {
- LOCK(events_mutex);
- events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info));
- // Get the low four bytes of the performance counter. This translates to roughly the
- // subsecond part.
- uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
- events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
-}
+void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
bool g_mock_deterministic_tests{false};
diff --git a/src/random.h b/src/random.h
index 82dd6ecf9f..e1b105168d 100644
--- a/src/random.h
+++ b/src/random.h
@@ -95,7 +95,7 @@ void RandAddPeriodic() noexcept;
*
* Thread-safe.
*/
-void RandAddEvent(const uint32_t event_info);
+void RandAddEvent(const uint32_t event_info) noexcept;
/**
* Fast randomness source. This is seeded once with secure random data, but