fuzz coverage

Coverage Report

Created: 2025-09-17 22:41

/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
7.24M
    RandomNumberGenerator auto& Impl() noexcept { return static_cast<T&>(*this); }
_ZN11RandomMixinI17FastRandomContextE4ImplEv
Line
Count
Source
185
7.24M
    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: _ZN11RandomMixinI21InsecureRandomContextE10FlushCacheEv
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE10FlushCacheEv
193
194
public:
195
14.9M
    constexpr RandomMixin() noexcept = default;
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextEC2Ev
_ZN11RandomMixinI17FastRandomContextEC2Ev
Line
Count
Source
195
14.9M
    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
5.36M
    {
206
5.36M
        Assume(bits <= 64);
Line
Count
Source
118
5.36M
#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
5.36M
        if (bits == 64) 
return Impl().rand64()0
;
209
5.36M
        uint64_t ret;
210
5.36M
        if (bits <= bitbuf_size) {
211
            // If there is enough entropy left in bitbuf, return its bottom bits bits.
212
5.24M
            ret = bitbuf;
213
5.24M
            bitbuf >>= bits;
214
5.24M
            bitbuf_size -= bits;
215
5.24M
        } 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
123k
            uint64_t gen = Impl().rand64();
220
123k
            ret = (gen << bitbuf_size) | bitbuf;
221
123k
            bitbuf = gen >> (bits - bitbuf_size);
222
123k
            bitbuf_size = 64 + bitbuf_size - bits;
223
123k
        }
224
        // Return the bottom bits bits of ret.
225
5.36M
        return ret & ((uint64_t{1} << bits) - 1);
226
5.36M
    }
_ZN11RandomMixinI17FastRandomContextE8randbitsEi
Line
Count
Source
205
5.36M
    {
206
5.36M
        Assume(bits <= 64);
Line
Count
Source
118
5.36M
#define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
207
        // Requests for the full 64 bits are passed through.
208
5.36M
        if (bits == 64) 
return Impl().rand64()0
;
209
5.36M
        uint64_t ret;
210
5.36M
        if (bits <= bitbuf_size) {
211
            // If there is enough entropy left in bitbuf, return its bottom bits bits.
212
5.24M
            ret = bitbuf;
213
5.24M
            bitbuf >>= bits;
214
5.24M
            bitbuf_size -= bits;
215
5.24M
        } 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
123k
            uint64_t gen = Impl().rand64();
220
123k
            ret = (gen << bitbuf_size) | bitbuf;
221
123k
            bitbuf = gen >> (bits - bitbuf_size);
222
123k
            bitbuf_size = 64 + bitbuf_size - bits;
223
123k
        }
224
        // Return the bottom bits bits of ret.
225
5.36M
        return ret & ((uint64_t{1} << bits) - 1);
226
5.36M
    }
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
637k
    {
232
637k
        static_assert(Bits >= 0 && Bits <= 64);
233
        if constexpr (Bits == 64) {
234
            return Impl().rand64();
235
637k
        } else {
236
637k
            uint64_t ret;
237
637k
            if (Bits <= bitbuf_size) {
238
0
                ret = bitbuf;
239
0
                bitbuf >>= Bits;
240
0
                bitbuf_size -= Bits;
241
637k
            } else {
242
637k
                uint64_t gen = Impl().rand64();
243
637k
                ret = (gen << bitbuf_size) | bitbuf;
244
637k
                bitbuf = gen >> (Bits - bitbuf_size);
245
637k
                bitbuf_size = 64 + bitbuf_size - Bits;
246
637k
            }
247
637k
            constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1;
248
637k
            return ret & MASK;
249
637k
        }
250
637k
    }
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsILi32EEEyv
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsILi8EEEyv
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randbitsILi1EEEyv
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE8randbitsILi1EEEyv
_ZN11RandomMixinI17FastRandomContextE8randbitsILi32EEEyv
Line
Count
Source
231
637k
    {
232
637k
        static_assert(Bits >= 0 && Bits <= 64);
233
        if constexpr (Bits == 64) {
234
            return Impl().rand64();
235
637k
        } else {
236
637k
            uint64_t ret;
237
637k
            if (Bits <= bitbuf_size) {
238
0
                ret = bitbuf;
239
0
                bitbuf >>= Bits;
240
0
                bitbuf_size -= Bits;
241
637k
            } else {
242
637k
                uint64_t gen = Impl().rand64();
243
637k
                ret = (gen << bitbuf_size) | bitbuf;
244
637k
                bitbuf = gen >> (Bits - bitbuf_size);
245
637k
                bitbuf_size = 64 + bitbuf_size - Bits;
246
637k
            }
247
637k
            constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1;
248
637k
            return ret & MASK;
249
637k
        }
250
637k
    }
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randbitsILi16EEEyv
Unexecuted 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
5.26M
    {
256
5.26M
        static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
257
5.26M
        Assume(range > 0);
Line
Count
Source
118
5.16M
#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
104k
#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
5.26M
        uint64_t maxval = range - 1U;
259
5.26M
        int bits = std::bit_width(maxval);
260
5.36M
        while (true) {
261
5.36M
            uint64_t ret = Impl().randbits(bits);
262
5.36M
            if (ret <= maxval) 
return ret5.26M
;
263
5.36M
        }
264
5.26M
    }
