Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501// benchmark of all the entropy gathering sources in this function).502SeedTimestamp(hasher);503}505/** Extract entropy from rng, strengthen it, and feed it into hasher. */506void SeedStrengthen(CSHA512& hasher, RNGState& rng, SteadyClock::duration dur) noexcept507{508// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.509// Never use the deterministic PRNG for this, as the result is only used internally.510unsigned char strengthen_seed[32];511rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false, /*always_use_real_rng=*/true);512// Strengthen the seed, and feed it into hasher.513Strengthen(strengthen_seed, dur, hasher);514}516void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept517{518// Everything that the 'fast' seeder includes519SeedFast(hasher);521// High-precision timestamp522SeedTimestamp(hasher);524// Add the events hasher into the mix525rng.SeedEvents(hasher);527// Dynamic environment data (clocks, resource usage, ...)528auto old_size = hasher.Size();529RandAddDynamicEnv(hasher);530LogDebug(BCLog::RAND, "Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);532// Strengthen for 10 ms533SeedStrengthen(hasher, rng, 10ms);534}536void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept537{538// Gather 256 bits of hardware randomness, if available539SeedHardwareSlow(hasher);541// Everything that the 'slow' seeder includes.542SeedSlow(hasher, rng);544// Dynamic environment data (clocks, resource usage, ...)545auto old_size = hasher.Size();546RandAddDynamicEnv(hasher);548// Static environment data549RandAddStaticEnv(hasher);550LogDebug(BCLog::RAND, "Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);552// Strengthen for 100 ms553SeedStrengthen(hasher, rng, 100ms);554}556enum class RNGLevel {557FAST, //!< Automatically called by GetRandBytes558SLOW, //!< Automatically called by GetStrongRandBytes559PERIODIC, //!< Called by RandAddPeriodic()560};562void ProcRand(unsigned char* out, int num, RNGLevel level, bool always_use_real_rng) noexcept563{564// Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).565RNGState& rng = GetRNGState();567assert(num <= 32);569CSHA512 hasher;570switch (level) {571case RNGLevel::FAST:572SeedFast(hasher);573break;574case RNGLevel::SLOW:575SeedSlow(hasher, rng);576break;577case RNGLevel::PERIODIC:578SeedPeriodic(hasher, rng);579break;580}582// Combine with and update state583if (!rng.MixExtract(out, num, std::move(hasher), false, always_use_real_rng)) {584// On the first invocation, also seed with SeedStartup().585CSHA512 startup_hasher;586SeedStartup(startup_hasher, rng);587rng.MixExtract(out, num, std::move(startup_hasher), true, always_use_real_rng);588}589}591} // namespace594/** Internal function to set g_determinstic_rng. Only accessed from tests. */595void MakeRandDeterministicDANGEROUS(const uint256& seed) noexcept596{597GetRNGState().MakeDeterministic(seed);598}599std::atomic<bool> g_used_g_prng{false}; // Only accessed from tests601void GetRandBytes(std::span<unsigned char> bytes) noexcept602{603g_used_g_prng = true;604ProcRand(bytes.data(), bytes.size(), RNGLevel::FAST, /*always_use_real_rng=*/false);605}607void GetStrongRandBytes(std::span<unsigned char> bytes) noexcept608{609ProcRand(bytes.data(), bytes.size(), RNGLevel::SLOW, /*always_use_real_rng=*/true);610}612void RandAddPeriodic() noexcept613{614ProcRand(nullptr, 0, RNGLevel::PERIODIC, /*always_use_real_rng=*/false);615}617void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }619void FastRandomContext::RandomSeed() noexcept620{621uint256 seed = GetRandHash();622rng.SetKey(MakeByteSpan(seed));623requires_seed = false;624}626void FastRandomContext::fillrand(std::span<std::byte> output) noexcept627{628if (requires_seed) RandomSeed();629rng.Keystream(output);630}632FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), rng(MakeByteSpan(seed)) {}634void FastRandomContext::Reseed(const uint256& seed) noexcept635{636FlushCache();637requires_seed = false;638rng = {MakeByteSpan(seed)};639}641bool Random_SanityCheck()642{643uint64_t start = GetPerformanceCounter();645/* This does not measure the quality of randomness, but it does test that646* GetOSRand() overwrites all 32 bytes of the output given a maximum647* number of tries.648*/649static constexpr int MAX_TRIES{1024};650uint8_t data[NUM_OS_RANDOM_BYTES];651bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */652int num_overwritten;653int tries = 0;654/* Loop until all bytes have been overwritten at least once, or max number tries reached */655do {656memset(data, 0, NUM_OS_RANDOM_BYTES);657GetOSRand(data);658for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {659overwritten[x] |= (data[x] != 0);660}662num_overwritten = 0;663for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {664if (overwritten[x]) {665num_overwritten += 1;666}667}669tries += 1;670} while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);671if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */673// Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.674std::this_thread::sleep_for(std::chrono::milliseconds(1));675uint64_t stop = GetPerformanceCounter();676if (stop == start) return false;678// We called GetPerformanceCounter. Use it as entropy.679CSHA512 to_add;680to_add.Write((const unsigned char*)&start, sizeof(start));681to_add.Write((const unsigned char*)&stop, sizeof(stop));682GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false, /*always_use_real_rng=*/true);684return true;685}687static constexpr std::array<std::byte, ChaCha20::KEYLEN> ZERO_KEY{};689FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), rng(ZERO_KEY)690{691// Note that despite always initializing with ZERO_KEY, requires_seed is set to true if not692// fDeterministic. That means the rng will be reinitialized with a secure random key upon first693// use.694}696void RandomInit()697{698// Invoke RNG code to trigger initialization (if not already performed)699ProcRand(nullptr, 0, RNGLevel::FAST, /*always_use_real_rng=*/true);701ReportHardwareRand();702}704double MakeExponentiallyDistributed(uint64_t uniform) noexcept705{706// To convert uniform into an exponentially-distributed double, we use two steps:707// - Convert uniform into a uniformly-distributed double in range [0, 1), use the expression708// ((uniform >> 11) * 0x1.0p-53), as described in https://prng.di.unimi.it/ under709// "Generating uniform doubles in the unit interval". Call this value x.710// - Given an x in uniformly distributed in [0, 1), we find an exponentially distributed value711// by applying the quantile function to it. For the exponential distribution with mean 1 this712// is F(x) = -log(1 - x).713//714// Combining the two, and using log1p(x) = log(1 + x), we obtain the following:715return -std::log1p((uniform >> 11) * -0x1.0p-53);716}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.