Skip to content

Commit d61f2bb

Browse files
committed
Run background seeding periodically instead of unpredictably
* Instead of calling RandAddSeedSleep anytime the scheduler goes idle, call its replacement (RandAddSeedPeriodic) just once per minute. This has better guarantees of actually being run, and helps limit how frequently the dynamic env data is gathered. * Since this code runs once per minute regardless now, we no longer need to keep track of the last time strengthening was run; just do it always. * Make strengthening time context dependent (100 ms at startup, 10 ms once per minute afterwards).
1 parent 483b942 commit d61f2bb

File tree

4 files changed

+24
-33
lines changed

4 files changed

+24
-33
lines changed

src/init.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,11 @@ bool AppInitMain(NodeContext& node)
12581258
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
12591259
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
12601260

1261+
// Gather some entropy once per minute.
1262+
scheduler.scheduleEvery([]{
1263+
RandAddPeriodic();
1264+
}, 60000);
1265+
12611266
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
12621267
GetMainSignals().RegisterWithMempoolSignals(mempool);
12631268

src/random.cpp

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -507,40 +507,28 @@ static void SeedSlow(CSHA512& hasher) noexcept
507507
}
508508

509509
/** Extract entropy from rng, strengthen it, and feed it into hasher. */
510-
static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept
510+
static void SeedStrengthen(CSHA512& hasher, RNGState& rng, int microseconds) noexcept
511511
{
512-
static std::atomic<int64_t> last_strengthen{0};
513-
int64_t last_time = last_strengthen.load();
514-
int64_t current_time = GetTimeMicros();
515-
if (current_time > last_time + 60000000) { // Only run once a minute
516-
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
517-
unsigned char strengthen_seed[32];
518-
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
519-
// Strengthen it for 10ms (100ms on first run), and feed it into hasher.
520-
Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher);
521-
last_strengthen = current_time;
522-
}
512+
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
513+
unsigned char strengthen_seed[32];
514+
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
515+
// Strengthen the seed, and feed it into hasher.
516+
Strengthen(strengthen_seed, microseconds, hasher);
523517
}
524518

525-
static void SeedSleep(CSHA512& hasher, RNGState& rng)
519+
static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
526520
{
527521
// Everything that the 'fast' seeder includes
528522
SeedFast(hasher);
529523

530524
// High-precision timestamp
531525
SeedTimestamp(hasher);
532526

533-
// Sleep for 1ms
534-
MilliSleep(1);
535-
536-
// High-precision timestamp after sleeping (as we commit to both the time before and after, this measures the delay)
537-
SeedTimestamp(hasher);
538-
539-
// Dynamic environment data (performance monitoring, ...; once every 10 minutes)
527+
// Dynamic environment data (performance monitoring, ...)
540528
RandAddDynamicEnv(hasher);
541529

542-
// Strengthen every minute
543-
SeedStrengthen(hasher, rng);
530+
// Strengthen for 10 ms
531+
SeedStrengthen(hasher, rng, 10000);
544532
}
545533

546534
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
@@ -551,20 +539,20 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
551539
// Everything that the 'slow' seeder includes.
552540
SeedSlow(hasher);
553541

554-
// Dynamic environment data
542+
// Dynamic environment data (performance monitoring, ...)
555543
RandAddDynamicEnv(hasher);
556544

557545
// Static environment data
558546
RandAddStaticEnv(hasher);
559547

560-
// Strengthen
561-
SeedStrengthen(hasher, rng);
548+
// Strengthen for 100 ms
549+
SeedStrengthen(hasher, rng, 100000);
562550
}
563551

564552
enum class RNGLevel {
565553
FAST, //!< Automatically called by GetRandBytes
566554
SLOW, //!< Automatically called by GetStrongRandBytes
567-
SLEEP, //!< Called by RandAddSeedSleep()
555+
PERIODIC, //!< Called by RandAddPeriodic()
568556
};
569557

570558
static void ProcRand(unsigned char* out, int num, RNGLevel level)
@@ -582,8 +570,8 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
582570
case RNGLevel::SLOW:
583571
SeedSlow(hasher);
584572
break;
585-
case RNGLevel::SLEEP:
586-
SeedSleep(hasher, rng);
573+
case RNGLevel::PERIODIC:
574+
SeedPeriodic(hasher, rng);
587575
break;
588576
}
589577

@@ -606,7 +594,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
606594

607595
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
608596
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
609-
void RandAddSeedSleep() { ProcRand(nullptr, 0, RNGLevel::SLEEP); }
597+
void RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
610598

611599
bool g_mock_deterministic_tests{false};
612600

src/random.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ uint256 GetRandHash() noexcept;
8484
void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
8585

8686
/**
87-
* Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG state.
87+
* Gather entropy from various expensive sources, and feed them to the PRNG state.
8888
*
8989
* Thread-safe.
9090
*/
91-
void RandAddSeedSleep();
91+
void RandAddPeriodic();
9292

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

src/scheduler.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ void CScheduler::serviceQueue()
4141
try {
4242
if (!shouldStop() && taskQueue.empty()) {
4343
reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
44-
// Use this chance to get more entropy
45-
RandAddSeedSleep();
4644
}
4745
while (!shouldStop() && taskQueue.empty()) {
4846
// Wait until there is something to do.

0 commit comments

Comments
 (0)