Bitcoin ABC 0.32.5
P2P Digital Currency
random.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 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
86void RandomInit();
87
94void RandAddPeriodic() noexcept;
95
102void RandAddEvent(const uint32_t event_info) noexcept;
103
121void GetRandBytes(Span<uint8_t> bytes) noexcept;
122
133void GetStrongRandBytes(Span<uint8_t> bytes) noexcept;
134
146// Forward declaration of RandomMixin, used in RandomNumberGenerator concept.
147template <typename T> class RandomMixin;
148
150template <typename T>
151concept RandomNumberGenerator = requires(T &rng, Span<std::byte> s) {
152 // A random number generator must provide rand64().
153 { rng.rand64() } noexcept -> std::same_as<uint64_t>;
154 // A random number generator must derive from RandomMixin, which adds other
155 // rand* functions.
156 requires std::derived_from<std::remove_reference_t<T>,
158};
159
161template <typename T>
162concept StdChronoDuration = requires {
163 []<class Rep, class Period>(
164 std::type_identity<std::chrono::duration<Rep, Period>>) {
165 }(std::type_identity<T>());
166};
167
172double MakeExponentiallyDistributed(uint64_t uniform) noexcept;
173
184template <typename T> class RandomMixin {
185private:
186 uint64_t bitbuf{0};
188
196 RandomNumberGenerator auto &Impl() noexcept {
197 return static_cast<T &>(*this);
198 }
199
200protected:
201 constexpr void FlushCache() noexcept {
202 bitbuf = 0;
203 bitbuf_size = 0;
204 }
205
206public:
207 constexpr RandomMixin() noexcept = default;
208
209 // Do not permit copying or moving an RNG.
210 RandomMixin(const RandomMixin &) = delete;
211 RandomMixin &operator=(const RandomMixin &) = delete;
213 RandomMixin &operator=(RandomMixin &&) = delete;
214
216 uint64_t randbits(int bits) noexcept {
217 Assume(bits <= 64);
218 // Requests for the full 64 bits are passed through.
219 if (bits == 64) {
220 return Impl().rand64();
221 }
222 uint64_t ret;
223 if (bits <= bitbuf_size) {
224 // If there is enough entropy left in bitbuf, return its bottom bits
225 // bits.
226 ret = bitbuf;
227 bitbuf >>= bits;
228 bitbuf_size -= bits;
229 } else {
230 // If not, return all of bitbuf, supplemented with the (bits -
231 // bitbuf_size) bottom bits of a newly generated 64-bit number on
232 // top. The remainder of that generated number becomes the new
233 // bitbuf.
234 uint64_t gen = Impl().rand64();
235 ret = (gen << bitbuf_size) | bitbuf;
236 bitbuf = gen >> (bits - bitbuf_size);
237 bitbuf_size = 64 + bitbuf_size - bits;
238 }
239 // Return the bottom bits bits of ret.
240 return ret & ((uint64_t{1} << bits) - 1);
241 }
242
244 template <int Bits> uint64_t randbits() noexcept {
245 static_assert(Bits >= 0 && Bits <= 64);
246 if constexpr (Bits == 64) {
247 return Impl().rand64();
248 } else {
249 uint64_t ret;
250 if (Bits <= bitbuf_size) {
251 ret = bitbuf;
252 bitbuf >>= Bits;
253 bitbuf_size -= Bits;
254 } else {
255 uint64_t gen = Impl().rand64();
256 ret = (gen << bitbuf_size) | bitbuf;
257 bitbuf = gen >> (Bits - bitbuf_size);
258 bitbuf_size = 64 + bitbuf_size - Bits;
259 }
260 constexpr uint64_t MASK = (uint64_t{1} << Bits) - 1;
261 return ret & MASK;
262 }
263 }
264
266 template <std::integral I> I randrange(I range) noexcept {
267 static_assert(std::numeric_limits<I>::max() <=
268 std::numeric_limits<uint64_t>::max());
269 Assume(range > 0);
270 uint64_t maxval = range - 1U;
271 int bits = std::bit_width(maxval);
272 while (true) {
273 uint64_t ret = Impl().randbits(bits);
274 if (ret <= maxval) {
275 return ret;
276 }
277 }
278 }
279
281 void fillrand(Span<std::byte> span) noexcept {
282 while (span.size() >= 8) {
283 uint64_t gen = Impl().rand64();
284 WriteLE64(UCharCast(span.data()), gen);
285 span = span.subspan(8);
286 }
287 if (span.size() >= 4) {
288 uint32_t gen = Impl().rand32();
289 WriteLE32(UCharCast(span.data()), gen);
290 span = span.subspan(4);
291 }
292 while (span.size()) {
293 span[0] = std::byte(Impl().template randbits<8>());
294 span = span.subspan(1);
295 }
296 }
297
299 template <std::integral I> I rand() noexcept {
300 static_assert(std::numeric_limits<I>::max() <=
301 std::numeric_limits<uint64_t>::max());
302 static constexpr auto BITS =
303 std::bit_width(uint64_t(std::numeric_limits<I>::max()));
304 static_assert(std::numeric_limits<I>::max() ==
305 std::numeric_limits<uint64_t>::max() >> (64 - BITS));
306 return I(Impl().template randbits<BITS>());
307 }
308
310 template <BasicByte B = uint8_t>
311 std::vector<B> randbytes(size_t len) noexcept {
312 std::vector<B> ret(len);
313 Impl().fillrand(MakeWritableByteSpan(ret));
314 return ret;
315 }
316
318 uint32_t rand32() noexcept { return Impl().template randbits<32>(); }
319
321 uint160 rand160() noexcept {
322 uint160 ret;
323 Impl().fillrand(MakeWritableByteSpan(ret));
324 return ret;
325 }
326
328 uint256 rand256() noexcept {
329 uint256 ret;
330 Impl().fillrand(MakeWritableByteSpan(ret));
331 return ret;
332 }
333
335 bool randbool() noexcept { return Impl().template randbits<1>(); }
336
338 template <typename Tp>
339 Tp rand_uniform_delay(const Tp &time,
340 typename Tp::duration range) noexcept {
341 return time + rand_uniform_duration<Tp>(range);
342 }
343
348 template <typename Chrono>
350 typename Chrono::duration
351 rand_uniform_duration(typename Chrono::duration range) noexcept {
352 using Dur = typename Chrono::duration;
353 return range.count() > 0
354 ? /* interval [0..range) */ Dur{Impl().randrange(
355 range.count())}
356 : range.count() < 0
357 ? /* interval (range..0] */ -Dur{Impl().randrange(
358 -range.count())}
359 :
360 /* interval [0..0] */ Dur{0};
361 };
362
367 template <StdChronoDuration Dur>
368 Dur randrange(typename std::common_type_t<Dur> range) noexcept
369 // Having the compiler infer the template argument from the function
370 // argument is dangerous, because the desired return value generally has a
371 // different type than the function argument. So std::common_type is used to
372 // force the call site to specify the type of the return value.
373 {
374 return Dur{Impl().randrange(range.count())};
375 }
376
388 std::chrono::microseconds
389 rand_exp_duration(std::chrono::microseconds mean) noexcept {
390 using namespace std::chrono_literals;
391 auto unscaled = MakeExponentiallyDistributed(Impl().rand64());
392 return std::chrono::duration_cast<std::chrono::microseconds>(
393 unscaled * mean + 0.5us);
394 }
395
396 // Compatibility with the UniformRandomBitGenerator concept
397 typedef uint64_t result_type;
398 static constexpr uint64_t min() noexcept { return 0; }
399 static constexpr uint64_t max() noexcept {
400 return std::numeric_limits<uint64_t>::max();
401 }
402 inline uint64_t operator()() noexcept { return Impl().rand64(); }
403};
404
411class FastRandomContext : public RandomMixin<FastRandomContext> {
412private:
415
416 void RandomSeed() noexcept;
417
418public:
423 explicit FastRandomContext(bool fDeterministic = false) noexcept;
424
426 explicit FastRandomContext(const uint256 &seed) noexcept;
427
429 void Reseed(const uint256 &seed) noexcept;
430
432 uint64_t rand64() noexcept {
433 if (requires_seed) {
434 RandomSeed();
435 }
436 std::array<std::byte, 8> buf;
437 rng.Keystream(buf);
438 return ReadLE64(UCharCast(buf.data()));
439 }
440
445 void fillrand(Span<std::byte> output) noexcept;
446};
447
459class InsecureRandomContext : public RandomMixin<InsecureRandomContext> {
460 uint64_t m_s0;
461 uint64_t m_s1;
462
463 [[nodiscard]] constexpr static uint64_t
464 SplitMix64(uint64_t &seedval) noexcept {
465 uint64_t z = (seedval += 0x9e3779b97f4a7c15);
466 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
467 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
468 return z ^ (z >> 31);
469 }
470
471public:
472 constexpr explicit InsecureRandomContext(uint64_t seedval) noexcept
473 : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {}
474
475 constexpr void Reseed(uint64_t seedval) noexcept {
476 FlushCache();
477 m_s0 = SplitMix64(seedval);
478 m_s1 = SplitMix64(seedval);
479 }
480
481 constexpr uint64_t rand64() noexcept {
482 uint64_t s0 = m_s0, s1 = m_s1;
483 const uint64_t result = std::rotl(s0 + s1, 17) + s0;
484 s1 ^= s0;
485 m_s0 = std::rotl(s0, 49) ^ s1 ^ (s1 << 21);
486 m_s1 = std::rotl(s1, 28);
487 return result;
488 }
489};
490
494inline uint256 GetRandHash() noexcept {
495 uint256 hash;
496 GetRandBytes(hash);
497 return hash;
498}
499
511template <typename I, RandomNumberGenerator R>
512void Shuffle(I first, I last, R &&rng) {
513 while (first != last) {
514 size_t j = rng.randrange(last - first);
515 if (j) {
516 using std::swap;
517 swap(*first, *(first + j));
518 }
519 ++first;
520 }
521}
522
529bool Random_SanityCheck();
530
531#endif // BITCOIN_RANDOM_H
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
Unrestricted ChaCha20 cipher.
Definition: chacha20.h:89
void Keystream(Span< std::byte > out) noexcept
outputs the keystream to out.
Definition: chacha20.cpp:298
Fast randomness source.
Definition: random.h:411
uint64_t rand64() noexcept
Generate a random 64-bit integer.
Definition: random.h:432
ChaCha20 rng
Definition: random.h:414
void RandomSeed() noexcept
Definition: random.cpp:708
void Reseed(const uint256 &seed) noexcept
Reseed with explicit seed (only for testing).
Definition: random.cpp:724
bool requires_seed
Definition: random.h:413
void fillrand(Span< std::byte > output) noexcept
Fill a byte Span with random bytes.
Definition: random.cpp:714
xoroshiro128++ PRNG.
Definition: random.h:459
static constexpr uint64_t SplitMix64(uint64_t &seedval) noexcept
Definition: random.h:464
constexpr uint64_t rand64() noexcept
Definition: random.h:481
constexpr void Reseed(uint64_t seedval) noexcept
Definition: random.h:475
constexpr InsecureRandomContext(uint64_t seedval) noexcept
Definition: random.h:472
===================== RANDOM NUMBER GENERATION CLASSES =====================
Definition: random.h:184
uint160 rand160() noexcept
generate a random uint160.
Definition: random.h:321
static constexpr uint64_t max() noexcept
Definition: random.h:399
constexpr RandomMixin() noexcept=default
RandomNumberGenerator auto & Impl() noexcept
Access the underlying generator.
Definition: random.h:196
Dur randrange(typename std::common_type_t< Dur > range) noexcept
Generate a uniform random duration in the range [0..max).
Definition: random.h:368
void fillrand(Span< std::byte > span) noexcept
Fill a Span with random bytes.
Definition: random.h:281
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:339
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:351
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
Definition: random.h:266
int bitbuf_size
Definition: random.h:187
uint256 rand256() noexcept
generate a random uint256.
Definition: random.h:328
uint64_t result_type
Definition: random.h:397
uint64_t bitbuf
Definition: random.h:186
bool randbool() noexcept
Generate a random boolean.
Definition: random.h:335
I rand() noexcept
Generate a random integer in its entire (non-negative) range.
Definition: random.h:299
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition: random.h:311
constexpr void FlushCache() noexcept
Definition: random.h:201
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:389
static constexpr uint64_t min() noexcept
Definition: random.h:398
uint32_t rand32() noexcept
Generate a random 32-bit integer.
Definition: random.h:318
uint64_t randbits() noexcept
Same as above, but with compile-time fixed bits count.
Definition: random.h:244
uint64_t operator()() noexcept
Definition: random.h:402
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:94
160-bit opaque blob.
Definition: uint256.h:117
256-bit opaque blob.
Definition: uint256.h:129
A concept for RandomMixin-based random number generators.
Definition: random.h:151
A concept for C++ std::chrono durations.
Definition: random.h:162
static void WriteLE32(uint8_t *ptr, uint32_t x)
Definition: common.h:36
static uint64_t ReadLE64(const uint8_t *ptr)
Definition: common.h:25
static void WriteLE64(uint8_t *ptr, uint64_t x)
Definition: common.h:41
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
void GetRandBytes(Span< uint8_t > bytes) noexcept
================== BASE RANDOMNESS GENERATION FUNCTIONS ====================
Definition: random.cpp:690
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
Definition: random.cpp:700
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:512
bool Random_SanityCheck()
=============== MISCELLANEOUS TEST-ONLY FUNCTIONS ======================
Definition: random.cpp:730
uint256 GetRandHash() noexcept
========== CONVENIENCE FUNCTIONS FOR COMMONLY USED RANDOMNESS ==========
Definition: random.h:494
void RandomInit()
Overall design of the RNG and entropy sources.
Definition: random.cpp:796
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
Definition: random.cpp:704
double MakeExponentiallyDistributed(uint64_t uniform) noexcept
Given a uniformly random uint64_t, return an exponentially distributed double with mean 1.
Definition: random.cpp:803
void GetStrongRandBytes(Span< uint8_t > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition: random.cpp:695
uint8_t * UCharCast(char *c)
Definition: span.h:310
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:305