Changeset View
Changeset View
Standalone View
Standalone View
src/random.h
Show All 15 Lines | |||||
/** | /** | ||||
* Generate random data via the internal PRNG. | * Generate random data via the internal PRNG. | ||||
* | * | ||||
* These functions are designed to be fast (sub microsecond), but do not | * These functions are designed to be fast (sub microsecond), but do not | ||||
* necessarily meaningfully add entropy to the PRNG state. | * necessarily meaningfully add entropy to the PRNG state. | ||||
* | * | ||||
* Thread-safe. | * Thread-safe. | ||||
*/ | */ | ||||
void GetRandBytes(uint8_t *buf, int num); | void GetRandBytes(uint8_t *buf, int num) noexcept; | ||||
uint64_t GetRand(uint64_t nMax); | uint64_t GetRand(uint64_t nMax) noexcept; | ||||
int GetRandInt(int nMax); | int GetRandInt(int nMax) noexcept; | ||||
uint256 GetRandHash(); | uint256 GetRandHash() noexcept; | ||||
/** | /** | ||||
* Gather entropy from various sources, feed it into the internal PRNG, and | * Gather entropy from various sources, feed it into the internal PRNG, and | ||||
* generate random data using it. | * generate random data using it. | ||||
* | * | ||||
* This function will cause failure whenever the OS RNG fails. | * This function will cause failure whenever the OS RNG fails. | ||||
* | * | ||||
* Thread-safe. | * Thread-safe. | ||||
*/ | */ | ||||
void GetStrongRandBytes(uint8_t *buf, int num); | void GetStrongRandBytes(uint8_t *buf, int num) noexcept; | ||||
/** | /** | ||||
* Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG | * Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG | ||||
* state. | * state. | ||||
* | * | ||||
* Thread-safe. | * Thread-safe. | ||||
*/ | */ | ||||
void RandAddSeedSleep(); | void RandAddSeedSleep(); | ||||
Show All 26 Lines | private: | ||||
} | } | ||||
void FillBitBuffer() { | void FillBitBuffer() { | ||||
bitbuf = rand64(); | bitbuf = rand64(); | ||||
bitbuf_size = 64; | bitbuf_size = 64; | ||||
} | } | ||||
public: | public: | ||||
explicit FastRandomContext(bool fDeterministic = false); | explicit FastRandomContext(bool fDeterministic = false) noexcept; | ||||
/** Initialize with explicit seed (only for testing) */ | /** Initialize with explicit seed (only for testing) */ | ||||
explicit FastRandomContext(const uint256 &seed); | explicit FastRandomContext(const uint256 &seed) noexcept; | ||||
// Do not permit copying a FastRandomContext (move it, or create a new one | // Do not permit copying a FastRandomContext (move it, or create a new one | ||||
// to get reseeded). | // to get reseeded). | ||||
FastRandomContext(const FastRandomContext &) = delete; | FastRandomContext(const FastRandomContext &) = delete; | ||||
FastRandomContext(FastRandomContext &&) = delete; | FastRandomContext(FastRandomContext &&) = delete; | ||||
FastRandomContext &operator=(const FastRandomContext &) = delete; | FastRandomContext &operator=(const FastRandomContext &) = delete; | ||||
/** | /** | ||||
* Move a FastRandomContext. If the original one is used again, it will be | * Move a FastRandomContext. If the original one is used again, it will be | ||||
* reseeded. | * reseeded. | ||||
*/ | */ | ||||
FastRandomContext &operator=(FastRandomContext &&from) noexcept; | FastRandomContext &operator=(FastRandomContext &&from) noexcept; | ||||
/** Generate a random 64-bit integer. */ | /** Generate a random 64-bit integer. */ | ||||
uint64_t rand64() { | uint64_t rand64() noexcept { | ||||
if (bytebuf_size < 8) { | if (bytebuf_size < 8) { | ||||
FillByteBuffer(); | FillByteBuffer(); | ||||
} | } | ||||
uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size); | uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size); | ||||
bytebuf_size -= 8; | bytebuf_size -= 8; | ||||
return ret; | return ret; | ||||
} | } | ||||
/** Generate a random (bits)-bit integer. */ | /** Generate a random (bits)-bit integer. */ | ||||
uint64_t randbits(int bits) { | uint64_t randbits(int bits) noexcept { | ||||
if (bits == 0) { | if (bits == 0) { | ||||
return 0; | return 0; | ||||
} else if (bits > 32) { | } else if (bits > 32) { | ||||
return rand64() >> (64 - bits); | return rand64() >> (64 - bits); | ||||
} else { | } else { | ||||
if (bitbuf_size < bits) { | if (bitbuf_size < bits) { | ||||
FillBitBuffer(); | FillBitBuffer(); | ||||
} | } | ||||
uint64_t ret = bitbuf & (~uint64_t(0) >> (64 - bits)); | uint64_t ret = bitbuf & (~uint64_t(0) >> (64 - bits)); | ||||
bitbuf >>= bits; | bitbuf >>= bits; | ||||
bitbuf_size -= bits; | bitbuf_size -= bits; | ||||
return ret; | return ret; | ||||
} | } | ||||
} | } | ||||
/** Generate a random integer in the range [0..range). */ | /** Generate a random integer in the range [0..range). */ | ||||
uint64_t randrange(uint64_t range) { | uint64_t randrange(uint64_t range) noexcept { | ||||
--range; | --range; | ||||
int bits = CountBits(range); | int bits = CountBits(range); | ||||
while (true) { | while (true) { | ||||
uint64_t ret = randbits(bits); | uint64_t ret = randbits(bits); | ||||
if (ret <= range) { | if (ret <= range) { | ||||
return ret; | return ret; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/** Generate random bytes. */ | /** Generate random bytes. */ | ||||
std::vector<uint8_t> randbytes(size_t len); | std::vector<uint8_t> randbytes(size_t len); | ||||
/** Generate a random 32-bit integer. */ | /** Generate a random 32-bit integer. */ | ||||
uint32_t rand32() { return randbits(32); } | uint32_t rand32() noexcept { return randbits(32); } | ||||
/** generate a random uint256. */ | /** generate a random uint256. */ | ||||
uint256 rand256(); | uint256 rand256() noexcept; | ||||
/** Generate a random boolean. */ | /** Generate a random boolean. */ | ||||
bool randbool() { return randbits(1); } | bool randbool() noexcept { return randbits(1); } | ||||
// Compatibility with the C++11 UniformRandomBitGenerator concept | // Compatibility with the C++11 UniformRandomBitGenerator concept | ||||
typedef uint64_t result_type; | typedef uint64_t result_type; | ||||
static constexpr uint64_t min() { return 0; } | static constexpr uint64_t min() { return 0; } | ||||
static constexpr uint64_t max() { | static constexpr uint64_t max() { | ||||
return std::numeric_limits<uint64_t>::max(); | return std::numeric_limits<uint64_t>::max(); | ||||
} | } | ||||
inline uint64_t operator()() { return rand64(); } | inline uint64_t operator()() noexcept { return rand64(); } | ||||
}; | }; | ||||
/** | /** | ||||
* More efficient than using std::shuffle on a FastRandomContext. | * More efficient than using std::shuffle on a FastRandomContext. | ||||
* | * | ||||
* This is more efficient as std::shuffle will consume entropy in groups of | * This is more efficient as std::shuffle will consume entropy in groups of | ||||
* 64 bits at the time and throw away most. | * 64 bits at the time and throw away most. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 45 Lines • Show Last 20 Lines |