0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-04 10:07:27 -05:00

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).
This commit is contained in:
Pieter Wuille 2019-10-29 11:55:59 -07:00
parent 483b94292e
commit d61f2bb076
4 changed files with 24 additions and 33 deletions

View file

@ -1258,6 +1258,11 @@ bool AppInitMain(NodeContext& node)
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler); CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop)); threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
// Gather some entropy once per minute.
scheduler.scheduleEvery([]{
RandAddPeriodic();
}, 60000);
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
GetMainSignals().RegisterWithMempoolSignals(mempool); GetMainSignals().RegisterWithMempoolSignals(mempool);

View file

@ -507,22 +507,16 @@ static void SeedSlow(CSHA512& hasher) noexcept
} }
/** Extract entropy from rng, strengthen it, and feed it into hasher. */ /** Extract entropy from rng, strengthen it, and feed it into hasher. */
static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept static void SeedStrengthen(CSHA512& hasher, RNGState& rng, int microseconds) noexcept
{ {
static std::atomic<int64_t> last_strengthen{0}; // Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
int64_t last_time = last_strengthen.load(); unsigned char strengthen_seed[32];
int64_t current_time = GetTimeMicros(); rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
if (current_time > last_time + 60000000) { // Only run once a minute // Strengthen the seed, and feed it into hasher.
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher. Strengthen(strengthen_seed, microseconds, hasher);
unsigned char strengthen_seed[32];
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
// Strengthen it for 10ms (100ms on first run), and feed it into hasher.
Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher);
last_strengthen = current_time;
}
} }
static void SeedSleep(CSHA512& hasher, RNGState& rng) static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
{ {
// Everything that the 'fast' seeder includes // Everything that the 'fast' seeder includes
SeedFast(hasher); SeedFast(hasher);
@ -530,17 +524,11 @@ static void SeedSleep(CSHA512& hasher, RNGState& rng)
// High-precision timestamp // High-precision timestamp
SeedTimestamp(hasher); SeedTimestamp(hasher);
// Sleep for 1ms // Dynamic environment data (performance monitoring, ...)
MilliSleep(1);
// High-precision timestamp after sleeping (as we commit to both the time before and after, this measures the delay)
SeedTimestamp(hasher);
// Dynamic environment data (performance monitoring, ...; once every 10 minutes)
RandAddDynamicEnv(hasher); RandAddDynamicEnv(hasher);
// Strengthen every minute // Strengthen for 10 ms
SeedStrengthen(hasher, rng); SeedStrengthen(hasher, rng, 10000);
} }
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
@ -551,20 +539,20 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
// Everything that the 'slow' seeder includes. // Everything that the 'slow' seeder includes.
SeedSlow(hasher); SeedSlow(hasher);
// Dynamic environment data // Dynamic environment data (performance monitoring, ...)
RandAddDynamicEnv(hasher); RandAddDynamicEnv(hasher);
// Static environment data // Static environment data
RandAddStaticEnv(hasher); RandAddStaticEnv(hasher);
// Strengthen // Strengthen for 100 ms
SeedStrengthen(hasher, rng); SeedStrengthen(hasher, rng, 100000);
} }
enum class RNGLevel { enum class RNGLevel {
FAST, //!< Automatically called by GetRandBytes FAST, //!< Automatically called by GetRandBytes
SLOW, //!< Automatically called by GetStrongRandBytes SLOW, //!< Automatically called by GetStrongRandBytes
SLEEP, //!< Called by RandAddSeedSleep() PERIODIC, //!< Called by RandAddPeriodic()
}; };
static void ProcRand(unsigned char* out, int num, RNGLevel level) static void ProcRand(unsigned char* out, int num, RNGLevel level)
@ -582,8 +570,8 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
case RNGLevel::SLOW: case RNGLevel::SLOW:
SeedSlow(hasher); SeedSlow(hasher);
break; break;
case RNGLevel::SLEEP: case RNGLevel::PERIODIC:
SeedSleep(hasher, rng); SeedPeriodic(hasher, rng);
break; break;
} }
@ -606,7 +594,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 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 GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
void RandAddSeedSleep() { ProcRand(nullptr, 0, RNGLevel::SLEEP); } void RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
bool g_mock_deterministic_tests{false}; bool g_mock_deterministic_tests{false};

View file

@ -84,11 +84,11 @@ uint256 GetRandHash() noexcept;
void GetStrongRandBytes(unsigned char* buf, int num) noexcept; void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
/** /**
* Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG state. * Gather entropy from various expensive sources, and feed them to the PRNG state.
* *
* Thread-safe. * Thread-safe.
*/ */
void RandAddSeedSleep(); void RandAddPeriodic();
/** /**
* Fast randomness source. This is seeded once with secure random data, but * Fast randomness source. This is seeded once with secure random data, but

View file

@ -41,8 +41,6 @@ void CScheduler::serviceQueue()
try { try {
if (!shouldStop() && taskQueue.empty()) { if (!shouldStop() && taskQueue.empty()) {
reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
// Use this chance to get more entropy
RandAddSeedSleep();
} }
while (!shouldStop() && taskQueue.empty()) { while (!shouldStop() && taskQueue.empty()) {
// Wait until there is something to do. // Wait until there is something to do.