Skip to content

Commit 7d6ddcb

Browse files
sipaFuzzbawls
authored andcommitted
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 4679181 commit 7d6ddcb

File tree

5 files changed

+26
-35
lines changed

5 files changed

+26
-35
lines changed

src/init.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,11 @@ bool AppInitMain()
12541254
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
12551255
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
12561256

1257+
// Gather some entropy once per minute.
1258+
scheduler.scheduleEvery([]{
1259+
RandAddPeriodic();
1260+
}, 60000);
1261+
12571262
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
12581263
GetMainSignals().RegisterWithMempoolSignals(mempool);
12591264

src/libzerocoin/bignum_gmp.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ CBigNum CBigNum::randBignum(const CBigNum& range)
6363
size_t size = (mpz_sizeinbase (range.bn, 2) + CHAR_BIT-1) / CHAR_BIT;
6464
std::vector<unsigned char> buf(size);
6565

66-
RandAddSeedSleep();
66+
RandAddPeriodic();
6767
GetRandBytes(buf.data(), size);
6868

6969
CBigNum ret(buf);
@@ -80,7 +80,7 @@ CBigNum CBigNum::randKBitBignum(const uint32_t k)
8080
{
8181
std::vector<unsigned char> buf((k+7)/8);
8282

83-
RandAddSeedSleep();
83+
RandAddPeriodic();
8484
GetRandBytes(buf.data(), (k+7)/8);
8585

8686
CBigNum ret(buf);

src/random.cpp

+17-29
Original file line numberDiff line numberDiff line change
@@ -511,40 +511,28 @@ static void SeedSlow(CSHA512& hasher) noexcept
511511
}
512512

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

529-
static void SeedSleep(CSHA512& hasher, RNGState& rng)
523+
static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
530524
{
531525
// Everything that the 'fast' seeder includes
532526
SeedFast(hasher);
533527

534528
// High-precision timestamp
535529
SeedTimestamp(hasher);
536530

537-
// Sleep for 1ms
538-
MilliSleep(1);
539-
540-
// High-precision timestamp after sleeping (as we commit to both the time before and after, this measures the delay)
541-
SeedTimestamp(hasher);
542-
543-
// Dynamic environment data (performance monitoring, ...; once every 10 minutes)
531+
// Dynamic environment data (performance monitoring, ...)
544532
RandAddDynamicEnv(hasher);
545533

546-
// Strengthen every minute
547-
SeedStrengthen(hasher, rng);
534+
// Strengthen for 10 ms
535+
SeedStrengthen(hasher, rng, 10000);
548536
}
549537

550538
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
@@ -555,20 +543,20 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
555543
// Everything that the 'slow' seeder includes.
556544
SeedSlow(hasher);
557545

558-
// Dynamic environment data
546+
// Dynamic environment data (performance monitoring, ...)
559547
RandAddDynamicEnv(hasher);
560548

561549
// Static environment data
562550
RandAddStaticEnv(hasher);
563551

564-
// Strengthen
565-
SeedStrengthen(hasher, rng);
552+
// Strengthen for 100 ms
553+
SeedStrengthen(hasher, rng, 100000);
566554
}
567555

568556
enum class RNGLevel {
569557
FAST, //!< Automatically called by GetRandBytes
570558
SLOW, //!< Automatically called by GetStrongRandBytes
571-
SLEEP, //!< Called by RandAddSeedSleep()
559+
PERIODIC, //!< Called by RandAddPeriodic()
572560
};
573561

574562
static void ProcRand(unsigned char* out, int num, RNGLevel level)
@@ -586,8 +574,8 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
586574
case RNGLevel::SLOW:
587575
SeedSlow(hasher);
588576
break;
589-
case RNGLevel::SLEEP:
590-
SeedSleep(hasher, rng);
577+
case RNGLevel::PERIODIC:
578+
SeedPeriodic(hasher, rng);
591579
break;
592580
}
593581

@@ -610,7 +598,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
610598

611599
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
612600
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
613-
void RandAddSeedSleep() { ProcRand(nullptr, 0, RNGLevel::SLEEP); }
601+
void RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
614602

615603
bool g_mock_deterministic_tests{false};
616604

src/random.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ uint256 GetRandHash() noexcept;
8383
void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
8484

8585
/**
86-
* Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG state.
86+
* Gather entropy from various expensive sources, and feed them to the PRNG state.
8787
*
8888
* Thread-safe.
8989
*/
90-
void RandAddSeedSleep();
90+
void RandAddPeriodic();
9191

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

src/scheduler.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ void CScheduler::serviceQueue()
3232
try {
3333
if (!shouldStop() && taskQueue.empty()) {
3434
reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
35-
// Use this chance to get more entropy
36-
RandAddSeedSleep();
3735
}
3836
while (!shouldStop() && taskQueue.empty()) {
3937
// Wait until there is something to do.

0 commit comments

Comments
 (0)