Skip to content

Commit a1f252e

Browse files
committed
Sprinkle some sweet noexcepts over the RNG code
1 parent 4ea8e50 commit a1f252e

File tree

2 files changed

+46
-31
lines changed

2 files changed

+46
-31
lines changed

src/random.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
std::abort();
5656
}
5757

58-
static inline int64_t GetPerformanceCounter()
58+
static inline int64_t GetPerformanceCounter() noexcept
5959
{
6060
// Read the hardware time stamp counter when available.
6161
// See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
@@ -105,7 +105,7 @@ static void InitHardwareRand() {}
105105
static void ReportHardwareRand() {}
106106
#endif
107107

108-
static bool GetHardwareRand(unsigned char* ent32) {
108+
static bool GetHardwareRand(unsigned char* ent32) noexcept {
109109
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
110110
if (rdrand_supported) {
111111
uint8_t ok;
@@ -285,7 +285,7 @@ struct RNGState {
285285
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
286286
std::unique_ptr<Mutex[]> m_mutex_openssl;
287287

288-
RNGState()
288+
RNGState() noexcept
289289
{
290290
InitHardwareRand();
291291

@@ -313,7 +313,7 @@ struct RNGState {
313313
*
314314
* If this function has never been called with strong_seed = true, false is returned.
315315
*/
316-
bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed)
316+
bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept
317317
{
318318
assert(num <= 32);
319319
unsigned char buf[64];
@@ -344,7 +344,7 @@ struct RNGState {
344344
}
345345
};
346346

347-
RNGState& GetRNGState()
347+
RNGState& GetRNGState() noexcept
348348
{
349349
// This C++11 idiom relies on the guarantee that static variable are initialized
350350
// on first call, even when multiple parallel calls are permitted.
@@ -364,13 +364,28 @@ void LockingCallbackOpenSSL(int mode, int i, const char* file, int line) NO_THRE
364364
}
365365
}
366366

367-
static void SeedTimestamp(CSHA512& hasher)
367+
/* A note on the use of noexcept in the seeding functions below:
368+
*
369+
* None of the RNG code should ever throw any exception, with the sole exception
370+
* of MilliSleep in SeedSleep, which can (and does) support interruptions which
371+
* cause a boost::thread_interrupted to be thrown.
372+
*
373+
* This means that SeedSleep, and all functions that invoke it are throwing.
374+
* However, we know that GetRandBytes() and GetStrongRandBytes() never trigger
375+
* this sleeping logic, so they are noexcept. The same is true for all the
376+
* GetRand*() functions that use GetRandBytes() indirectly.
377+
*
378+
* TODO: After moving away from interruptible boost-based thread management,
379+
* everything can become noexcept here.
380+
*/
381+
382+
static void SeedTimestamp(CSHA512& hasher) noexcept
368383
{
369384
int64_t perfcounter = GetPerformanceCounter();
370385
hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
371386
}
372387

373-
static void SeedFast(CSHA512& hasher)
388+
static void SeedFast(CSHA512& hasher) noexcept
374389
{
375390
unsigned char buffer[32];
376391

@@ -386,7 +401,7 @@ static void SeedFast(CSHA512& hasher)
386401
SeedTimestamp(hasher);
387402
}
388403

389-
static void SeedSlow(CSHA512& hasher)
404+
static void SeedSlow(CSHA512& hasher) noexcept
390405
{
391406
unsigned char buffer[32];
392407

@@ -426,7 +441,7 @@ static void SeedSleep(CSHA512& hasher)
426441
RandAddSeedPerfmon(hasher);
427442
}
428443

429-
static void SeedStartup(CSHA512& hasher)
444+
static void SeedStartup(CSHA512& hasher) noexcept
430445
{
431446
#ifdef WIN32
432447
RAND_screen();
@@ -482,11 +497,11 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
482497
}
483498
}
484499

485-
void GetRandBytes(unsigned char* buf, int num) { ProcRand(buf, num, RNGLevel::FAST); }
486-
void GetStrongRandBytes(unsigned char* buf, int num) { ProcRand(buf, num, RNGLevel::SLOW); }
500+
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
501+
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
487502
void RandAddSeedSleep() { ProcRand(nullptr, 0, RNGLevel::SLEEP); }
488503

489-
uint64_t GetRand(uint64_t nMax)
504+
uint64_t GetRand(uint64_t nMax) noexcept
490505
{
491506
if (nMax == 0)
492507
return 0;
@@ -501,12 +516,12 @@ uint64_t GetRand(uint64_t nMax)
501516
return (nRand % nMax);
502517
}
503518

504-
int GetRandInt(int nMax)
519+
int GetRandInt(int nMax) noexcept
505520
{
506521
return GetRand(nMax);
507522
}
508523

509-
uint256 GetRandHash()
524+
uint256 GetRandHash() noexcept
510525
{
511526
uint256 hash;
512527
GetRandBytes((unsigned char*)&hash, sizeof(hash));
@@ -520,7 +535,7 @@ void FastRandomContext::RandomSeed()
520535
requires_seed = false;
521536
}
522537

523-
uint256 FastRandomContext::rand256()
538+
uint256 FastRandomContext::rand256() noexcept
524539
{
525540
if (bytebuf_size < 32) {
526541
FillByteBuffer();
@@ -541,7 +556,7 @@ std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
541556
return ret;
542557
}
543558

544-
FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
559+
FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
545560
{
546561
rng.SetKey(seed.begin(), 32);
547562
}
@@ -592,7 +607,7 @@ bool Random_SanityCheck()
592607
return true;
593608
}
594609

595-
FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
610+
FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
596611
{
597612
if (!fDeterministic) {
598613
return;

src/random.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
*
2222
* Thread-safe.
2323
*/
24-
void GetRandBytes(unsigned char* buf, int num);
25-
uint64_t GetRand(uint64_t nMax);
26-
int GetRandInt(int nMax);
27-
uint256 GetRandHash();
24+
void GetRandBytes(unsigned char* buf, int num) noexcept;
25+
uint64_t GetRand(uint64_t nMax) noexcept;
26+
int GetRandInt(int nMax) noexcept;
27+
uint256 GetRandHash() noexcept;
2828

2929
/**
3030
* Gather entropy from various sources, feed it into the internal PRNG, and
@@ -34,7 +34,7 @@ uint256 GetRandHash();
3434
*
3535
* Thread-safe.
3636
*/
37-
void GetStrongRandBytes(unsigned char* buf, int num);
37+
void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
3838

3939
/**
4040
* Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG state.
@@ -78,10 +78,10 @@ class FastRandomContext {
7878
}
7979

8080
public:
81-
explicit FastRandomContext(bool fDeterministic = false);
81+
explicit FastRandomContext(bool fDeterministic = false) noexcept;
8282

8383
/** Initialize with explicit seed (only for testing) */
84-
explicit FastRandomContext(const uint256& seed);
84+
explicit FastRandomContext(const uint256& seed) noexcept;
8585

8686
// Do not permit copying a FastRandomContext (move it, or create a new one to get reseeded).
8787
FastRandomContext(const FastRandomContext&) = delete;
@@ -92,7 +92,7 @@ class FastRandomContext {
9292
FastRandomContext& operator=(FastRandomContext&& from) noexcept;
9393

9494
/** Generate a random 64-bit integer. */
95-
uint64_t rand64()
95+
uint64_t rand64() noexcept
9696
{
9797
if (bytebuf_size < 8) FillByteBuffer();
9898
uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size);
@@ -101,7 +101,7 @@ class FastRandomContext {
101101
}
102102

103103
/** Generate a random (bits)-bit integer. */
104-
uint64_t randbits(int bits) {
104+
uint64_t randbits(int bits) noexcept {
105105
if (bits == 0) {
106106
return 0;
107107
} else if (bits > 32) {
@@ -116,7 +116,7 @@ class FastRandomContext {
116116
}
117117

118118
/** Generate a random integer in the range [0..range). */
119-
uint64_t randrange(uint64_t range)
119+
uint64_t randrange(uint64_t range) noexcept
120120
{
121121
--range;
122122
int bits = CountBits(range);
@@ -130,19 +130,19 @@ class FastRandomContext {
130130
std::vector<unsigned char> randbytes(size_t len);
131131

132132
/** Generate a random 32-bit integer. */
133-
uint32_t rand32() { return randbits(32); }
133+
uint32_t rand32() noexcept { return randbits(32); }
134134

135135
/** generate a random uint256. */
136-
uint256 rand256();
136+
uint256 rand256() noexcept;
137137

138138
/** Generate a random boolean. */
139-
bool randbool() { return randbits(1); }
139+
bool randbool() noexcept { return randbits(1); }
140140

141141
// Compatibility with the C++11 UniformRandomBitGenerator concept
142142
typedef uint64_t result_type;
143143
static constexpr uint64_t min() { return 0; }
144144
static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); }
145-
inline uint64_t operator()() { return rand64(); }
145+
inline uint64_t operator()() noexcept { return rand64(); }
146146
};
147147

148148
/** More efficient than using std::shuffle on a FastRandomContext.

0 commit comments

Comments
 (0)