_ZN11RandomMixinI17FastRandomContextE9randrangeITkNSt3__18integralEiEET_S4_
Line
Count
Source
255
5.16M
    {
256
5.16M
        static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
257
5.16M
        Assume(range > 0);
Line
Count
Source
118
5.16M
#define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
258
5.16M
        uint64_t maxval = range - 1U;
259
5.16M
        int bits = std::bit_width(maxval);
260
5.16M
        while (true) {
261
5.16M
            uint64_t ret = Impl().randbits(bits);
262
5.16M
            if (ret <= maxval) return ret;
263
5.16M
        }
264
5.16M
    }
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
104k
    {
256
104k
        static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
257
104k
        Assume(range > 0);
Line
Count
Source
118
104k
#define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
258
104k
        uint64_t maxval = range - 1U;
259
104k
        int bits = std::bit_width(maxval);
260
205k
        while (true) {
261
205k
            uint64_t ret = Impl().randbits(bits);
262
205k
            if (ret <= maxval) 
return ret104k
;
263
205k
        }
264
104k
    }
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
637k
    {
289
637k
        static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
290
637k
        static constexpr auto BITS = std::bit_width(uint64_t(std::numeric_limits<I>::max()));
291
637k
        static_assert(std::numeric_limits<I>::max() == std::numeric_limits<uint64_t>::max() >> (64 - BITS));
292
637k
        return I(Impl().template randbits<BITS>());
293
637k
    }
_ZN11RandomMixinI17FastRandomContextE4randITkNSt3__18integralEjEET_v
Line
Count
Source
288
637k
    {
289
637k
        static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
290
637k
        static constexpr auto BITS = std::bit_width(uint64_t(std::numeric_limits<I>::max()));
291
637k
        static_assert(std::numeric_limits<I>::max() == std::numeric_limits<uint64_t>::max() >> (64 - BITS));
292
637k
        return I(Impl().template randbits<BITS>());
293
637k
    }
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
38.8k
    {
299
38.8k
        std::vector<B> ret(len);
300
38.8k
        Impl().fillrand(MakeWritableByteSpan(ret));
301
38.8k
        return ret;
302
38.8k
    }
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randbytesITk9BasicByteSt4byteEENSt3__16vectorIT_NS4_9allocatorIS6_EEEEm
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE9randbytesITk9BasicBytehEENSt3__16vectorIT_NS3_9allocatorIS5_EEEEm
_ZN11RandomMixinI17FastRandomContextE9randbytesITk9BasicBytehEENSt3__16vectorIT_NS3_9allocatorIS5_EEEEm
Line
Count
Source
298
38.8k
    {
299
38.8k
        std::vector<B> ret(len);
300
38.8k
        Impl().fillrand(MakeWritableByteSpan(ret));
301
38.8k
        return ret;
302
38.8k
    }
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: _ZN11RandomMixinI21InsecureRandomContextE6rand32Ev
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE6rand32Ev
315
316
    /** generate a random uint256. */
317
    uint256 rand256() noexcept
