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.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <bitcoin-build-config.h> // IWYU pragma: keep8#include <random.h>10#include <compat/compat.h>11#include <compat/cpuid.h>12#include <crypto/chacha20.h>13#include <crypto/sha256.h>14#include <crypto/sha512.h>15#include <randomenv.h>16#include <span.h>17#include <support/allocators/secure.h>18#include <support/cleanse.h>19#include <sync.h>20#include <util/log.h>21#include <util/time.h>23#include <array>24#include <cmath>25#include <cstdlib>26#include <optional>27#include <thread>29#ifdef WIN3230#include <bcrypt.h>31#else32#include <fcntl.h>33#include <sys/time.h>34#endif36#if defined(HAVE_GETRANDOM) || (defined(HAVE_GETENTROPY_RAND) && defined(__APPLE__))37#include <sys/random.h>38#endif40#ifdef HAVE_SYSCTL_ARND41#include <sys/sysctl.h>42#endif44namespace {46/* Number of random bytes returned by GetOSRand.47* When changing this constant make sure to change all call sites, and make48* sure that the underlying OS APIs for all platforms support the number.49* (many cap out at 256 bytes).50*/51static const int NUM_OS_RANDOM_BYTES = 32;54[[noreturn]] void RandFailure()55{56LogError("Failed to read randomness, aborting\n");57std::abort();58}60inline int64_t GetPerformanceCounter() noexcept61{62// Read the hardware time stamp counter when available.63// See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.64#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))65return __rdtsc();66#elif !defined(_MSC_VER) && defined(__i386__)67uint64_t r = 0;68__asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair.69return r;70#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))71uint64_t r1 = 0, r2 = 0;72__asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.73return (r2 << 32) | r1;74#else75// Fall back to using standard library clock (usually microsecond or nanosecond precision)76return std::chrono::high_resolution_clock::now().time_since_epoch().count();77#endif78}80#ifdef HAVE_GETCPUID81bool g_rdrand_supported = false;82bool g_rdseed_supported = false;83constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;84constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;85#ifdef bit_RDRND86static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, "Unexpected value for bit_RDRND");87#endif88#ifdef bit_RDSEED89static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, "Unexpected value for bit_RDSEED");90#endif92void InitHardwareRand()93{94uint32_t eax, ebx, ecx, edx;95GetCPUID(1, 0, eax, ebx, ecx, edx);96if (ecx & CPUID_F1_ECX_RDRAND) {97g_rdrand_supported = true;98}99GetCPUID(7, 0, eax, ebx, ecx, edx);100if (ebx & CPUID_F7_EBX_RDSEED) {101g_rdseed_supported = true;102}103}105void ReportHardwareRand()106{107// This must be done in a separate function, as InitHardwareRand() may be indirectly called108// from global constructors, before logging is initialized.109if (g_rdseed_supported) {110LogInfo("Using RdSeed as an additional entropy source");111}112if (g_rdrand_supported) {113LogInfo("Using RdRand as an additional entropy source");114}115}117/** Read 64 bits of entropy using rdrand.118*119* Must only be called when RdRand is supported.120*/121uint64_t GetRdRand() noexcept122{123// RdRand may very rarely fail. Invoke it up to 10 times in a loop to reduce this risk.124#ifdef __i386__125uint8_t ok = 0;126// Initialize to 0 to silence a compiler warning that r1 or r2 may be used127// uninitialized. Even if rdrand fails (!ok) it will set the output to 0,128// but there is no way that the compiler could know that.129uint32_t r1 = 0, r2 = 0;130for (int i = 0; i < 10; ++i) {131__asm__ volatile (".byte 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %eax132if (ok) break;133}134for (int i = 0; i < 10; ++i) {135__asm__ volatile (".byte 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdrand %eax136if (ok) break;137}138return (((uint64_t)r2) << 32) | r1;139#elif defined(__x86_64__) || defined(__amd64__)140uint8_t ok = 0;141uint64_t r1 = 0; // See above why we initialize to 0.142for (int i = 0; i < 10; ++i) {143__asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %rax144if (ok) break;145}146return r1;147#else148#error "RdRand is only supported on x86 and x86_64"149#endif150}152/** Read 64 bits of entropy using rdseed.153*154* Must only be called when RdSeed is supported.155*/156uint64_t GetRdSeed() noexcept157{158// RdSeed may fail when the HW RNG is overloaded. Loop indefinitely until enough entropy is gathered,159// but pause after every failure.160#ifdef __i386__161uint8_t ok = 0;162uint32_t r1, r2;163do {164__asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %eax165if (ok) break;166__asm__ volatile ("pause");167} while(true);168do {169__asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdseed %eax170if (ok) break;171__asm__ volatile ("pause");172} while(true);173return (((uint64_t)r2) << 32) | r1;174#elif defined(__x86_64__) || defined(__amd64__)175uint8_t ok;176uint64_t r1;177do {178__asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %rax179if (ok) break;180__asm__ volatile ("pause");181} while(true);182return r1;183#else184#error "RdSeed is only supported on x86 and x86_64"185#endif186}188#else189/* Access to other hardware random number generators could be added here later,190* assuming it is sufficiently fast (in the order of a few hundred CPU cycles).191* Slower sources should probably be invoked separately, and/or only from192* RandAddPeriodic (which is called once a minute).193*/194void InitHardwareRand() {}195void ReportHardwareRand() {}196#endif198/** Add 64 bits of entropy gathered from hardware to hasher. Do nothing if not supported. */199void SeedHardwareFast(CSHA512& hasher) noexcept {200#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)201if (g_rdrand_supported) {202uint64_t out = GetRdRand();203hasher.Write((const unsigned char*)&out, sizeof(out));204return;205}206#endif207}209/** Add 256 bits of entropy gathered from hardware to hasher. Do nothing if not supported. */210void SeedHardwareSlow(CSHA512& hasher) noexcept {211#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)212// When we want 256 bits of entropy, prefer RdSeed over RdRand, as it's213// guaranteed to produce independent randomness on every call.214if (g_rdseed_supported) {215for (int i = 0; i < 4; ++i) {216uint64_t out = GetRdSeed();217hasher.Write((const unsigned char*)&out, sizeof(out));218}219return;220}221// When falling back to RdRand, XOR the result of 1024 results.222// This guarantees a reseeding occurs between each.223if (g_rdrand_supported) {224for (int i = 0; i < 4; ++i) {225uint64_t out = 0;226for (int j = 0; j < 1024; ++j) out ^= GetRdRand();227hasher.Write((const unsigned char*)&out, sizeof(out));228}229return;230}231#endif232}234/** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */235void Strengthen(const unsigned char (&seed)[32], SteadyClock::duration dur, CSHA512& hasher) noexcept236{237CSHA512 inner_hasher;238inner_hasher.Write(seed, sizeof(seed));240// Hash loop241unsigned char buffer[64];242const auto stop{SteadyClock::now() + dur};243do {244for (int i = 0; i < 1000; ++i) {245inner_hasher.Finalize(buffer);246inner_hasher.Reset();247inner_hasher.Write(buffer, sizeof(buffer));248}249// Benchmark operation and feed it into outer hasher.250int64_t perf = GetPerformanceCounter();
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.