/Users/eugenesiegel/btc/bitcoin/src/random.h
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2009-2010 Satoshi Nakamoto | 
| 2 |  | // Copyright (c) 2009-present The Bitcoin Core developers | 
| 3 |  | // Distributed under the MIT software license, see the accompanying | 
| 4 |  | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | 
| 5 |  |  | 
| 6 |  | #ifndef BITCOIN_RANDOM_H | 
| 7 |  | #define BITCOIN_RANDOM_H | 
| 8 |  |  | 
| 9 |  | #include <crypto/chacha20.h> | 
| 10 |  | #include <crypto/common.h> | 
| 11 |  | #include <span.h> | 
| 12 |  | #include <uint256.h> | 
| 13 |  | #include <util/check.h> | 
| 14 |  |  | 
| 15 |  | #include <bit> | 
| 16 |  | #include <cassert> | 
| 17 |  | #include <chrono> | 
| 18 |  | #include <concepts> | 
| 19 |  | #include <cstdint> | 
| 20 |  | #include <limits> | 
| 21 |  | #include <type_traits> | 
| 22 |  | #include <vector> | 
| 23 |  |  | 
| 24 |  | /** | 
| 25 |  |  * Overall design of the RNG and entropy sources. | 
| 26 |  |  * | 
| 27 |  |  * We maintain a single global 256-bit RNG state for all high-quality randomness. | 
| 28 |  |  * The following (classes of) functions interact with that state by mixing in new | 
| 29 |  |  * entropy, and optionally extracting random output from it: | 
| 30 |  |  * | 
| 31 |  |  * - GetRandBytes, GetRandHash, GetRandDur, as well as construction of FastRandomContext | 
| 32 |  |  *   objects, perform 'fast' seeding, consisting of mixing in: | 
| 33 |  |  *   - A stack pointer (indirectly committing to calling thread and call stack) | 
| 34 |  |  *   - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise) | 
| 35 |  |  *   - 64 bits from the hardware RNG (rdrand) when available. | 
| 36 |  |  *   These entropy sources are very fast, and only designed to protect against situations | 
| 37 |  |  *   where a VM state restore/copy results in multiple systems with the same randomness. | 
| 38 |  |  *   FastRandomContext on the other hand does not protect against this once created, but | 
| 39 |  |  *   is even faster (and acceptable to use inside tight loops). | 
| 40 |  |  * | 
| 41 |  |  * - The GetStrongRandBytes() function performs 'slow' seeding, including everything | 
| 42 |  |  *   that fast seeding includes, but additionally: | 
| 43 |  |  *   - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if | 
| 44 |  |  *     this entropy source fails. | 
| 45 |  |  *   - Another high-precision timestamp (indirectly committing to a benchmark of all the | 
| 46 |  |  *     previous sources). | 
| 47 |  |  *   These entropy sources are slower, but designed to make sure the RNG state contains | 
| 48 |  |  *   fresh data that is unpredictable to attackers. | 
| 49 |  |  * | 
| 50 |  |  * - RandAddPeriodic() seeds everything that fast seeding includes, but additionally: | 
| 51 |  |  *   - A high-precision timestamp | 
| 52 |  |  *   - Dynamic environment data (clocks, resource usage, ...) | 
| 53 |  |  *   - Strengthen the entropy for 10 ms using repeated SHA512. | 
| 54 |  |  *   This is run once every minute. | 
| 55 |  |  * | 
| 56 |  |  * - On first use of the RNG (regardless of what function is called first), all entropy | 
| 57 |  |  *   sources used in the 'slow' seeder are included, but also: | 
| 58 |  |  *   - 256 bits from the hardware RNG (rdseed or rdrand) when available. | 
| 59 |  |  *   - Dynamic environment data (performance monitoring, ...) | 
| 60 |  |  *   - Static environment data | 
| 61 |  |  *   - Strengthen the entropy for 100 ms using repeated SHA512. | 
| 62 |  |  * | 
| 63 |  |  * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and | 
| 64 |  |  * (up to) the first 32 bytes of H are produced as output, while the last 32 bytes | 
| 65 |  |  * become the new RNG state. | 
| 66 |  |  * | 
| 67 |  |  * During tests, the RNG can be put into a special deterministic mode, in which the output | 
| 68 |  |  * of all RNG functions, with the exception of GetStrongRandBytes(), is replaced with the | 
| 69 |  |  * output of a deterministic RNG. This deterministic RNG does not gather entropy, and is | 
| 70 |  |  * unaffected by RandAddPeriodic() or RandAddEvent(). It produces pseudorandom data that | 
| 71 |  |  * only depends on the seed it was initialized with, possibly until it is reinitialized. | 
| 72 |  | */ | 
| 73 |  |  | 
| 74 |  |  | 
| 75 |  | /* ============================= INITIALIZATION AND ADDING ENTROPY ============================= */ | 
| 76 |  |  | 
| 77 |  | /** | 
| 78 |  |  * Initialize global RNG state and log any CPU features that are used. | 
| 79 |  |  * | 
| 80 |  |  * Calling this function is optional. RNG state will be initialized when first | 
| 81 |  |  * needed if it is not called. | 
| 82 |  |  */ | 
| 83 |  | void RandomInit(); | 
| 84 |  |  | 
| 85 |  | /** | 
| 86 |  |  * Gather entropy from various expensive sources, and feed them to the PRNG state. | 
| 87 |  |  * | 
| 88 |  |  * Thread-safe. | 
| 89 |  |  */ | 
| 90 |  | void RandAddPeriodic() noexcept; | 
| 91 |  |  | 
| 92 |  | /** | 
| 93 |  |  * Gathers entropy from the low bits of the time at which events occur. Should | 
| 94 |  |  * be called with a uint32_t describing the event at the time an event occurs. | 
| 95 |  |  * | 
| 96 |  |  * Thread-safe. | 
| 97 |  |  */ | 
| 98 |  | void RandAddEvent(const uint32_t event_info) noexcept; | 
| 99 |  |  | 
| 100 |  |  | 
| 101 |  | /* =========================== BASE RANDOMNESS GENERATION FUNCTIONS =========================== | 
| 102 |  |  * | 
| 103 |  |  * All produced randomness is eventually generated by one of these functions. | 
| 104 |  |  */ | 
| 105 |  |  | 
| 106 |  | /** | 
| 107 |  |  * Generate random data via the internal PRNG. | 
| 108 |  |  * | 
| 109 |  |  * These functions are designed to be fast (sub microsecond), but do not necessarily | 
| 110 |  |  * meaningfully add entropy to the PRNG state. | 
| 111 |  |  * | 
| 112 |  |  * In test mode (see SeedRandomForTest in src/test/util/random.h), the normal PRNG state is | 
| 113 |  |  * bypassed, and a deterministic, seeded, PRNG is used instead. | 
| 114 |  |  * | 
| 115 |  |  * Thread-safe. | 
| 116 |  |  */ | 
| 117 |  | void GetRandBytes(std::span<unsigned char> bytes) noexcept; | 
| 118 |  |  | 
| 119 |  | /** | 
| 120 |  |  * Gather entropy from various sources, feed it into the internal PRNG, and | 
| 121 |  |  * generate random data using it. | 
| 122 |  |  * | 
| 123 |  |  * This function will cause failure whenever the OS RNG fails. | 
| 124 |  |  * | 
| 125 |  |  * The normal PRNG is never bypassed here, even in test mode. | 
| 126 |  |  * | 
| 127 |  |  * Thread-safe. | 
| 128 |  |  */ | 
| 129 |  | void GetStrongRandBytes(std::span<unsigned char> bytes) noexcept; | 
| 130 |  |  | 
| 131 |  |  | 
| 132 |  | /* ============================= RANDOM NUMBER GENERATION CLASSES ============================= | 
| 133 |  |  * | 
| 134 |  |  * In this section, 3 classes are defined: | 
| 135 |  |  * - RandomMixin:            a base class that adds functionality to all RNG classes. | 
| 136 |  |  * - FastRandomContext:      a cryptographic RNG (seeded through GetRandBytes in its default | 
| 137 |  |  *                           constructor). | 
| 138 |  |  * - InsecureRandomContext:  a non-cryptographic, very fast, RNG. | 
| 139 |  |  */ | 
| 140 |  |  | 
| 141 |  | // Forward declaration of RandomMixin, used in RandomNumberGenerator concept. | 
| 142 |  | template<typename T> | 
| 143 |  | class RandomMixin; | 
| 144 |  |  | 
| 145 |  | /** A concept for RandomMixin-based random number generators. */ | 
| 146 |  | template<typename T> | 
| 147 |  | concept RandomNumberGenerator = requires(T& rng, std::span<std::byte> s) { | 
| 148 |  |     // A random number generator must provide rand64(). | 
| 149 |  |     { rng.rand64() } noexcept -> std::same_as<uint64_t>; | 
| 150 |  |     // A random number generator must derive from RandomMixin, which adds other rand* functions. | 
| 151 |  |     requires std::derived_from<std::remove_reference_t<T>, RandomMixin<std::remove_reference_t<T>>>; | 
| 152 |  | }; | 
| 153 |  |  | 
| 154 |  | /** A concept for C++ std::chrono durations. */ | 
| 155 |  | template<typename T> | 
| 156 |  | concept StdChronoDuration = requires { | 
| 157 | 0 |     []<class Rep, class Period>(std::type_identity<std::chrono::duration<Rep, Period>>){}(Unexecuted instantiation: wallet.cpp:_ZZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1000000EEEEEEEQ17StdChronoDurationINTL0__8durationEEEENT_8durationESF_ENKUlTyTyNS3_13type_identityINS7_ISE_T0_EEEEE_clIxS9_EEDaSJ_Unexecuted instantiation: mapport.cpp:_ZZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000EEEEEEET_NS3_11common_typeIJS9_EE4typeEENKUlTyTyNS3_13type_identityINS5_IS9_T0_EEEEE_clIxS7_EEDaSG_Unexecuted instantiation: net.cpp:_ZZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono12steady_clockEQ17StdChronoDurationINTL0__8durationEEEENT_8durationES9_ENKUlTyTyNS3_13type_identityINS4_8durationIS8_T0_EEEEE_clIxNS3_5ratioILl1ELl1000000000EEEEEDaSE_Unexecuted instantiation: net.cpp:_ZZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000000EEEEEEET_NS3_11common_typeIJS9_EE4typeEENKUlTyTyNS3_13type_identityINS5_IS9_T0_EEEEE_clIxS7_EEDaSG_Unexecuted instantiation: net.cpp:_ZZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1EEEEEEEQ17StdChronoDurationINTL0__8durationEEEENT_8durationESF_ENKUlTyTyNS3_13type_identityINS7_ISE_T0_EEEEE_clIxS9_EEDaSJ_Unexecuted instantiation: net_processing.cpp:_ZZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000EEEEEEET_NS3_11common_typeIJS9_EE4typeEENKUlTyTyNS3_13type_identityINS5_IS9_T0_EEEEE_clIxS7_EEDaSG_Unexecuted instantiation: net_processing.cpp:_ZZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000000EEEEEEET_NS3_11common_typeIJS9_EE4typeEENKUlTyTyNS3_13type_identityINS5_IS9_T0_EEEEE_clIxS7_EEDaSG_Unexecuted instantiation: validation.cpp:_ZZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1000000EEEEEEEQ17StdChronoDurationINTL0__8durationEEEENT_8durationESF_ENKUlTyTyNS3_13type_identityINS7_ISE_T0_EEEEE_clIxS9_EEDaSJ_ | 
| 158 |  |         std::type_identity<T>()); | 
| 159 |  | }; | 
| 160 |  |  | 
| 161 |  | /** Given a uniformly random uint64_t, return an exponentially distributed double with mean 1. */ | 
| 162 |  | double MakeExponentiallyDistributed(uint64_t uniform) noexcept; | 
| 163 |  |  | 
| 164 |  | /** Mixin class that provides helper randomness functions. | 
| 165 |  |  * | 
| 166 |  |  * Intended to be used through CRTP: https://en.cppreference.com/w/cpp/language/crtp. | 
| 167 |  |  * An RNG class FunkyRNG would derive publicly from RandomMixin<FunkyRNG>. This permits | 
| 168 |  |  * RandomMixin from accessing the derived class's rand64() function, while also allowing | 
| 169 |  |  * the derived class to provide more. | 
| 170 |  |  * | 
| 171 |  |  * The derived class must satisfy the RandomNumberGenerator concept. | 
| 172 |  |  */ | 
| 173 |  | template<typename T> | 
| 174 |  | class RandomMixin | 
| 175 |  | { | 
| 176 |  | private: | 
| 177 |  |     uint64_t bitbuf{0}; | 
| 178 |  |     int bitbuf_size{0}; | 
| 179 |  |  | 
| 180 |  |     /** Access the underlying generator. | 
| 181 |  |      * | 
| 182 |  |      * This also enforces the RandomNumberGenerator concept. We cannot declare that in the template | 
| 183 |  |      * (no template<RandomNumberGenerator T>) because the type isn't fully instantiated yet there. | 
| 184 |  |      */ | 
| 185 | 3.80M |     RandomNumberGenerator auto& Impl() noexcept { return static_cast<T&>(*this); }_ZN11RandomMixinI17FastRandomContextE4ImplEv| Line | Count | Source |  | 185 | 3.80M |     RandomNumberGenerator auto& Impl() noexcept { return static_cast<T&>(*this); } | 
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE4ImplEv | 
| 186 |  |  | 
| 187 |  | protected: | 
| 188 |  |     constexpr void FlushCache() noexcept | 
| 189 | 0 |     { | 
| 190 | 0 |         bitbuf = 0; | 
| 191 | 0 |         bitbuf_size = 0; | 
| 192 | 0 |     } Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE10FlushCacheEvUnexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE10FlushCacheEv | 
| 193 |  |  | 
| 194 |  | public: | 
| 195 | 15.4M |     constexpr RandomMixin() noexcept = default; Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextEC2Ev_ZN11RandomMixinI17FastRandomContextEC2Ev| Line | Count | Source |  | 195 | 15.4M |     constexpr RandomMixin() noexcept = default; | 
 | 
| 196 |  |  | 
| 197 |  |     // Do not permit copying or moving an RNG. | 
| 198 |  |     RandomMixin(const RandomMixin&) = delete; | 
| 199 |  |     RandomMixin& operator=(const RandomMixin&) = delete; | 
| 200 |  |     RandomMixin(RandomMixin&&) = delete; | 
| 201 |  |     RandomMixin& operator=(RandomMixin&&) = delete; | 
| 202 |  |  | 
| 203 |  |     /** Generate a random (bits)-bit integer. */ | 
| 204 |  |     uint64_t randbits(int bits) noexcept | 
| 205 | 2.86M |     { | 
| 206 | 2.86M |         Assume(bits <= 64); | Line | Count | Source |  | 118 | 2.86M | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(bits <= 64); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 | 
| 207 |  |         // Requests for the full 64 bits are passed through. | 
| 208 | 2.86M |         if (bits == 64) return Impl().rand64()0; | 
| 209 | 2.86M |         uint64_t ret; | 
| 210 | 2.86M |         if (bits <= bitbuf_size) { | 
| 211 |  |             // If there is enough entropy left in bitbuf, return its bottom bits bits. | 
| 212 | 2.82M |             ret = bitbuf; | 
| 213 | 2.82M |             bitbuf >>= bits; | 
| 214 | 2.82M |             bitbuf_size -= bits; | 
| 215 | 2.82M |         } else { | 
| 216 |  |             // If not, return all of bitbuf, supplemented with the (bits - bitbuf_size) bottom | 
| 217 |  |             // bits of a newly generated 64-bit number on top. The remainder of that generated | 
| 218 |  |             // number becomes the new bitbuf. | 
| 219 | 42.9k |             uint64_t gen = Impl().rand64(); | 
| 220 | 42.9k |             ret = (gen << bitbuf_size) | bitbuf; | 
| 221 | 42.9k |             bitbuf = gen >> (bits - bitbuf_size); | 
| 222 | 42.9k |             bitbuf_size = 64 + bitbuf_size - bits; | 
| 223 | 42.9k |         } | 
| 224 |  |         // Return the bottom bits bits of ret. | 
| 225 | 2.86M |         return ret & ((uint64_t{1} << bits) - 1); | 
| 226 | 2.86M |     } _ZN11RandomMixinI17FastRandomContextE8randbitsEi| Line | Count | Source |  | 205 | 2.86M |     { |  | 206 | 2.86M |         Assume(bits <= 64); | Line | Count | Source |  | 118 | 2.86M | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |  | 207 |  |         // Requests for the full 64 bits are passed through. |  | 208 | 2.86M |         if (bits == 64) return Impl().rand64()0; |  | 209 | 2.86M |         uint64_t ret; |  | 210 | 2.86M |         if (bits <= bitbuf_size) { |  | 211 |  |             // If there is enough entropy left in bitbuf, return its bottom bits bits. |  | 212 | 2.82M |             ret = bitbuf; |  | 213 | 2.82M |             bitbuf >>= bits; |  | 214 | 2.82M |             bitbuf_size -= bits; |  | 215 | 2.82M |         } else { |  | 216 |  |             // If not, return all of bitbuf, supplemented with the (bits - bitbuf_size) bottom |  | 217 |  |             // bits of a newly generated 64-bit number on top. The remainder of that generated |  | 218 |  |             // number becomes the new bitbuf. |  | 219 | 42.9k |             uint64_t gen = Impl().rand64(); |  | 220 | 42.9k |             ret = (gen << bitbuf_size) | bitbuf; |  | 221 | 42.9k |             bitbuf = gen >> (bits - bitbuf_size); |  | 222 | 42.9k |             bitbuf_size = 64 + bitbuf_size - bits; |  | 223 | 42.9k |         } |  | 224 |  |         // Return the bottom bits bits of ret. |  | 225 | 2.86M |         return ret & ((uint64_t{1} << bits) - 1); |  | 226 | 2.86M |     } | 
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsEi | 
| 227 |  |  | 
| 228 |  |     /** Same as above, but with compile-time fixed bits count. */ | 
| 229 |  |     template<int Bits> | 
| 230 |  |     uint64_t randbits() noexcept | 
| 231 | 329k |     { | 
| 232 | 329k |         static_assert(Bits >= 0 && Bits <= 64); | 
| 233 |  |         if constexpr (Bits == 64) { | 
| 234 |  |             return Impl().rand64(); | 
| 235 | 329k |         } else { | 
| 236 | 329k |             uint64_t ret; | 
| 237 | 329k |             if (Bits <= bitbuf_size) { | 
| 238 | 0 |                 ret = bitbuf; | 
| 239 | 0 |                 bitbuf >>= Bits; | 
| 240 | 0 |                 bitbuf_size -= Bits; | 
| 241 | 329k |             } else { | 
| 242 | 329k |                 uint64_t gen = Impl().rand64(); | 
| 243 | 329k |                 ret = (gen << bitbuf_size) | bitbuf; | 
| 244 | 329k |                 bitbuf = gen >> (Bits - bitbuf_size); | 
| 245 | 329k |                 bitbuf_size = 64 + bitbuf_size - Bits; | 
| 246 | 329k |             } | 
| 247 | 329k |             constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1; | 
| 248 | 329k |             return ret & MASK; | 
| 249 | 329k |         } | 
| 250 | 329k |     } Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsILi32EEEyvUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsILi8EEEyvUnexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randbitsILi1EEEyvUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsILi1EEEyv_ZN11RandomMixinI17FastRandomContextE8randbitsILi32EEEyv| Line | Count | Source |  | 231 | 329k |     { |  | 232 | 329k |         static_assert(Bits >= 0 && Bits <= 64); |  | 233 |  |         if constexpr (Bits == 64) { |  | 234 |  |             return Impl().rand64(); |  | 235 | 329k |         } else { |  | 236 | 329k |             uint64_t ret; |  | 237 | 329k |             if (Bits <= bitbuf_size) { |  | 238 | 0 |                 ret = bitbuf; |  | 239 | 0 |                 bitbuf >>= Bits; |  | 240 | 0 |                 bitbuf_size -= Bits; |  | 241 | 329k |             } else { |  | 242 | 329k |                 uint64_t gen = Impl().rand64(); |  | 243 | 329k |                 ret = (gen << bitbuf_size) | bitbuf; |  | 244 | 329k |                 bitbuf = gen >> (Bits - bitbuf_size); |  | 245 | 329k |                 bitbuf_size = 64 + bitbuf_size - Bits; |  | 246 | 329k |             } |  | 247 | 329k |             constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1; |  | 248 | 329k |             return ret & MASK; |  | 249 | 329k |         } |  | 250 | 329k |     } | 
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randbitsILi16EEEyvUnexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randbitsILi30EEEyv | 
| 251 |  |  | 
| 252 |  |     /** Generate a random integer in the range [0..range), with range > 0. */ | 
| 253 |  |     template<std::integral I> | 
| 254 |  |     I randrange(I range) noexcept | 
| 255 | 2.84M |     { | 
| 256 | 2.84M |         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max()); | 
| 257 | 2.84M |         Assume(range > 0); | Line | Count | Source |  | 118 | 2.80M | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 37.9k | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |         Assume(range > 0); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 | 
| 258 | 2.84M |         uint64_t maxval = range - 1U; | 
| 259 | 2.84M |         int bits = std::bit_width(maxval); | 
| 260 | 2.86M |         while (true) { | 
| 261 | 2.86M |             uint64_t ret = Impl().randbits(bits); | 
| 262 | 2.86M |             if (ret <= maxval) return ret2.84M; | 
| 263 | 2.86M |         } | 
| 264 | 2.84M |     } _ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralEiEET_S4_| Line | Count | Source |  | 255 | 2.80M |     { |  | 256 | 2.80M |         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max()); |  | 257 | 2.80M |         Assume(range > 0); | Line | Count | Source |  | 118 | 2.80M | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |  | 258 | 2.80M |         uint64_t maxval = range - 1U; |  | 259 | 2.80M |         int bits = std::bit_width(maxval); |  | 260 | 2.80M |         while (true) { |  | 261 | 2.80M |             uint64_t ret = Impl().randbits(bits); |  | 262 | 2.80M |             if (ret <= maxval) return ret; |  | 263 | 2.80M |         } |  | 264 | 2.80M |     } | 
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randrangeITkNSt3__18integralEjEET_S4_Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralEyEET_S4_Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randrangeITkNSt3__18integralEmEET_S4_Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randrangeITkNSt3__18integralEiEET_S4_Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralEmEET_S4__ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralExEET_S4_| Line | Count | Source |  | 255 | 37.9k |     { |  | 256 | 37.9k |         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max()); |  | 257 | 37.9k |         Assume(range > 0); | Line | Count | Source |  | 118 | 37.9k | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 |  | 258 | 37.9k |         uint64_t maxval = range - 1U; |  | 259 | 37.9k |         int bits = std::bit_width(maxval); |  | 260 | 55.4k |         while (true) { |  | 261 | 55.4k |             uint64_t ret = Impl().randbits(bits); |  | 262 | 55.4k |             if (ret <= maxval) return ret37.9k; |  | 263 | 55.4k |         } |  | 264 | 37.9k |     } | 
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralEjEET_S4_Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralElEET_S4_ | 
| 265 |  |  | 
| 266 |  |     /** Fill a span with random bytes. */ | 
| 267 |  |     void fillrand(std::span<std::byte> span) noexcept | 
| 268 | 0 |     { | 
| 269 | 0 |         while (span.size() >= 8) { | 
| 270 | 0 |             uint64_t gen = Impl().rand64(); | 
| 271 | 0 |             WriteLE64(span.data(), gen); | 
| 272 | 0 |             span = span.subspan(8); | 
| 273 | 0 |         } | 
| 274 | 0 |         if (span.size() >= 4) { | 
| 275 | 0 |             uint32_t gen = Impl().rand32(); | 
| 276 | 0 |             WriteLE32(span.data(), gen); | 
| 277 | 0 |             span = span.subspan(4); | 
| 278 | 0 |         } | 
| 279 | 0 |         while (span.size()) { | 
| 280 | 0 |             span[0] = std::byte(Impl().template randbits<8>()); | 
| 281 | 0 |             span = span.subspan(1); | 
| 282 | 0 |         } | 
| 283 | 0 |     } | 
| 284 |  |  | 
| 285 |  |     /** Generate a random integer in its entire (non-negative) range. */ | 
| 286 |  |     template<std::integral I> | 
| 287 |  |     I rand() noexcept | 
| 288 | 329k |     { | 
| 289 | 329k |         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max()); | 
| 290 | 329k |         static constexpr auto BITS = std::bit_width(uint64_t(std::numeric_limits<I>::max())); | 
| 291 | 329k |         static_assert(std::numeric_limits<I>::max() == std::numeric_limits<uint64_t>::max() >> (64 - BITS)); | 
| 292 | 329k |         return I(Impl().template randbits<BITS>()); | 
| 293 | 329k |     } _ZN11RandomMixinI17FastRandomContextE4randITkNSt3__18integralEjEET_v| Line | Count | Source |  | 288 | 329k |     { |  | 289 | 329k |         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max()); |  | 290 | 329k |         static constexpr auto BITS = std::bit_width(uint64_t(std::numeric_limits<I>::max())); |  | 291 | 329k |         static_assert(std::numeric_limits<I>::max() == std::numeric_limits<uint64_t>::max() >> (64 - BITS)); |  | 292 | 329k |         return I(Impl().template randbits<BITS>()); |  | 293 | 329k |     } | 
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE4randITkNSt3__18integralEtEET_v | 
| 294 |  |  | 
| 295 |  |     /** Generate random bytes. */ | 
| 296 |  |     template <BasicByte B = unsigned char> | 
| 297 |  |     std::vector<B> randbytes(size_t len) noexcept | 
| 298 | 0 |     { | 
| 299 | 0 |         std::vector<B> ret(len); | 
| 300 | 0 |         Impl().fillrand(MakeWritableByteSpan(ret)); | 
| 301 | 0 |         return ret; | 
| 302 | 0 |     } Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randbytesITk9BasicByteSt4byteEENSt3__16vectorIT_NS4_9allocatorIS6_EEEEmUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randbytesITk9BasicBytehEENSt3__16vectorIT_NS3_9allocatorIS5_EEEEmUnexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randbytesITk9BasicBytehEENSt3__16vectorIT_NS3_9allocatorIS5_EEEEm | 
| 303 |  |  | 
| 304 |  |     /** Generate fixed-size random bytes. */ | 
| 305 |  |     template <size_t N, BasicByte B = std::byte> | 
| 306 |  |     std::array<B, N> randbytes() noexcept | 
| 307 | 0 |     { | 
| 308 | 0 |         std::array<B, N> ret; | 
| 309 | 0 |         Impl().fillrand(MakeWritableByteSpan(ret)); | 
| 310 | 0 |         return ret; | 
| 311 | 0 |     } | 
| 312 |  |  | 
| 313 |  |     /** Generate a random 32-bit integer. */ | 
| 314 | 0 |     uint32_t rand32() noexcept { return Impl().template randbits<32>(); }Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE6rand32EvUnexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE6rand32Ev | 
| 315 |  |  | 
| 316 |  |     /** generate a random uint256. */ | 
| 317 |  |     uint256 rand256() noexcept | 
| 318 | 51.2k |     { | 
| 319 | 51.2k |         uint256 ret; | 
| 320 | 51.2k |         Impl().fillrand(MakeWritableByteSpan(ret)); | 
| 321 | 51.2k |         return ret; | 
| 322 | 51.2k |     } _ZN11RandomMixinI17FastRandomContextE7rand256Ev| Line | Count | Source |  | 318 | 51.2k |     { |  | 319 | 51.2k |         uint256 ret; |  | 320 | 51.2k |         Impl().fillrand(MakeWritableByteSpan(ret)); |  | 321 | 51.2k |         return ret; |  | 322 | 51.2k |     } | 
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE7rand256Ev | 
| 323 |  |  | 
| 324 |  |     /** Generate a random boolean. */ | 
| 325 | 0 |     bool randbool() noexcept { return Impl().template randbits<1>(); }Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randboolEvUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randboolEv | 
| 326 |  |  | 
| 327 |  |     /** Return the time point advanced by a uniform random duration. */ | 
| 328 |  |     template <typename Tp> | 
| 329 |  |     Tp rand_uniform_delay(const Tp& time, typename Tp::duration range) noexcept | 
| 330 | 33.3k |     { | 
| 331 | 33.3k |         return time + Impl().template rand_uniform_duration<Tp>(range); | 
| 332 | 33.3k |     } _ZN11RandomMixinI17FastRandomContextE18rand_uniform_delayINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1000000EEEEEEEEET_RKSC_NSC_8durationE| Line | Count | Source |  | 330 | 33.3k |     { |  | 331 | 33.3k |         return time + Impl().template rand_uniform_duration<Tp>(range); |  | 332 | 33.3k |     } | 
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE18rand_uniform_delayINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1EEEEEEEEET_RKSC_NSC_8durationE | 
| 333 |  |  | 
| 334 |  |     /** Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive). */ | 
| 335 |  |     template <typename Chrono> requires StdChronoDuration<typename Chrono::duration> | 
| 336 |  |     typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept | 
| 337 | 33.3k |     { | 
| 338 | 33.3k |         using Dur = typename Chrono::duration; | 
| 339 | 33.3k |         return range.count() > 0 ? /* interval [0..range) */ Dur{Impl().randrange(range.count())} : | 
| 340 | 33.3k |                range.count() < 00? /* interval (range..0] */ -Dur{Impl().randrange(-range.count())}0: | 
| 341 | 0 |                                    /* interval [0..0] */ Dur{0}; | 
| 342 | 33.3k |     }; _ZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1000000EEEEEEEQ17StdChronoDurationINTL0__8durationEEEENT_8durationESF_| Line | Count | Source |  | 337 | 33.3k |     { |  | 338 | 33.3k |         using Dur = typename Chrono::duration; |  | 339 | 33.3k |         return range.count() > 0 ? /* interval [0..range) */ Dur{Impl().randrange(range.count())} : |  | 340 | 33.3k |                range.count() < 00? /* interval (range..0] */ -Dur{Impl().randrange(-range.count())}0: |  | 341 | 0 |                                    /* interval [0..0] */ Dur{0}; |  | 342 | 33.3k |     }; | 
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1EEEEEEEQ17StdChronoDurationINTL0__8durationEEEENT_8durationESF_Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono12steady_clockEQ17StdChronoDurationINTL0__8durationEEEENT_8durationES9_ | 
| 343 |  |  | 
| 344 |  |     /** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */ | 
| 345 |  |     template <StdChronoDuration Dur> | 
| 346 |  |     Dur randrange(std::common_type_t<Dur> range) noexcept | 
| 347 |  |     // Having the compiler infer the template argument from the function argument | 
| 348 |  |     // is dangerous, because the desired return value generally has a different | 
| 349 |  |     // type than the function argument. So std::common_type is used to force the | 
| 350 |  |     // call site to specify the type of the return value. | 
| 351 | 4.65k |     { | 
| 352 | 4.65k |         return Dur{Impl().randrange(range.count())}; | 
| 353 | 4.65k |     } Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000EEEEEEET_NS3_11common_typeIJS9_EE4typeE_ZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000000EEEEEEET_NS3_11common_typeIJS9_EE4typeE| Line | Count | Source |  | 351 | 4.65k |     { |  | 352 | 4.65k |         return Dur{Impl().randrange(range.count())}; |  | 353 | 4.65k |     } | 
 | 
