Bitcoin Core 28.99.0
P2P Digital Currency
random.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2022 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
75/* ============================= INITIALIZATION AND ADDING ENTROPY ============================= */
76
83void RandomInit();
84
90void RandAddPeriodic() noexcept;
91
98void 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
117void GetRandBytes(Span<unsigned char> bytes) noexcept;
118
129void GetStrongRandBytes(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.
142template<typename T>
143class RandomMixin;
144
146template<typename T>
147concept RandomNumberGenerator = requires(T& rng, 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
155template<typename T>
156concept StdChronoDuration = requires {
157 []<class Rep, class Period>(std::type_identity<std::chrono::duration<Rep, Period>>){}(
158 std::type_identity<T>());
159};
160
162double MakeExponentiallyDistributed(uint64_t uniform) noexcept;
163
173template<typename T>
175{
176private:
177 uint64_t bitbuf{0};
179
185 RandomNumberGenerator auto& Impl() noexcept { return static_cast<T&>(*this); }
186
187protected:
188 constexpr void FlushCache() noexcept
189 {
190 bitbuf = 0;
191 bitbuf_size = 0;
192 }
193
194public:
195 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;
201 RandomMixin& operator=(RandomMixin&&) = delete;
202
204 uint64_t randbits(int bits) noexcept
205 {
206 Assume(bits <= 64);
207 // Requests for the full 64 bits are passed through.
208 if (bits == 64) return Impl().rand64();
209 uint64_t ret;
210 if (bits <= bitbuf_size) {
211 // If there is enough entropy left in bitbuf, return its bottom bits bits.
212 ret = bitbuf;
213 bitbuf >>= bits;
214 bitbuf_size -= bits;
215 } 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 uint64_t gen = Impl().rand64();
220 ret = (gen << bitbuf_size) | bitbuf;
221 bitbuf = gen >> (bits - bitbuf_size);
222 bitbuf_size = 64 + bitbuf_size - bits;
223 }
224 // Return the bottom bits bits of ret.
225 return ret & ((uint64_t{1} << bits) - 1);
226 }
227
229 template<int Bits>
230 uint64_t randbits() noexcept
231 {
232 static_assert(Bits >= 0 && Bits <= 64);
233 if constexpr (Bits == 64) {
234 return Impl().rand64();
235 } else {
236 uint64_t ret;
237 if (Bits <= bitbuf_size) {
238 ret = bitbuf;
239 bitbuf >>= Bits;
240 bitbuf_size -= Bits;
241 } else {
242 uint64_t gen = Impl().rand64();
243 ret = (gen << bitbuf_size) | bitbuf;
244 bitbuf = gen >> (Bits - bitbuf_size);
245 bitbuf_size = 64 + bitbuf_size - Bits;
246 }
247 constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1;
248 return ret & MASK;
249 }
250 }
251
253 template<std::integral I>
254 I randrange(I range) noexcept
255 {
256 static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
257 Assume(range > 0);
258 uint64_t maxval = range - 1U;
259 int bits = std::bit_width(maxval);
260 while (true) {
261 uint64_t ret = Impl().randbits(bits);
262 if (ret <= maxval) return ret;
263 }
264 }
265
267 void fillrand(Span<std::byte> span) noexcept
268 {
269 while (span.size() >= 8) {
270 uint64_t gen = Impl().rand64();
271 WriteLE64(UCharCast(span.data()), gen);
272 span = span.subspan(8);
273 }
274 if (span.size() >= 4) {
275 uint32_t gen = Impl().rand32();
276 WriteLE32(UCharCast(span.data()), gen);
277 span = span.subspan(4);
278 }
279 while (span.size()) {
280 span[0] = std::byte(Impl().template randbits<8>());
281 span = span.subspan(1);
282 }
283 }
284
286 template<std::integral I>
287 I rand() noexcept
288 {
289 static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max());
290 static constexpr auto BITS = std::bit_width(uint64_t(std::numeric_limits<I>::max()));
291 static_assert(std::numeric_limits<I>::max() == std::numeric_limits<uint64_t>::max() >> (64 - BITS));
292 return I(Impl().template randbits<BITS>());
293 }
294
296 template <BasicByte B = unsigned char>
297 std::vector<B> randbytes(size_t len) noexcept
298 {
299 std::vector<B> ret(len);
300 Impl().fillrand(MakeWritableByteSpan(ret));
301 return ret;
302 }
303
305 uint32_t rand32() noexcept { return Impl().template randbits<32>(); }
306
308 uint256 rand256() noexcept
309 {
310 uint256 ret;
311 Impl().fillrand(MakeWritableByteSpan(ret));
312 return ret;
313 }
314
316 bool randbool() noexcept { return Impl().template randbits<1>(); }
317
319 template <typename Tp>
320 Tp rand_uniform_delay(const Tp& time, typename Tp::duration range) noexcept
321 {
322 return time + Impl().template rand_uniform_duration<Tp>(range);
323 }
324
326 template <typename Chrono> requires StdChronoDuration<typename Chrono::duration>
327 typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
328 {
329 using Dur = typename Chrono::duration;
330 return range.count() > 0 ? /* interval [0..range) */ Dur{Impl().randrange(range.count())} :
331 range.count() < 0 ? /* interval (range..0] */ -Dur{Impl().randrange(-range.count())} :
332 /* interval [0..0] */ Dur{0};
333 };
334
336 template <StdChronoDuration Dur>
337 Dur randrange(typename std::common_type_t<Dur> range) noexcept
338 // Having the compiler infer the template argument from the function argument
339 // is dangerous, because the desired return value generally has a different
340 // type than the function argument. So std::common_type is used to force the
341 // call site to specify the type of the return value.
342 {
343 return Dur{Impl().randrange(range.count())};
344 }
345
356 std::chrono::microseconds rand_exp_duration(std::chrono::microseconds mean) noexcept
357 {
358 using namespace std::chrono_literals;
359 auto unscaled = MakeExponentiallyDistributed(Impl().rand64());
360 return std::chrono::duration_cast<std::chrono::microseconds>(unscaled * mean + 0.5us);
361 }
362
363 // Compatibility with the UniformRandomBitGenerator concept
364 typedef uint64_t result_type;
365 static constexpr uint64_t min() noexcept { return 0; }
366 static constexpr uint64_t max() noexcept { return std::numeric_limits<uint64_t>::max(); }
367 inline uint64_t operator()() noexcept { return Impl().rand64(); }
368};
369
376class FastRandomContext : public RandomMixin<FastRandomContext>
377{
378private:
381
382 void RandomSeed() noexcept;
383
384public:
386 explicit FastRandomContext(bool fDeterministic = false) noexcept;
387
389 explicit FastRandomContext(const uint256& seed) noexcept;
390
392 void Reseed(const uint256& seed) noexcept;
393
395 uint64_t rand64() noexcept
396 {
398 std::array<std::byte, 8> buf;
399 rng.Keystream(buf);
400 return ReadLE64(UCharCast(buf.data()));
401 }
402
404 void fillrand(Span<std::byte> output) noexcept;
405};
406
415class InsecureRandomContext : public RandomMixin<InsecureRandomContext>
416{
417 uint64_t m_s0;
418 uint64_t m_s1;
419
420 [[nodiscard]] constexpr static uint64_t SplitMix64(uint64_t& seedval) noexcept
421 {
422 uint64_t z = (seedval += 0x9e3779b97f4a7c15);
423 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
424 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
425 return z ^ (z >> 31);
426 }
427
428public:
429 constexpr explicit InsecureRandomContext(uint64_t seedval) noexcept
430 : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {}
431
432 constexpr void Reseed(uint64_t seedval) noexcept
433 {
434 FlushCache();
435 m_s0 = SplitMix64(seedval);
436 m_s1 = SplitMix64(seedval);
437 }
438
439 constexpr uint64_t rand64() noexcept
440 {
441 uint64_t s0 = m_s0, s1 = m_s1;
442 const uint64_t result = std::rotl(s0 + s1, 17) + s0;
443 s1 ^= s0;
444 m_s0 = std::rotl(s0, 49) ^ s1 ^ (s1 << 21);
445 m_s1 = std::rotl(s1, 28);
446 return result;
447 }
448};
449
450
451/* ==================== CONVENIENCE FUNCTIONS FOR COMMONLY USED RANDOMNESS ==================== */
452
454inline uint256 GetRandHash() noexcept
455{
456 uint256 hash;
457 GetRandBytes(hash);
458 return hash;
459}
460
461/* ============================= MISCELLANEOUS TEST-ONLY FUNCTIONS ============================= */
462
466bool Random_SanityCheck();
467
468#endif // BITCOIN_RANDOM_H
int ret
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
Unrestricted ChaCha20 cipher.
Definition: chacha20.h:78
void Keystream(Span< std::byte > out) noexcept
outputs the keystream to out.
Definition: chacha20.cpp:282
Fast randomness source.
Definition: random.h:377
uint64_t rand64() noexcept
Generate a random 64-bit integer.
Definition: random.h:395
ChaCha20 rng
Definition: random.h:380
void RandomSeed() noexcept
Definition: random.cpp:694
void Reseed(const uint256 &seed) noexcept
Reseed with explicit seed (only for testing).
Definition: random.cpp:709
bool requires_seed
Definition: random.h:379
void fillrand(Span< std::byte > output) noexcept
Fill a byte Span with random bytes.
Definition: random.cpp:701
xoroshiro128++ PRNG.
Definition: random.h:416
static constexpr uint64_t SplitMix64(uint64_t &seedval) noexcept
Definition: random.h:420
constexpr uint64_t rand64() noexcept
Definition: random.h:439
constexpr void Reseed(uint64_t seedval) noexcept
Definition: random.h:432
constexpr InsecureRandomContext(uint64_t seedval) noexcept
Definition: random.h:429
Mixin class that provides helper randomness functions.
Definition: random.h:175
static constexpr uint64_t max() noexcept
Definition: random.h:366
constexpr RandomMixin() noexcept=default
RandomNumberGenerator auto & Impl() noexcept
Access the underlying generator.
Definition: random.h:185
Dur randrange(typename std::common_type_t< Dur > range) noexcept
Generate a uniform random duration in the range [0..max).
Definition: random.h:337
void fillrand(Span< std::byte > span) noexcept
Fill a Span with random bytes.
Definition: random.h:267
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) noexcept
Return the time point advanced by a uniform random duration.
Definition: random.h:320
Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive).
Definition: random.h:327
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
Definition: random.h:254
int bitbuf_size
Definition: random.h:178
uint256 rand256() noexcept
generate a random uint256.
Definition: random.h:308
uint64_t result_type
Definition: random.h:364
uint64_t bitbuf
Definition: random.h:177
bool randbool() noexcept
Generate a random boolean.
Definition: random.h:316
I rand() noexcept
Generate a random integer in its entire (non-negative) range.
Definition: random.h:287
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition: random.h:297
constexpr void FlushCache() noexcept
Definition: random.h:188
std::chrono::microseconds rand_exp_duration(std::chrono::microseconds mean) noexcept
Return a duration sampled from an exponential distribution (https://en.wikipedia.org/wiki/Exponential...
Definition: random.h:356
static constexpr uint64_t min() noexcept
Definition: random.h:365
uint32_t rand32() noexcept
Generate a random 32-bit integer.
Definition: random.h:305
uint64_t randbits() noexcept
Same as above, but with compile-time fixed bits count.
Definition: random.h:230
uint64_t operator()() noexcept
Definition: random.h:367
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
256-bit opaque blob.
Definition: uint256.h:190
A concept for RandomMixin-based random number generators.
Definition: random.h:147
A concept for C++ std::chrono durations.
Definition: random.h:156
static uint64_t ReadLE64(const unsigned char *ptr)
Definition: common.h:27
static void WriteLE32(unsigned char *ptr, uint32_t x)
Definition: common.h:40
static void WriteLE64(unsigned char *ptr, uint64_t x)
Definition: common.h:46
void GetRandBytes(Span< unsigned char > bytes) noexcept
Generate random data via the internal PRNG.
Definition: random.cpp:676
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
Definition: random.cpp:687
void GetStrongRandBytes(Span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition: random.cpp:682
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
Definition: random.cpp:716
uint256 GetRandHash() noexcept
Generate a random uint256.
Definition: random.h:454
void RandomInit()
Overall design of the RNG and entropy sources.
Definition: random.cpp:771
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
Definition: random.cpp:692
double MakeExponentiallyDistributed(uint64_t uniform) noexcept
Given a uniformly random uint64_t, return an exponentially distributed double with mean 1.
Definition: random.cpp:779
unsigned char * UCharCast(char *c)
Definition: span.h:281
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:275
static SECP256K1_INLINE uint64_t rotl(const uint64_t x, int k)
Definition: testrand_impl.h:39