2014-06-26 14:41:53 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
2018-07-27 00:36:45 +02:00
|
|
|
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
2014-12-13 05:09:33 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2014-06-26 14:41:53 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#ifndef BITCOIN_RANDOM_H
|
|
|
|
#define BITCOIN_RANDOM_H
|
|
|
|
|
2017-11-10 01:57:53 +01:00
|
|
|
#include <crypto/chacha20.h>
|
|
|
|
#include <crypto/common.h>
|
|
|
|
#include <uint256.h>
|
2014-06-26 14:41:53 +02:00
|
|
|
|
|
|
|
#include <stdint.h>
|
2018-03-21 03:10:39 +01:00
|
|
|
#include <limits>
|
2014-06-26 14:41:53 +02:00
|
|
|
|
2016-04-16 12:25:12 +02:00
|
|
|
/* Seed OpenSSL PRNG with additional entropy data */
|
2014-06-26 14:41:53 +02:00
|
|
|
void RandAddSeed();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Functions to gather random data via the OpenSSL PRNG
|
|
|
|
*/
|
2014-11-07 13:42:52 +01:00
|
|
|
void GetRandBytes(unsigned char* buf, int num);
|
2014-06-26 14:41:53 +02:00
|
|
|
uint64_t GetRand(uint64_t nMax);
|
|
|
|
int GetRandInt(int nMax);
|
|
|
|
uint256 GetRandHash();
|
|
|
|
|
2017-05-22 22:01:52 +02:00
|
|
|
/**
|
|
|
|
* Add a little bit of randomness to the output of GetStrongRangBytes.
|
|
|
|
* This sleeps for a millisecond, so should only be called when there is
|
|
|
|
* no other work to be done.
|
|
|
|
*/
|
|
|
|
void RandAddSeedSleep();
|
|
|
|
|
2016-04-16 12:25:12 +02:00
|
|
|
/**
|
|
|
|
* Function to gather random data from multiple sources, failing whenever any
|
2018-03-18 15:26:45 +01:00
|
|
|
* of those sources fail to provide a result.
|
2016-04-16 12:25:12 +02:00
|
|
|
*/
|
|
|
|
void GetStrongRandBytes(unsigned char* buf, int num);
|
|
|
|
|
2014-06-26 14:41:53 +02:00
|
|
|
/**
|
2016-10-13 16:19:20 +02:00
|
|
|
* Fast randomness source. This is seeded once with secure random data, but
|
|
|
|
* is completely deterministic and insecure after that.
|
|
|
|
* This class is not thread-safe.
|
2014-06-26 14:41:53 +02:00
|
|
|
*/
|
2016-10-13 16:19:20 +02:00
|
|
|
class FastRandomContext {
|
2017-02-16 02:45:22 +01:00
|
|
|
private:
|
|
|
|
bool requires_seed;
|
|
|
|
ChaCha20 rng;
|
|
|
|
|
|
|
|
unsigned char bytebuf[64];
|
|
|
|
int bytebuf_size;
|
|
|
|
|
|
|
|
uint64_t bitbuf;
|
|
|
|
int bitbuf_size;
|
|
|
|
|
|
|
|
void RandomSeed();
|
|
|
|
|
|
|
|
void FillByteBuffer()
|
|
|
|
{
|
|
|
|
if (requires_seed) {
|
|
|
|
RandomSeed();
|
|
|
|
}
|
|
|
|
rng.Output(bytebuf, sizeof(bytebuf));
|
|
|
|
bytebuf_size = sizeof(bytebuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FillBitBuffer()
|
|
|
|
{
|
|
|
|
bitbuf = rand64();
|
|
|
|
bitbuf_size = 64;
|
|
|
|
}
|
|
|
|
|
2016-10-13 16:19:20 +02:00
|
|
|
public:
|
2017-02-16 02:45:22 +01:00
|
|
|
explicit FastRandomContext(bool fDeterministic = false);
|
2016-10-13 16:19:20 +02:00
|
|
|
|
2017-02-16 02:45:22 +01:00
|
|
|
/** Initialize with explicit seed (only for testing) */
|
|
|
|
explicit FastRandomContext(const uint256& seed);
|
|
|
|
|
|
|
|
/** Generate a random 64-bit integer. */
|
|
|
|
uint64_t rand64()
|
|
|
|
{
|
|
|
|
if (bytebuf_size < 8) FillByteBuffer();
|
|
|
|
uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size);
|
|
|
|
bytebuf_size -= 8;
|
|
|
|
return ret;
|
2016-10-13 16:19:20 +02:00
|
|
|
}
|
|
|
|
|
2017-02-16 02:45:22 +01:00
|
|
|
/** Generate a random (bits)-bit integer. */
|
|
|
|
uint64_t randbits(int bits) {
|
|
|
|
if (bits == 0) {
|
|
|
|
return 0;
|
|
|
|
} else if (bits > 32) {
|
|
|
|
return rand64() >> (64 - bits);
|
|
|
|
} else {
|
|
|
|
if (bitbuf_size < bits) FillBitBuffer();
|
|
|
|
uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits));
|
|
|
|
bitbuf >>= bits;
|
|
|
|
bitbuf_size -= bits;
|
|
|
|
return ret;
|
|
|
|
}
|
2017-02-18 01:32:16 +01:00
|
|
|
}
|
|
|
|
|
2017-02-25 21:16:58 +01:00
|
|
|
/** Generate a random integer in the range [0..range). */
|
|
|
|
uint64_t randrange(uint64_t range)
|
|
|
|
{
|
|
|
|
--range;
|
|
|
|
int bits = CountBits(range);
|
|
|
|
while (true) {
|
|
|
|
uint64_t ret = randbits(bits);
|
|
|
|
if (ret <= range) return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-02 20:04:31 +02:00
|
|
|
/** Generate random bytes. */
|
|
|
|
std::vector<unsigned char> randbytes(size_t len);
|
|
|
|
|
2017-02-16 02:45:22 +01:00
|
|
|
/** Generate a random 32-bit integer. */
|
|
|
|
uint32_t rand32() { return randbits(32); }
|
|
|
|
|
2017-05-02 20:04:31 +02:00
|
|
|
/** generate a random uint256. */
|
|
|
|
uint256 rand256();
|
|
|
|
|
2017-02-16 02:45:22 +01:00
|
|
|
/** Generate a random boolean. */
|
|
|
|
bool randbool() { return randbits(1); }
|
2018-03-21 03:10:39 +01:00
|
|
|
|
|
|
|
// Compatibility with the C++11 UniformRandomBitGenerator concept
|
|
|
|
typedef uint64_t result_type;
|
|
|
|
static constexpr uint64_t min() { return 0; }
|
|
|
|
static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); }
|
|
|
|
inline uint64_t operator()() { return rand64(); }
|
2016-10-13 16:19:20 +02:00
|
|
|
};
|
2014-06-26 14:41:53 +02:00
|
|
|
|
2018-10-31 23:42:03 +01:00
|
|
|
/** More efficient than using std::shuffle on a FastRandomContext.
|
|
|
|
*
|
|
|
|
* This is more efficient as std::shuffle will consume entropy in groups of
|
|
|
|
* 64 bits at the time and throw away most.
|
|
|
|
*
|
|
|
|
* This also works around a bug in libstdc++ std::shuffle that may cause
|
|
|
|
* type::operator=(type&&) to be invoked on itself, which the library's
|
|
|
|
* debug mode detects and panics on. This is a known issue, see
|
|
|
|
* https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle
|
|
|
|
*/
|
|
|
|
template<typename I, typename R>
|
|
|
|
void Shuffle(I first, I last, R&& rng)
|
|
|
|
{
|
|
|
|
while (first != last) {
|
|
|
|
size_t j = rng.randrange(last - first);
|
|
|
|
if (j) {
|
|
|
|
using std::swap;
|
|
|
|
swap(*first, *(first + j));
|
|
|
|
}
|
|
|
|
++first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 07:38:42 +01:00
|
|
|
/* Number of random bytes returned by GetOSRand.
|
|
|
|
* When changing this constant make sure to change all call sites, and make
|
|
|
|
* sure that the underlying OS APIs for all platforms support the number.
|
|
|
|
* (many cap out at 256 bytes).
|
|
|
|
*/
|
2017-11-09 21:06:49 +01:00
|
|
|
static const int NUM_OS_RANDOM_BYTES = 32;
|
2017-02-21 17:36:37 +01:00
|
|
|
|
|
|
|
/** Get 32 bytes of system entropy. Do not use this in application code: use
|
|
|
|
* GetStrongRandBytes instead.
|
|
|
|
*/
|
|
|
|
void GetOSRand(unsigned char *ent32);
|
|
|
|
|
2017-02-22 08:02:50 +01:00
|
|
|
/** Check that OS randomness is available and returning the requested number
|
|
|
|
* of bytes.
|
|
|
|
*/
|
|
|
|
bool Random_SanityCheck();
|
|
|
|
|
2017-05-10 00:13:00 +02:00
|
|
|
/** Initialize the RNG. */
|
|
|
|
void RandomInit();
|
|
|
|
|
2014-06-26 14:41:53 +02:00
|
|
|
#endif // BITCOIN_RANDOM_H
|