| 354 |  |  | 
| 355 |  |     /** | 
| 356 |  |      * Return a duration sampled from an exponential distribution | 
| 357 |  |      * (https://en.wikipedia.org/wiki/Exponential_distribution). Successive events | 
| 358 |  |      * whose intervals are distributed according to this form a memoryless Poisson | 
| 359 |  |      * process. This should be used for repeated network events (e.g. sending a | 
| 360 |  |      * certain type of message) to minimize leaking information to observers. | 
| 361 |  |      * | 
| 362 |  |      * The probability of an event occurring before time x is 1 - e^-(x/a) where a | 
| 363 |  |      * is the average interval between events. | 
| 364 |  |      * */ | 
| 365 |  |     std::chrono::microseconds rand_exp_duration(std::chrono::microseconds mean) noexcept | 
| 366 | 119k |     { | 
| 367 | 119k |         using namespace std::chrono_literals; | 
| 368 | 119k |         auto unscaled = MakeExponentiallyDistributed(Impl().rand64()); | 
| 369 | 119k |         return std::chrono::duration_cast<std::chrono::microseconds>(unscaled * mean + 0.5us); | 
| 370 | 119k |     } | 
| 371 |  |  | 
| 372 |  |     // Compatibility with the UniformRandomBitGenerator concept | 
| 373 |  |     typedef uint64_t result_type; | 
| 374 | 0 |     static constexpr uint64_t min() noexcept { return 0; }Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE3minEvUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE3minEv | 
| 375 | 0 |     static constexpr uint64_t max() noexcept { return std::numeric_limits<uint64_t>::max(); }Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE3maxEvUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE3maxEv | 
| 376 | 0 |     inline uint64_t operator()() noexcept { return Impl().rand64(); }Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextEclEvUnexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextEclEv | 
| 377 |  | }; | 
| 378 |  |  | 
| 379 |  | /** | 
| 380 |  |  * Fast randomness source. This is seeded once with secure random data, but | 
| 381 |  |  * is completely deterministic and does not gather more entropy after that. | 
| 382 |  |  * | 
| 383 |  |  * This class is not thread-safe. | 
| 384 |  |  */ | 
| 385 |  | class FastRandomContext : public RandomMixin<FastRandomContext> | 
| 386 |  | { | 
| 387 |  | private: | 
| 388 |  |     bool requires_seed; | 
| 389 |  |     ChaCha20 rng; | 
| 390 |  |  | 
| 391 |  |     void RandomSeed() noexcept; | 
| 392 |  |  | 
| 393 |  | public: | 
| 394 |  |     /** Construct a FastRandomContext with GetRandHash()-based entropy (or zero key if fDeterministic). */ | 
| 395 |  |     explicit FastRandomContext(bool fDeterministic = false) noexcept; | 
| 396 |  |  | 
| 397 |  |     /** Initialize with explicit seed (only for testing) */ | 
| 398 |  |     explicit FastRandomContext(const uint256& seed) noexcept; | 
| 399 |  |  | 
| 400 |  |     /** Reseed with explicit seed (only for testing). */ | 
| 401 |  |     void Reseed(const uint256& seed) noexcept; | 
| 402 |  |  | 
| 403 |  |     /** Generate a random 64-bit integer. */ | 
| 404 |  |     uint64_t rand64() noexcept | 
| 405 | 12.5M |     { | 
| 406 | 12.5M |         if (requires_seed) RandomSeed()12.4M; | 
| 407 | 12.5M |         std::array<std::byte, 8> buf; | 
| 408 | 12.5M |         rng.Keystream(buf); | 
| 409 | 12.5M |         return ReadLE64(buf.data()); | 
| 410 | 12.5M |     } | 
| 411 |  |  | 
| 412 |  |     /** Fill a byte span with random bytes. This overrides the RandomMixin version. */ | 
| 413 |  |     void fillrand(std::span<std::byte> output) noexcept; | 
| 414 |  | }; | 
| 415 |  |  | 
| 416 |  | /** xoroshiro128++ PRNG. Extremely fast, not appropriate for cryptographic purposes. | 
| 417 |  |  * | 
| 418 |  |  * Memory footprint is very small, period is 2^128 - 1. | 
| 419 |  |  * This class is not thread-safe. | 
| 420 |  |  * | 
| 421 |  |  * Reference implementation available at https://prng.di.unimi.it/xoroshiro128plusplus.c | 
| 422 |  |  * See https://prng.di.unimi.it/ | 
| 423 |  |  */ | 
| 424 |  | class InsecureRandomContext : public RandomMixin<InsecureRandomContext> | 
| 425 |  | { | 
| 426 |  |     uint64_t m_s0; | 
| 427 |  |     uint64_t m_s1; | 
| 428 |  |  | 
| 429 |  |     [[nodiscard]] constexpr static uint64_t SplitMix64(uint64_t& seedval) noexcept | 
| 430 | 0 |     { | 
| 431 | 0 |         uint64_t z = (seedval += 0x9e3779b97f4a7c15); | 
| 432 | 0 |         z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; | 
| 433 | 0 |         z = (z ^ (z >> 27)) * 0x94d049bb133111eb; | 
| 434 | 0 |         return z ^ (z >> 31); | 
| 435 | 0 |     } | 
| 436 |  |  | 
| 437 |  | public: | 
| 438 |  |     constexpr explicit InsecureRandomContext(uint64_t seedval) noexcept | 
| 439 | 0 |         : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {} | 
| 440 |  |  | 
| 441 |  |     constexpr void Reseed(uint64_t seedval) noexcept | 
| 442 | 0 |     { | 
| 443 | 0 |         FlushCache(); | 
| 444 | 0 |         m_s0 = SplitMix64(seedval); | 
| 445 | 0 |         m_s1 = SplitMix64(seedval); | 
| 446 | 0 |     } | 
| 447 |  |  | 
| 448 |  |     constexpr uint64_t rand64() noexcept | 
| 449 | 0 |     { | 
| 450 | 0 |         uint64_t s0 = m_s0, s1 = m_s1; | 
| 451 | 0 |         const uint64_t result = std::rotl(s0 + s1, 17) + s0; | 
| 452 | 0 |         s1 ^= s0; | 
| 453 | 0 |         m_s0 = std::rotl(s0, 49) ^ s1 ^ (s1 << 21); | 
| 454 | 0 |         m_s1 = std::rotl(s1, 28); | 
| 455 | 0 |         return result; | 
| 456 | 0 |     } | 
| 457 |  | }; | 
| 458 |  |  | 
| 459 |  |  | 
| 460 |  | /* ==================== CONVENIENCE FUNCTIONS FOR COMMONLY USED RANDOMNESS ==================== */ | 
| 461 |  |  | 
| 462 |  | /** Generate a random uint256. */ | 
| 463 |  | inline uint256 GetRandHash() noexcept | 
| 464 | 12.6M | { | 
| 465 | 12.6M |     uint256 hash; | 
| 466 | 12.6M |     GetRandBytes(hash); | 
| 467 | 12.6M |     return hash; | 
| 468 | 12.6M | } | 
| 469 |  |  | 
| 470 |  | /* ============================= MISCELLANEOUS TEST-ONLY FUNCTIONS ============================= */ | 
| 471 |  |  | 
| 472 |  | /** Check that OS randomness is available and returning the requested number | 
| 473 |  |  * of bytes. | 
| 474 |  |  */ | 
| 475 |  | bool Random_SanityCheck(); | 
| 476 |  |  | 
| 477 |  | #endif // BITCOIN_RANDOM_H |