diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2017-02-15 17:45:22 -0800 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2017-03-29 11:26:08 -0700 |
commit | 16329224e70d0525208f6b0ba00c5e1531a4f5ea (patch) | |
tree | 8decd575cf1023486f2383e125c90085ebabd17a /src/random.h | |
parent | e04326fe6652543dc26d90eba4a48fbdc935fd0c (diff) |
Switch FastRandomContext to ChaCha20
Diffstat (limited to 'src/random.h')
-rw-r--r-- | src/random.h | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/src/random.h b/src/random.h index 82886bec59..077f58c4d9 100644 --- a/src/random.h +++ b/src/random.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_RANDOM_H #define BITCOIN_RANDOM_H +#include "crypto/chacha20.h" #include "uint256.h" #include <stdint.h> @@ -33,21 +34,68 @@ void GetStrongRandBytes(unsigned char* buf, int num); * This class is not thread-safe. */ class FastRandomContext { +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; + } + public: - explicit FastRandomContext(bool fDeterministic=false); + explicit FastRandomContext(bool fDeterministic = false); - uint32_t rand32() { - Rz = 36969 * (Rz & 65535) + (Rz >> 16); - Rw = 18000 * (Rw & 65535) + (Rw >> 16); - return (Rw << 16) + Rz; + /** 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; } - bool randbool() { - return rand32() & 1; + /** 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; + } } - uint32_t Rz; - uint32_t Rw; + /** Generate a random 32-bit integer. */ + uint32_t rand32() { return randbits(32); } + + /** Generate a random boolean. */ + bool randbool() { return randbits(1); } }; /* Number of random bytes returned by GetOSRand. |