318
38.8k
    {
319
38.8k
        uint256 ret;
320
38.8k
        Impl().fillrand(MakeWritableByteSpan(ret));
321
38.8k
        return ret;
322
38.8k
    }
_ZN11RandomMixinI17FastRandomContextE7rand256Ev
Line
Count
Source
318
38.8k
    {
319
38.8k
        uint256 ret;
320
38.8k
        Impl().fillrand(MakeWritableByteSpan(ret));
321
38.8k
        return ret;
322
38.8k
    }
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE7rand256Ev
323
324
    /** Generate a random boolean. */
325
0
    bool randbool() noexcept { return Impl().template randbits<1>(); }
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE8randboolEv
Unexecuted 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
39.1k
    {
331
39.1k
        return time + Impl().template rand_uniform_duration<Tp>(range);
332
39.1k
    }
_ZN11RandomMixinI17FastRandomContextE18rand_uniform_delayINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1000000EEEEEEEEET_RKSC_NSC_8durationE
Line
Count
Source
330
39.1k
    {
331
39.1k
        return time + Impl().template rand_uniform_duration<Tp>(range);
332
39.1k
    }
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
39.1k
    {
338
39.1k
        using Dur = typename Chrono::duration;
339
39.1k
        return range.count() > 0 ? /* interval [0..range) */ Dur{Impl().randrange(range.count())} :
340
39.1k
               
range.count() < 00
? /* interval (range..0] */
-Dur{Impl().randrange(-range.count())}0
:
341
0
                                   /* interval [0..0] */ Dur{0};
342
39.1k
    };
_ZN11RandomMixinI17FastRandomContextE21rand_uniform_durationINSt3__16chrono10time_pointI9NodeClockNS4_8durationIxNS3_5ratioILl1ELl1000000EEEEEEEQ17StdChronoDurationINTL0__8durationEEEENT_8durationESF_
Line
Count
Source
337
39.1k
    {
338
39.1k
        using Dur = typename Chrono::duration;
339
39.1k
        return range.count() > 0 ? /* interval [0..range) */ Dur{Impl().randrange(range.count())} :
340
39.1k
               
range.count() < 00
? /* interval (range..0] */
-Dur{Impl().randrange(-range.count())}0
:
341
0
                                   /* interval [0..0] */ Dur{0};
342
39.1k
    };
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
65.2k
    {
352
65.2k
        return Dur{Impl().randrange(range.count())};
353
65.2k
    }
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000EEEEEEET_NS3_11common_typeIJS9_EE4typeE
_ZN11RandomMixinI17FastRandomContextE9randrangeITk17StdChronoDurationNSt3__16chrono8durationIxNS3_5ratioILl1ELl1000000EEEEEEET_NS3_11common_typeIJS9_EE4typeE
Line
Count
Source
351
65.2k
    {
352
65.2k
        return Dur{Impl().randrange(range.count())};
353
65.2k
    }
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
255k
    {
367
255k
        using namespace std::chrono_literals;
368
255k
        auto unscaled = MakeExponentiallyDistributed(Impl().rand64());
369
255k
        return std::chrono::duration_cast<std::chrono::microseconds>(unscaled * mean + 0.5us);
370
255k
    }
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: _ZN11RandomMixinI17FastRandomContextE3minEv
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE3minEv
375
0
    static constexpr uint64_t max() noexcept { return std::numeric_limits<uint64_t>::max(); }
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextE3maxEv
Unexecuted instantiation: _ZN11RandomMixinI21InsecureRandomContextE3maxEv
376
0
    inline uint64_t operator()() noexcept { return Impl().rand64(); }
Unexecuted instantiation: _ZN11RandomMixinI17FastRandomContextEclEv
Unexecuted 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
9.99M
    {
406
9.99M
        if (requires_seed) 
RandomSeed()9.65M
;
407
9.99M
        std::array<std::byte, 8> buf;
408
9.99M
        rng.Keystream(buf);
409
9.99M
        return ReadLE64(buf.data());
410
9.99M
    }
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
9.77M
{
465
9.77M
    uint256 hash;
466
9.77M
    GetRandBytes(hash);
467
9.77M
    return hash;
468
9.77M
}
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