Bitcoin Core  24.1.0
P2P Digital Currency
random.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 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 
14 #include <cassert>
15 #include <chrono>
16 #include <cstdint>
17 #include <limits>
18 
71 void GetRandBytes(Span<unsigned char> bytes) noexcept;
73 uint64_t GetRandInternal(uint64_t nMax) noexcept;
78 template<typename T>
79 T GetRand(T nMax=std::numeric_limits<T>::max()) noexcept {
80  static_assert(std::is_integral<T>(), "T must be integral");
81  static_assert(std::numeric_limits<T>::max() <= std::numeric_limits<uint64_t>::max(), "GetRand only supports up to uint64_t");
82  return T(GetRandInternal(nMax));
83 }
85 template <typename D>
86 D GetRandomDuration(typename std::common_type<D>::type max) noexcept
87 // Having the compiler infer the template argument from the function argument
88 // is dangerous, because the desired return value generally has a different
89 // type than the function argument. So std::common_type is used to force the
90 // call site to specify the type of the return value.
91 {
92  assert(max.count() > 0);
93  return D{GetRand(max.count())};
94 };
95 constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>;
96 constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
97 
107 std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval);
108 
109 uint256 GetRandHash() noexcept;
110 
119 void GetStrongRandBytes(Span<unsigned char> bytes) noexcept;
120 
126 void RandAddPeriodic() noexcept;
127 
134 void RandAddEvent(const uint32_t event_info) noexcept;
135 
143 {
144 private:
147 
148  unsigned char bytebuf[64];
150 
151  uint64_t bitbuf;
153 
154  void RandomSeed();
155 
157  {
158  if (requires_seed) {
159  RandomSeed();
160  }
161  rng.Keystream(bytebuf, sizeof(bytebuf));
162  bytebuf_size = sizeof(bytebuf);
163  }
164 
166  {
167  bitbuf = rand64();
168  bitbuf_size = 64;
169  }
170 
171 public:
172  explicit FastRandomContext(bool fDeterministic = false) noexcept;
173 
175  explicit FastRandomContext(const uint256& seed) noexcept;
176 
177  // Do not permit copying a FastRandomContext (move it, or create a new one to get reseeded).
178  FastRandomContext(const FastRandomContext&) = delete;
180  FastRandomContext& operator=(const FastRandomContext&) = delete;
181 
183  FastRandomContext& operator=(FastRandomContext&& from) noexcept;
184 
186  uint64_t rand64() noexcept
187  {
188  if (bytebuf_size < 8) FillByteBuffer();
189  uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size);
190  bytebuf_size -= 8;
191  return ret;
192  }
193 
195  uint64_t randbits(int bits) noexcept
196  {
197  if (bits == 0) {
198  return 0;
199  } else if (bits > 32) {
200  return rand64() >> (64 - bits);
201  } else {
202  if (bitbuf_size < bits) FillBitBuffer();
203  uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits));
204  bitbuf >>= bits;
205  bitbuf_size -= bits;
206  return ret;
207  }
208  }
209 
213  uint64_t randrange(uint64_t range) noexcept
214  {
215  assert(range);
216  --range;
217  int bits = CountBits(range);
218  while (true) {
219  uint64_t ret = randbits(bits);
220  if (ret <= range) return ret;
221  }
222  }
223 
225  std::vector<unsigned char> randbytes(size_t len);
226 
228  uint32_t rand32() noexcept { return randbits(32); }
229 
231  uint256 rand256() noexcept;
232 
234  bool randbool() noexcept { return randbits(1); }
235 
237  template <typename Tp>
238  Tp rand_uniform_delay(const Tp& time, typename Tp::duration range)
239  {
240  return time + rand_uniform_duration<Tp>(range);
241  }
242 
244  template <typename Chrono>
245  typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
246  {
247  using Dur = typename Chrono::duration;
248  return range.count() > 0 ? /* interval [0..range) */ Dur{randrange(range.count())} :
249  range.count() < 0 ? /* interval (range..0] */ -Dur{randrange(-range.count())} :
250  /* interval [0..0] */ Dur{0};
251  };
252 
253  // Compatibility with the C++11 UniformRandomBitGenerator concept
254  typedef uint64_t result_type;
255  static constexpr uint64_t min() { return 0; }
256  static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); }
257  inline uint64_t operator()() noexcept { return rand64(); }
258 };
259 
270 template <typename I, typename R>
271 void Shuffle(I first, I last, R&& rng)
272 {
273  while (first != last) {
274  size_t j = rng.randrange(last - first);
275  if (j) {
276  using std::swap;
277  swap(*first, *(first + j));
278  }
279  ++first;
280  }
281 }
282 
283 /* Number of random bytes returned by GetOSRand.
284  * When changing this constant make sure to change all call sites, and make
285  * sure that the underlying OS APIs for all platforms support the number.
286  * (many cap out at 256 bytes).
287  */
288 static const int NUM_OS_RANDOM_BYTES = 32;
289 
293 void GetOSRand(unsigned char* ent32);
294 
298 bool Random_SanityCheck();
299 
306 void RandomInit();
307 
308 #endif // BITCOIN_RANDOM_H
static const int NUM_OS_RANDOM_BYTES
Definition: random.h:288
int ret
assert(!tx.IsCoinBase())
uint64_t bitbuf
Definition: random.h:151
constexpr auto GetRandMillis
Definition: random.h:96
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
Definition: random.cpp:632
void FillBitBuffer()
Definition: random.h:165
void FillByteBuffer()
Definition: random.h:156
constexpr auto GetRandMicros
Definition: random.h:95
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition: random.h:79
A class for ChaCha20 256-bit stream cipher developed by Daniel J.
Definition: chacha20.h:13
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
Definition: random.h:195
void GetRandBytes(Span< unsigned char > bytes) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:580
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
Definition: random.cpp:701
Fast randomness source.
Definition: random.h:142
static constexpr uint64_t max()
Definition: random.h:256
static uint64_t CountBits(uint64_t x)
Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set...
Definition: common.h:90
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
Definition: random.cpp:582
static uint64_t ReadLE64(const unsigned char *ptr)
Definition: common.h:31
uint32_t rand32() noexcept
Generate a random 32-bit integer.
Definition: random.h:228
bool requires_seed
Definition: random.h:145
256-bit opaque blob.
Definition: uint256.h:119
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:581
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:271
void Keystream(unsigned char *c, size_t bytes)
outputs the keystream of size <bytes> into
Definition: chacha20.cpp:76
uint256 GetRandHash() noexcept
Definition: random.cpp:592
void GetOSRand(unsigned char *ent32)
Get 32 bytes of system entropy.
Definition: random.cpp:276
D GetRandomDuration(typename std::common_type< D >::type max) noexcept
Generate a uniform random duration in the range [0..max).
Definition: random.h:86
uint64_t operator()() noexcept
Definition: random.h:257
static constexpr uint64_t min()
Definition: random.h:255
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
Definition: random.h:238
uint64_t GetRandInternal(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
Definition: random.cpp:587
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:96
ChaCha20 rng
Definition: random.h:146
#define T(expected, seed, data)
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
Definition: random.cpp:583
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Definition: random.h:213
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:245
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en.wikipedia.org/wiki/Exponential_distribution).
Definition: random.cpp:709