Bitcoin ABC  0.26.3
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 
14 #include <chrono>
15 #include <cstdint>
16 #include <limits>
17 
73 void GetRandBytes(Span<uint8_t> bytes) noexcept;
78 uint64_t GetRandInternal(uint64_t nMax) noexcept;
84 template <typename T>
85 T GetRand(T nMax = std::numeric_limits<T>::max()) noexcept {
86  static_assert(std::is_integral<T>(), "T must be integral");
87  static_assert(std::numeric_limits<T>::max() <=
88  std::numeric_limits<uint64_t>::max(),
89  "GetRand only supports up to uint64_t");
90  return T(GetRandInternal(nMax));
91 }
96 template <typename D>
97 D GetRandomDuration(typename std::common_type<D>::type max) noexcept {
98  // Having the compiler infer the template argument from the function
99  // argument is dangerous, because the desired return value generally has a
100  // different type than the function argument. So std::common_type is used to
101  // force the call site to specify the type of the return value.
102 
103  assert(max.count() > 0);
104  return D{GetRand(max.count())};
105 };
106 constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>;
107 constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
108 
118 std::chrono::microseconds
119 GetExponentialRand(std::chrono::microseconds now,
120  std::chrono::seconds average_interval);
121 
122 uint256 GetRandHash() noexcept;
123 
132 void GetStrongRandBytes(Span<uint8_t> bytes) noexcept;
133 
140 void RandAddPeriodic() noexcept;
141 
148 void RandAddEvent(const uint32_t event_info) noexcept;
149 
157 private:
160 
161  uint8_t bytebuf[64];
163 
164  uint64_t bitbuf;
166 
167  void RandomSeed();
168 
169  void FillByteBuffer() {
170  if (requires_seed) {
171  RandomSeed();
172  }
173  rng.Keystream(bytebuf, sizeof(bytebuf));
174  bytebuf_size = sizeof(bytebuf);
175  }
176 
177  void FillBitBuffer() {
178  bitbuf = rand64();
179  bitbuf_size = 64;
180  }
181 
182 public:
183  explicit FastRandomContext(bool fDeterministic = false) noexcept;
184 
186  explicit FastRandomContext(const uint256 &seed) noexcept;
187 
188  // Do not permit copying a FastRandomContext (move it, or create a new one
189  // to get reseeded).
192  FastRandomContext &operator=(const FastRandomContext &) = delete;
193 
198  FastRandomContext &operator=(FastRandomContext &&from) noexcept;
199 
201  uint64_t rand64() noexcept {
202  if (bytebuf_size < 8) {
203  FillByteBuffer();
204  }
205  uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size);
206  bytebuf_size -= 8;
207  return ret;
208  }
209 
211  uint64_t randbits(int bits) noexcept {
212  if (bits == 0) {
213  return 0;
214  } else if (bits > 32) {
215  return rand64() >> (64 - bits);
216  } else {
217  if (bitbuf_size < bits) {
218  FillBitBuffer();
219  }
220  uint64_t ret = bitbuf & (~uint64_t(0) >> (64 - bits));
221  bitbuf >>= bits;
222  bitbuf_size -= bits;
223  return ret;
224  }
225  }
226 
231  uint64_t randrange(uint64_t range) noexcept {
232  assert(range);
233  --range;
234  int bits = CountBits(range);
235  while (true) {
236  uint64_t ret = randbits(bits);
237  if (ret <= range) {
238  return ret;
239  }
240  }
241  }
242 
244  std::vector<uint8_t> randbytes(size_t len);
245 
247  uint32_t rand32() noexcept { return randbits(32); }
248 
250  uint160 rand160() noexcept;
251 
253  uint256 rand256() noexcept;
254 
256  bool randbool() noexcept { return randbits(1); }
257 
259  template <typename Tp>
260  Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) {
261  using Dur = typename Tp::duration;
262  Dur dur{range.count() > 0
263  ? /* interval [0..range) */ Dur{randrange(range.count())}
264  : range.count() < 0
265  ? /* interval (range..0] */ -Dur{randrange(-range.count())}
266  :
267  /* interval [0..0] */ Dur{0}};
268  return time + dur;
269  }
270 
271  // Compatibility with the C++11 UniformRandomBitGenerator concept
272  typedef uint64_t result_type;
273  static constexpr uint64_t min() { return 0; }
274  static constexpr uint64_t max() {
275  return std::numeric_limits<uint64_t>::max();
276  }
277  inline uint64_t operator()() noexcept { return rand64(); }
278 };
279 
291 template <typename I, typename R> void Shuffle(I first, I last, R &&rng) {
292  while (first != last) {
293  size_t j = rng.randrange(last - first);
294  if (j) {
295  using std::swap;
296  swap(*first, *(first + j));
297  }
298  ++first;
299  }
300 }
301 
308 static const int NUM_OS_RANDOM_BYTES = 32;
309 
314 void GetOSRand(uint8_t *ent32);
315 
320 bool Random_SanityCheck();
321 
328 void RandomInit();
329 
330 #endif // BITCOIN_RANDOM_H
A class for ChaCha20 256-bit stream cipher developed by Daniel J.
Definition: chacha20.h:15
void Keystream(uint8_t *c, size_t bytes)
outputs the keystream of size <bytes> into
Definition: chacha20.cpp:79
Fast randomness source.
Definition: random.h:156
uint32_t rand32() noexcept
Generate a random 32-bit integer.
Definition: random.h:247
void FillBitBuffer()
Definition: random.h:177
uint64_t bitbuf
Definition: random.h:164
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
Definition: random.h:260
ChaCha20 rng
Definition: random.h:159
static constexpr uint64_t max()
Definition: random.h:274
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
Definition: random.h:211
static constexpr uint64_t min()
Definition: random.h:273
uint64_t result_type
Definition: random.h:272
bool requires_seed
Definition: random.h:158
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Definition: random.h:231
uint64_t operator()() noexcept
Definition: random.h:277
void FillByteBuffer()
Definition: random.h:169
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:93
160-bit opaque blob.
Definition: uint256.h:115
256-bit opaque blob.
Definition: uint256.h:127
static uint64_t ReadLE64(const uint8_t *ptr)
Definition: common.h:29
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:82
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....
Definition: random.cpp:794
D GetRandomDuration(typename std::common_type< D >::type max) noexcept
Generate a uniform random duration in the range [0..max).
Definition: random.h:97
constexpr auto GetRandMicros
Definition: random.h:106
void GetRandBytes(Span< uint8_t > bytes) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:639
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
Definition: random.cpp:645
constexpr auto GetRandMillis
Definition: random.h:107
uint64_t GetRandInternal(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
Definition: random.cpp:655
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:291
void GetOSRand(uint8_t *ent32)
Get 32 bytes of system entropy.
Definition: random.cpp:319
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
Definition: random.cpp:706
uint256 GetRandHash() noexcept
Definition: random.cpp:659
static const int NUM_OS_RANDOM_BYTES
Number of random bytes returned by GetOSRand.
Definition: random.h:308
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
Definition: random.cpp:786
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
Definition: random.cpp:649
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:85
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:642
assert(!tx.IsCoinBase())