From cab3eb10ab52021c9d9ad931803ace4e3ee4acac Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 17 Feb 2017 16:32:16 -0800 Subject: [PATCH 01/19] Introduce FastRandomContext::randbool() Cherry-picked from: c21cbe61c6249bcfca098705df6f9b4baab9f296 --- src/random.h | 4 ++++ src/wallet/wallet.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/random.h b/src/random.h index 664f030eb..367a99c7c 100644 --- a/src/random.h +++ b/src/random.h @@ -42,6 +42,10 @@ public: return (Rw << 16) + Rz; } + bool randbool() { + return rand32() & 1; + } + uint32_t Rz; uint32_t Rw; }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7b38882e6..0d59c548a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2123,7 +2123,7 @@ static void ApproximateBestSubset(vector Date: Wed, 15 Feb 2017 17:56:54 -0800 Subject: [PATCH 02/19] FastRandom benchmark Cherry-picked from: 663fbae7776b0c238f6f27d73811b4bc627d0b6b --- src/bench/crypto_hash.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 737d3572a..5257e60e8 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -7,6 +7,7 @@ #include "bench.h" #include "bloom.h" #include "hash.h" +#include "random.h" #include "uint256.h" #include "utiltime.h" #include "crypto/ripemd160.h" @@ -69,6 +70,28 @@ static void SipHash_32b(benchmark::State& state) } } +static void FastRandom_32bit(benchmark::State& state) +{ + FastRandomContext rng(true); + uint32_t x; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + x += rng.rand32(); + } + } +} + +static void FastRandom_1bit(benchmark::State& state) +{ + FastRandomContext rng(true); + uint32_t x; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + x += rng.randbool(); + } + } +} + BENCHMARK(RIPEMD160); BENCHMARK(SHA1); BENCHMARK(SHA256); @@ -76,3 +99,5 @@ BENCHMARK(SHA512); BENCHMARK(SHA256_32b); BENCHMARK(SipHash_32b); +BENCHMARK(FastRandom_32bit); +BENCHMARK(FastRandom_1bit); From e25cad001292c3cdfa9d61ccaae268b9588d57c8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 15 Feb 2017 12:29:23 -0800 Subject: [PATCH 03/19] Add ChaCha20 Cherry-picked from: e04326fe6652543dc26d90eba4a48fbdc935fd0c --- src/Makefile.am | 2 + src/crypto/chacha20.cpp | 180 ++++++++++++++++++++++++++++++++++++++ src/crypto/chacha20.h | 26 ++++++ src/test/crypto_tests.cpp | 45 ++++++++++ 4 files changed, 253 insertions(+) create mode 100644 src/crypto/chacha20.cpp create mode 100644 src/crypto/chacha20.h diff --git a/src/Makefile.am b/src/Makefile.am index 9ede7fbab..b26afc5c1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -256,6 +256,8 @@ crypto_libdogecoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libdogecoin_crypto_a_SOURCES = \ crypto/aes.cpp \ crypto/aes.h \ + crypto/chacha20.h \ + crypto/chacha20.cpp \ crypto/common.h \ crypto/hmac_sha256.cpp \ crypto/hmac_sha256.h \ diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp new file mode 100644 index 000000000..816ae870e --- /dev/null +++ b/src/crypto/chacha20.cpp @@ -0,0 +1,180 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// Based on the public domain implementation 'merged' by D. J. Bernstein +// See https://cr.yp.to/chacha.html. + +#include "crypto/common.h" +#include "crypto/chacha20.h" + +#include + +constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); } + +#define QUARTERROUND(a,b,c,d) \ + a += b; d = rotl32(d ^ a, 16); \ + c += d; b = rotl32(b ^ c, 12); \ + a += b; d = rotl32(d ^ a, 8); \ + c += d; b = rotl32(b ^ c, 7); + +static const unsigned char sigma[] = "expand 32-byte k"; +static const unsigned char tau[] = "expand 16-byte k"; + +void ChaCha20::SetKey(const unsigned char* k, size_t keylen) +{ + const unsigned char *constants; + + input[4] = ReadLE32(k + 0); + input[5] = ReadLE32(k + 4); + input[6] = ReadLE32(k + 8); + input[7] = ReadLE32(k + 12); + if (keylen == 32) { /* recommended */ + k += 16; + constants = sigma; + } else { /* keylen == 16 */ + constants = tau; + } + input[8] = ReadLE32(k + 0); + input[9] = ReadLE32(k + 4); + input[10] = ReadLE32(k + 8); + input[11] = ReadLE32(k + 12); + input[0] = ReadLE32(constants + 0); + input[1] = ReadLE32(constants + 4); + input[2] = ReadLE32(constants + 8); + input[3] = ReadLE32(constants + 12); + input[12] = 0; + input[13] = 0; + input[14] = 0; + input[15] = 0; +} + +ChaCha20::ChaCha20() +{ + memset(input, 0, sizeof(input)); +} + +ChaCha20::ChaCha20(const unsigned char* k, size_t keylen) +{ + SetKey(k, keylen); +} + +void ChaCha20::SetIV(uint64_t iv) +{ + input[14] = iv; + input[15] = iv >> 32; +} + +void ChaCha20::Seek(uint64_t pos) +{ + input[12] = pos; + input[13] = pos >> 32; +} + +void ChaCha20::Output(unsigned char* c, size_t bytes) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + unsigned char *ctarget = NULL; + unsigned char tmp[64]; + unsigned int i; + + if (!bytes) return; + + j0 = input[0]; + j1 = input[1]; + j2 = input[2]; + j3 = input[3]; + j4 = input[4]; + j5 = input[5]; + j6 = input[6]; + j7 = input[7]; + j8 = input[8]; + j9 = input[9]; + j10 = input[10]; + j11 = input[11]; + j12 = input[12]; + j13 = input[13]; + j14 = input[14]; + j15 = input[15]; + + for (;;) { + if (bytes < 64) { + ctarget = c; + c = tmp; + } + x0 = j0; + x1 = j1; + x2 = j2; + x3 = j3; + x4 = j4; + x5 = j5; + x6 = j6; + x7 = j7; + x8 = j8; + x9 = j9; + x10 = j10; + x11 = j11; + x12 = j12; + x13 = j13; + x14 = j14; + x15 = j15; + for (i = 20;i > 0;i -= 2) { + QUARTERROUND( x0, x4, x8,x12) + QUARTERROUND( x1, x5, x9,x13) + QUARTERROUND( x2, x6,x10,x14) + QUARTERROUND( x3, x7,x11,x15) + QUARTERROUND( x0, x5,x10,x15) + QUARTERROUND( x1, x6,x11,x12) + QUARTERROUND( x2, x7, x8,x13) + QUARTERROUND( x3, x4, x9,x14) + } + x0 += j0; + x1 += j1; + x2 += j2; + x3 += j3; + x4 += j4; + x5 += j5; + x6 += j6; + x7 += j7; + x8 += j8; + x9 += j9; + x10 += j10; + x11 += j11; + x12 += j12; + x13 += j13; + x14 += j14; + x15 += j15; + + ++j12; + if (!j12) ++j13; + + WriteLE32(c + 0, x0); + WriteLE32(c + 4, x1); + WriteLE32(c + 8, x2); + WriteLE32(c + 12, x3); + WriteLE32(c + 16, x4); + WriteLE32(c + 20, x5); + WriteLE32(c + 24, x6); + WriteLE32(c + 28, x7); + WriteLE32(c + 32, x8); + WriteLE32(c + 36, x9); + WriteLE32(c + 40, x10); + WriteLE32(c + 44, x11); + WriteLE32(c + 48, x12); + WriteLE32(c + 52, x13); + WriteLE32(c + 56, x14); + WriteLE32(c + 60, x15); + + if (bytes <= 64) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) ctarget[i] = c[i]; + } + input[12] = j12; + input[13] = j13; + return; + } + bytes -= 64; + c += 64; + } +} diff --git a/src/crypto/chacha20.h b/src/crypto/chacha20.h new file mode 100644 index 000000000..a305977bc --- /dev/null +++ b/src/crypto/chacha20.h @@ -0,0 +1,26 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_CHACHA20_H +#define BITCOIN_CRYPTO_CHACHA20_H + +#include +#include + +/** A PRNG class for ChaCha20. */ +class ChaCha20 +{ +private: + uint32_t input[16]; + +public: + ChaCha20(); + ChaCha20(const unsigned char* key, size_t keylen); + void SetKey(const unsigned char* key, size_t keylen); + void SetIV(uint64_t iv); + void Seek(uint64_t pos); + void Output(unsigned char* output, size_t bytes); +}; + +#endif // BITCOIN_CRYPTO_CHACHA20_H diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 4d1741717..a20182afb 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/aes.h" +#include "crypto/chacha20.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" @@ -187,6 +188,19 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad } } +void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout) +{ + std::vector key = ParseHex(hexkey); + ChaCha20 rng(key.data(), key.size()); + rng.SetIV(nonce); + rng.Seek(seek); + std::vector out = ParseHex(hexout); + std::vector outres; + outres.resize(out.size()); + rng.Output(outres.data(), outres.size()); + BOOST_CHECK(out == outres); +} + std::string LongTestString(void) { std::string ret; for (int i=0; i<200000; i++) { @@ -439,4 +453,35 @@ BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) { "b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644"); } + +BOOST_AUTO_TEST_CASE(chacha20_testvector) +{ + // Test vector from RFC 7539 + TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, + "224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cb" + "a40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a" + "832c89c167eacd901d7e2bf363"); + + // Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0, 0, + "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b" + "8f41518a11cc387b669b2ee6586"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000001", 0, 0, + "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d79" + "2b1c43fea817e9ad275ae546963"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0, + "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b52770" + "62eb7a0433e445f41e3"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 1, 0, + "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc4" + "97a0b466e7d6bbdb0041b2f586b"); + TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0, + "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3b" + "e59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc1" + "18be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5" + "a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5" + "360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78" + "fab78c9"); +} + BOOST_AUTO_TEST_SUITE_END() From f75d5ea728dd47567c9a292889319a0f2a17580c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 21 Feb 2017 17:36:37 +0100 Subject: [PATCH 04/19] util: Specific GetOSRandom for Linux/FreeBSD/OpenBSD These are available in sandboxes without access to files or devices. Also [they are safer and more straightforward](https://en.wikipedia.org/wiki/Entropy-supplying_system_calls) to use than `/dev/urandom` as reading from a file has quite a few edge cases: - Linux: `getrandom(buf, buflen, 0)`. [getrandom(2)](http://man7.org/linux/man-pages/man2/getrandom.2.html) was introduced in version 3.17 of the Linux kernel. - OpenBSD: `getentropy(buf, buflen)`. The [getentropy(2)](http://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) function appeared in OpenBSD 5.6. - FreeBSD and NetBSD: `sysctl(KERN_ARND)`. Not sure when this was added but it has existed for quite a while. Alternatives: - Linux has sysctl `CTL_KERN` / `KERN_RANDOM` / `RANDOM_UUID` which gives 16 bytes of randomness. This may be available on older kernels, however [sysctl is deprecated on Linux](https://lwn.net/Articles/605392/) and even removed in some distros so we shouldn't use it. Add tests for `GetOSRand()`: - Test that no error happens (otherwise `RandFailure()` which aborts) - Test that all 32 bytes are overwritten (initialize with zeros, try multiple times) Discussion: - When to use these? Currently they are always used when available. Another option would be to use them only when `/dev/urandom` is not available. But this would mean these code paths receive less testing, and I'm not sure there is any reason to prefer `/dev/urandom`. Closes: #9676 Cherry-picked from: 224e6eb089a0f4977d22f3803fc27e44b5e7eea5 Contains squashed commit of aa09ccbb74ea9febd83ce3362238ac5339069909 squashme: comment that NUM_OS_RANDOM_BYTES should not be changed lightly --- configure.ac | 27 +++++++++++++++++++ src/Makefile.test.include | 1 + src/random.cpp | 56 ++++++++++++++++++++++++++++++++++----- src/random.h | 12 +++++++++ src/test/random_tests.cpp | 46 ++++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 src/test/random_tests.cpp diff --git a/configure.ac b/configure.ac index e7ab4a2e6..b2c087b57 100644 --- a/configure.ac +++ b/configure.ac @@ -636,6 +636,33 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([ ] ) +# Check for different ways of gathering OS randomness +AC_MSG_CHECKING(for Linux getrandom syscall) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include + #include ]], + [[ syscall(SYS_getrandom, nullptr, 32, 0); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYS_GETRANDOM, 1,[Define this symbol if the Linux getrandom system call is available]) ], + [ AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING(for getentropy) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ getentropy(nullptr, 32) ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY, 1,[Define this symbol if the BSD getentropy system call is available]) ], + [ AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING(for sysctl KERN_ARND) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], + [[ static const int name[2] = {CTL_KERN, KERN_ARND}; + sysctl(name, 2, nullptr, nullptr, nullptr, 0); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL_ARND, 1,[Define this symbol if the BSD sysctl(KERN_ARND) is available]) ], + [ AC_MSG_RESULT(no)] +) + +# Check for reduced exports if test x$use_reduce_exports = xyes; then AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"], [AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])]) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index d0dc3af6f..a645eee66 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -113,6 +113,7 @@ BITCOIN_TESTS =\ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ test/prevector_tests.cpp \ + test/random_tests.cpp \ test/raii_event_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ diff --git a/src/random.cpp b/src/random.cpp index 6634019be..5774e9a3c 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -21,6 +21,17 @@ #include #endif +#ifdef HAVE_SYS_GETRANDOM +#include +#include +#endif +#ifdef HAVE_GETENTROPY +#include +#endif +#ifdef HAVE_SYSCTL_ARND +#include +#endif + #include #include @@ -92,32 +103,65 @@ static void RandAddSeedPerfmon() } /** Get 32 bytes of system entropy. */ -static void GetOSRand(unsigned char *ent32) +void GetOSRand(unsigned char *ent32) { -#ifdef WIN32 +#if defined(WIN32) HCRYPTPROV hProvider; int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!ret) { RandFailure(); } - ret = CryptGenRandom(hProvider, 32, ent32); + ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32); if (!ret) { RandFailure(); } CryptReleaseContext(hProvider, 0); +#elif defined(HAVE_SYS_GETRANDOM) + /* Linux. From the getrandom(2) man page: + * "If the urandom source has been initialized, reads of up to 256 bytes + * will always return as many bytes as requested and will not be + * interrupted by signals." + */ + if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) { + RandFailure(); + } +#elif defined(HAVE_GETENTROPY) + /* On OpenBSD this can return up to 256 bytes of entropy, will return an + * error if more are requested. + * The call cannot return less than the requested number of bytes. + */ + if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { + RandFailure(); + } +#elif defined(HAVE_SYSCTL_ARND) + /* FreeBSD and similar. It is possible for the call to return less + * bytes than requested, so need to read in a loop. + */ + static const int name[2] = {CTL_KERN, KERN_ARND}; + int have = 0; + do { + size_t len = NUM_OS_RANDOM_BYTES - have; + if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) { + RandFailure(); + } + have += len; + } while (have < NUM_OS_RANDOM_BYTES); #else + /* Fall back to /dev/urandom if there is no specific method implemented to + * get system entropy for this OS. + */ int f = open("/dev/urandom", O_RDONLY); if (f == -1) { RandFailure(); } int have = 0; do { - ssize_t n = read(f, ent32 + have, 32 - have); - if (n <= 0 || n + have > 32) { + ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); + if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { RandFailure(); } have += n; - } while (have < 32); + } while (have < NUM_OS_RANDOM_BYTES); close(f); #endif } diff --git a/src/random.h b/src/random.h index 367a99c7c..b0aadbc1d 100644 --- a/src/random.h +++ b/src/random.h @@ -50,4 +50,16 @@ public: uint32_t Rw; }; +/* 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). + */ +static const ssize_t NUM_OS_RANDOM_BYTES = 32; + +/** Get 32 bytes of system entropy. Do not use this in application code: use + * GetStrongRandBytes instead. + */ +void GetOSRand(unsigned char *ent32); + #endif // BITCOIN_RANDOM_H diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp new file mode 100644 index 000000000..4f67415c7 --- /dev/null +++ b/src/test/random_tests.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "random.h" + +#include "test/test_bitcoin.h" + +#include + +BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup) + +static const ssize_t MAX_TRIES = 1024; + +BOOST_AUTO_TEST_CASE(osrandom_tests) +{ + /* This does not measure the quality of randomness, but it does test that + * OSRandom() overwrites all 32 bytes of the output given a maximum + * number of tries. + */ + uint8_t data[NUM_OS_RANDOM_BYTES]; + bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ + int num_overwritten; + int tries = 0; + /* Loop until all bytes have been overwritten at least once */ + do { + memset(data, 0, NUM_OS_RANDOM_BYTES); + GetOSRand(data); + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + overwritten[x] |= (data[x] != 0); + } + + num_overwritten = 0; + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + if (overwritten[x]) { + num_overwritten += 1; + } + } + + tries += 1; + } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); + BOOST_CHECK(num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ +} + +BOOST_AUTO_TEST_SUITE_END() + From 18a8fd45062518f931af33cd16bcfbd0e93396ed Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Feb 2017 08:02:50 +0100 Subject: [PATCH 05/19] sanity: Move OS random to sanity check function Move the OS random test to a sanity check function that is called every time bitcoind is initialized. Keep `src/test/random_tests.cpp` for the case that later random tests are added, and keep a rudimentary test that just calls the sanity check. Cherry-picked from: 7cad84929907c4294f07377453aa77887911b486 --- src/init.cpp | 6 ++++++ src/random.cpp | 30 ++++++++++++++++++++++++++++++ src/random.h | 5 +++++ src/test/random_tests.cpp | 29 +---------------------------- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 760d5ef97..a39713d4a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -696,9 +696,15 @@ bool InitSanityCheck(void) InitError("Elliptic curve cryptography sanity check failure. Aborting."); return false; } + if (!glibc_sanity_test() || !glibcxx_sanity_test()) return false; + if (!Random_SanityCheck()) { + InitError("OS cryptographic RNG sanity check failure. Aborting."); + return false; + } + return true; } diff --git a/src/random.cpp b/src/random.cpp index 5774e9a3c..7fdada752 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -239,3 +239,33 @@ FastRandomContext::FastRandomContext(bool fDeterministic) } } +bool Random_SanityCheck() +{ + /* This does not measure the quality of randomness, but it does test that + * OSRandom() overwrites all 32 bytes of the output given a maximum + * number of tries. + */ + static const ssize_t MAX_TRIES = 1024; + uint8_t data[NUM_OS_RANDOM_BYTES]; + bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ + int num_overwritten; + int tries = 0; + /* Loop until all bytes have been overwritten at least once, or max number tries reached */ + do { + memset(data, 0, NUM_OS_RANDOM_BYTES); + GetOSRand(data); + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + overwritten[x] |= (data[x] != 0); + } + + num_overwritten = 0; + for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { + if (overwritten[x]) { + num_overwritten += 1; + } + } + + tries += 1; + } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); + return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ +} diff --git a/src/random.h b/src/random.h index b0aadbc1d..82886bec5 100644 --- a/src/random.h +++ b/src/random.h @@ -62,4 +62,9 @@ static const ssize_t NUM_OS_RANDOM_BYTES = 32; */ void GetOSRand(unsigned char *ent32); +/** Check that OS randomness is available and returning the requested number + * of bytes. + */ +bool Random_SanityCheck(); + #endif // BITCOIN_RANDOM_H diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 4f67415c7..d2c46c0da 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -10,36 +10,9 @@ BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup) -static const ssize_t MAX_TRIES = 1024; - BOOST_AUTO_TEST_CASE(osrandom_tests) { - /* This does not measure the quality of randomness, but it does test that - * OSRandom() overwrites all 32 bytes of the output given a maximum - * number of tries. - */ - uint8_t data[NUM_OS_RANDOM_BYTES]; - bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ - int num_overwritten; - int tries = 0; - /* Loop until all bytes have been overwritten at least once */ - do { - memset(data, 0, NUM_OS_RANDOM_BYTES); - GetOSRand(data); - for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { - overwritten[x] |= (data[x] != 0); - } - - num_overwritten = 0; - for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { - if (overwritten[x]) { - num_overwritten += 1; - } - } - - tries += 1; - } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); - BOOST_CHECK(num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ + BOOST_CHECK(Random_SanityCheck()); } BOOST_AUTO_TEST_SUITE_END() From 74888ca56788b958e2386dbe0dab869e6c201a31 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Feb 2017 08:51:26 +0100 Subject: [PATCH 06/19] random: Add fallback if getrandom syscall not available If the code was compiled with newer (>=3.17) kernel headers but executed on a system without the system call, every use of random would crash the program. Add a fallback for that case. Cherry-picked from: 7e6dcd9995b99e894b8017f09016c405b066ca36 --- src/random.cpp | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 7fdada752..8284f457c 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -102,6 +102,28 @@ static void RandAddSeedPerfmon() #endif } +#ifndef WIN32 +/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most + * compatible way to get cryptographic randomness on UNIX-ish platforms. + */ +void GetDevURandom(unsigned char *ent32) +{ + int f = open("/dev/urandom", O_RDONLY); + if (f == -1) { + RandFailure(); + } + int have = 0; + do { + ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); + if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { + RandFailure(); + } + have += n; + } while (have < NUM_OS_RANDOM_BYTES); + close(f); +} +#endif + /** Get 32 bytes of system entropy. */ void GetOSRand(unsigned char *ent32) { @@ -122,8 +144,17 @@ void GetOSRand(unsigned char *ent32) * will always return as many bytes as requested and will not be * interrupted by signals." */ - if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) { - RandFailure(); + int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0); + if (rv != NUM_OS_RANDOM_BYTES) { + if (rv < 0 && errno == ENOSYS) { + /* Fallback for kernel <3.17: the return value will be -1 and errno + * ENOSYS if the syscall is not available, in that case fall back + * to /dev/urandom. + */ + GetDevURandom(ent32); + } else { + RandFailure(); + } } #elif defined(HAVE_GETENTROPY) /* On OpenBSD this can return up to 256 bytes of entropy, will return an @@ -150,19 +181,7 @@ void GetOSRand(unsigned char *ent32) /* Fall back to /dev/urandom if there is no specific method implemented to * get system entropy for this OS. */ - int f = open("/dev/urandom", O_RDONLY); - if (f == -1) { - RandFailure(); - } - int have = 0; - do { - ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); - if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { - RandFailure(); - } - have += n; - } while (have < NUM_OS_RANDOM_BYTES); - close(f); + GetDevURandom(ent32); #endif } From b2dc5e349b0086f7c3c82ded1a70ca0abc67ddea Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 15 Feb 2017 17:45:22 -0800 Subject: [PATCH 07/19] Switch FastRandomContext to ChaCha20 Cherry-picked from: 16329224e70d0525208f6b0ba00c5e1531a4f5ea --- src/Makefile.test.include | 2 +- src/addrman.cpp | 8 ++--- src/addrman.h | 11 ++++-- src/random.cpp | 33 ++++++++++-------- src/random.h | 66 +++++++++++++++++++++++++++++++----- src/test/addrman_tests.cpp | 9 ++--- src/test/prevector_tests.cpp | 8 ++--- src/test/random_tests.cpp | 21 +++++++++++- src/test/test_bitcoin.cpp | 3 +- src/test/test_random.h | 8 ++++- 10 files changed, 126 insertions(+), 43 deletions(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index a645eee66..39aba1e3b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -113,8 +113,8 @@ BITCOIN_TESTS =\ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ test/prevector_tests.cpp \ - test/random_tests.cpp \ test/raii_event_tests.cpp \ + test/random_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ diff --git a/src/addrman.cpp b/src/addrman.cpp index b6ab4c630..33a623c1f 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -351,8 +351,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { - nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT; - nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; + nKBucket = (nKBucket + insecure_rand.randbits(ADDRMAN_TRIED_BUCKET_COUNT_LOG2)) % ADDRMAN_TRIED_BUCKET_COUNT; + nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE; } int nId = vvTried[nKBucket][nKBucketPos]; assert(mapInfo.count(nId) == 1); @@ -368,8 +368,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { - nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT; - nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; + nUBucket = (nUBucket + insecure_rand.randbits(ADDRMAN_NEW_BUCKET_COUNT_LOG2)) % ADDRMAN_NEW_BUCKET_COUNT; + nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE; } int nId = vvNew[nUBucket][nUBucketPos]; assert(mapInfo.count(nId) == 1); diff --git a/src/addrman.h b/src/addrman.h index 6e5f946bf..bb45ac91e 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -136,13 +136,13 @@ public: */ //! total number of buckets for tried addresses -#define ADDRMAN_TRIED_BUCKET_COUNT 256 +#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8 //! total number of buckets for new addresses -#define ADDRMAN_NEW_BUCKET_COUNT 1024 +#define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10 //! maximum allowed number of entries in buckets for new and tried addresses -#define ADDRMAN_BUCKET_SIZE 64 +#define ADDRMAN_BUCKET_SIZE_LOG2 6 //! over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8 @@ -171,6 +171,11 @@ public: //! the maximum number of nodes to return in a getaddr call #define ADDRMAN_GETADDR_MAX 2500 +//! Convenience +#define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2) +#define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2) +#define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2) + /** * Stochastical (IP) address manager */ diff --git a/src/random.cpp b/src/random.cpp index 8284f457c..c1e313cbd 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -240,22 +240,16 @@ uint256 GetRandHash() return hash; } -FastRandomContext::FastRandomContext(bool fDeterministic) +void FastRandomContext::RandomSeed() { - // The seed values have some unlikely fixed points which we avoid. - if (fDeterministic) { - Rz = Rw = 11; - } else { - uint32_t tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while (tmp == 0 || tmp == 0x9068ffffU); - Rz = tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while (tmp == 0 || tmp == 0x464fffffU); - Rw = tmp; - } + uint256 seed = GetRandHash(); + rng.SetKey(seed.begin(), 32); + requires_seed = false; +} + +FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) +{ + rng.SetKey(seed.begin(), 32); } bool Random_SanityCheck() @@ -288,3 +282,12 @@ bool Random_SanityCheck() } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ } + +FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) +{ + if (!fDeterministic) { + return; + } + uint256 seed; + rng.SetKey(seed.begin(), 32); +} diff --git a/src/random.h b/src/random.h index 82886bec5..077f58c4d 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 @@ -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. diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 541e4283e..af5871a21 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -195,10 +195,11 @@ BOOST_AUTO_TEST_CASE(addrman_select) BOOST_CHECK(addrman.size() == 7); // Test 12: Select pulls from new and tried regardless of port number. - BOOST_CHECK(addrman.Select().ToString() == "250.4.6.6:8333"); - BOOST_CHECK(addrman.Select().ToString() == "250.3.2.2:9999"); - BOOST_CHECK(addrman.Select().ToString() == "250.3.3.3:9999"); - BOOST_CHECK(addrman.Select().ToString() == "250.4.4.4:8333"); + std::set ports; + for (int i = 0; i < 20; ++i) { + ports.insert(addrman.Select().GetPort()); + } + BOOST_CHECK_EQUAL(ports.size(), 3); } BOOST_AUTO_TEST_CASE(addrman_new_collisions) diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index bd8a7819a..cfed5e347 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -28,6 +28,7 @@ class prevector_tester { typedef typename pretype::size_type Size; bool passed = true; FastRandomContext rand_cache; + uint256 rand_seed; template @@ -183,13 +184,12 @@ public: } ~prevector_tester() { - BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: " - << rand_cache.Rz - << ", insecure_rand_Rw: " - << rand_cache.Rw); + BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString()); } + prevector_tester() { seed_insecure_rand(); + rand_seed = insecure_rand_seed; rand_cache = insecure_rand_ctx; } }; diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index d2c46c0da..31b993cd3 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -15,5 +15,24 @@ BOOST_AUTO_TEST_CASE(osrandom_tests) BOOST_CHECK(Random_SanityCheck()); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_CASE(fastrandom_tests) +{ + // Check that deterministic FastRandomContexts are deterministic + FastRandomContext ctx1(true); + FastRandomContext ctx2(true); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); + BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + + // Check that a nondeterministic ones are not + FastRandomContext ctx3; + FastRandomContext ctx4; + BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 9ec06ab8d..8a88e8a37 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -32,7 +32,8 @@ #include std::unique_ptr g_connman; -FastRandomContext insecure_rand_ctx(true); +uint256 insecure_rand_seed = GetRandHash(); +FastRandomContext insecure_rand_ctx(insecure_rand_seed); extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/test/test_random.h b/src/test/test_random.h index 4a1637ac7..318c44df4 100644 --- a/src/test/test_random.h +++ b/src/test/test_random.h @@ -8,11 +8,17 @@ #include "random.h" +extern uint256 insecure_rand_seed; extern FastRandomContext insecure_rand_ctx; static inline void seed_insecure_rand(bool fDeterministic = false) { - insecure_rand_ctx = FastRandomContext(fDeterministic); + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); } static inline uint32_t insecure_rand(void) From 3f511675be9c9095283bad0c1d539cbc54c4ef74 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 25 Feb 2017 12:16:58 -0800 Subject: [PATCH 08/19] Add a FastRandomContext::randrange and use it Cherry-picked from: 4fd2d2fc97e21efceab849576e544160fd5e3e3d --- configure.ac | 2 ++ src/bench/checkqueue.cpp | 2 +- src/crypto/common.h | 21 +++++++++++++++++++++ src/net.h | 2 +- src/random.h | 12 ++++++++++++ src/test/crypto_tests.cpp | 23 +++++++++++++++++++++++ src/test/random_tests.cpp | 15 +++++++++++++++ 7 files changed, 75 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b2c087b57..f0c9926d6 100644 --- a/configure.ac +++ b/configure.ac @@ -603,6 +603,8 @@ AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,, #include #endif]) +AC_CHECK_DECLS([__builtin_clz, __builtin_clzl, __builtin_clzll]) + dnl Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 6fa9fe4fe..88a2a570f 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -68,7 +68,7 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::State& state) PrevectorJob(){ } PrevectorJob(FastRandomContext& insecure_rand){ - p.resize(insecure_rand.rand32() % (PREVECTOR_SIZE*2)); + p.resize(insecure_rand.randrange(PREVECTOR_SIZE*2)); } bool operator()() { diff --git a/src/crypto/common.h b/src/crypto/common.h index 4a9d1150b..bcca3d30e 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -79,4 +79,25 @@ void static inline WriteBE64(unsigned char* ptr, uint64_t x) memcpy(ptr, (char*)&v, 8); } +/** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ +uint64_t static inline CountBits(uint64_t x) +{ +#ifdef HAVE_DECL___BUILTIN_CLZL + if (sizeof(unsigned long) >= sizeof(uint64_t)) { + return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; + } +#endif +#ifdef HAVE_DECL___BUILTIN_CLZLL + if (sizeof(unsigned long long) >= sizeof(uint64_t)) { + return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; + } +#endif + int ret = 0; + while (x) { + x >>= 1; + ++ret; + } + return ret; +} + #endif // BITCOIN_CRYPTO_COMMON_H diff --git a/src/net.h b/src/net.h index e7ad38925..17afaab74 100644 --- a/src/net.h +++ b/src/net.h @@ -778,7 +778,7 @@ public: // after addresses were pushed. if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand.rand32() % vAddrToSend.size()] = _addr; + vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr; } else { vAddrToSend.push_back(_addr); } diff --git a/src/random.h b/src/random.h index 077f58c4d..9551e1c46 100644 --- a/src/random.h +++ b/src/random.h @@ -7,6 +7,7 @@ #define BITCOIN_RANDOM_H #include "crypto/chacha20.h" +#include "crypto/common.h" #include "uint256.h" #include @@ -91,6 +92,17 @@ public: } } + /** 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; + } + } + /** Generate a random 32-bit integer. */ uint32_t rand32() { return randbits(32); } diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index a20182afb..72e562808 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -10,6 +10,7 @@ #include "crypto/sha512.h" #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" +#include "random.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" #include "test/test_random.h" @@ -484,4 +485,26 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector) "fab78c9"); } +BOOST_AUTO_TEST_CASE(countbits_tests) +{ + FastRandomContext ctx; + for (int i = 0; i <= 64; ++i) { + if (i == 0) { + // Check handling of zero. + BOOST_CHECK_EQUAL(CountBits(0), 0); + } else if (i < 10) { + for (uint64_t j = 1 << (i - 1); (j >> i) == 0; ++j) { + // Exhaustively test up to 10 bits + BOOST_CHECK_EQUAL(CountBits(j), i); + } + } else { + for (int k = 0; k < 1000; k++) { + // Randomly test 1000 samples of each length above 10 bits. + uint64_t j = ((uint64_t)1) << (i - 1) | ctx.randbits(i - 1); + BOOST_CHECK_EQUAL(CountBits(j), i); + } + } + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 31b993cd3..859673422 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -35,4 +35,19 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal } +BOOST_AUTO_TEST_CASE(fastrandom_randbits) +{ + FastRandomContext ctx1; + FastRandomContext ctx2; + for (int bits = 0; bits < 63; ++bits) { + for (int j = 0; j < 1000; ++j) { + uint64_t rangebits = ctx1.randbits(bits); + BOOST_CHECK_EQUAL(rangebits >> bits, 0); + uint64_t range = ((uint64_t)1) << bits | rangebits; + uint64_t rand = ctx2.randrange(range); + BOOST_CHECK(rand < range); + } + } +} + BOOST_AUTO_TEST_SUITE_END() From a8cad7ed4c15b2d0e6d2416d3b93e860e03cfc62 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Mar 2024 14:31:48 -0700 Subject: [PATCH 09/19] Add FastRandomContext::rand256() and ::randbytes() FastRandomContext now provides all functionality that the real Rand* functions provide. Cherry-picked from: 37e864eb9fee4b592bd61c5ec3555b00a2de2cf7 --- src/random.cpp | 20 ++++++++++++++++++++ src/random.h | 6 ++++++ src/test/cuckoocache_tests.cpp | 24 ++++++++++++------------ src/test/random_tests.cpp | 7 +++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index c1e313cbd..0e8f83dd8 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -247,6 +247,26 @@ void FastRandomContext::RandomSeed() requires_seed = false; } +uint256 FastRandomContext::rand256() +{ + if (bytebuf_size < 32) { + FillByteBuffer(); + } + uint256 ret; + memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32); + bytebuf_size -= 32; + return ret; +} + +std::vector FastRandomContext::randbytes(size_t len) +{ + std::vector ret(len); + if (len > 0) { + rng.Output(&ret[0], len); + } + return ret; +} + FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) { rng.SetKey(seed.begin(), 32); diff --git a/src/random.h b/src/random.h index 9551e1c46..f8e2e0dc5 100644 --- a/src/random.h +++ b/src/random.h @@ -103,9 +103,15 @@ public: } } + /** Generate random bytes. */ + std::vector randbytes(size_t len); + /** Generate a random 32-bit integer. */ uint32_t rand32() { return randbits(32); } + /** generate a random uint256. */ + uint256 rand256(); + /** Generate a random boolean. */ bool randbool() { return randbits(1); } }; diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 6004b25aa..916b23cee 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -24,18 +24,18 @@ * using BOOST_CHECK_CLOSE to fail. * */ -FastRandomContext insecure_rand(true); +FastRandomContext local_rand_ctx(true); BOOST_AUTO_TEST_SUITE(cuckoocache_tests); -/** insecure_GetRandHash fills in a uint256 from insecure_rand +/** insecure_GetRandHash fills in a uint256 from local_rand_ctx */ void insecure_GetRandHash(uint256& t) { uint32_t* ptr = (uint32_t*)t.begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** Definition copied from /src/script/sigcache.cpp @@ -60,7 +60,7 @@ public: */ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); CuckooCache::cache cc{}; cc.setup_bytes(32 << 20); uint256 v; @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) template double test_cache(size_t megabytes, double load) { - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -90,7 +90,7 @@ double test_cache(size_t megabytes, double load) for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)hashes[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -151,7 +151,7 @@ template void test_cache_erase(size_t megabytes) { double load = 1; - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -161,7 +161,7 @@ void test_cache_erase(size_t megabytes) for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)hashes[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -214,7 +214,7 @@ template void test_cache_erase_parallel(size_t megabytes) { double load = 1; - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -224,7 +224,7 @@ void test_cache_erase_parallel(size_t megabytes) for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)hashes[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -316,7 +316,7 @@ void test_cache_generations() // iterations with non-deterministic values, so it isn't "overfit" to the // specific entropy in FastRandomContext(true) and implementation of the // cache. - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); // block_activity models a chunk of network activity. n_insert elements are // adde to the cache. The first and last n/4 are stored for removal later @@ -333,7 +333,7 @@ void test_cache_generations() for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)inserts[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } for (uint32_t i = 0; i < n_insert / 4; ++i) reads.push_back(inserts[i]); diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 859673422..132e19005 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -25,14 +25,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128)); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); + BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50)); // Check that a nondeterministic ones are not FastRandomContext ctx3; FastRandomContext ctx4; BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal + BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); + BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); } BOOST_AUTO_TEST_CASE(fastrandom_randbits) From 9feb51fe9d1e458ea344ae8c94ce93ba0028ae72 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 26 Mar 2024 16:09:38 -0700 Subject: [PATCH 10/19] Merge test_random.h into test_bitcoin.h Cherry-picked from: 124d13a58cdcd9f66eeffc7e6281e3eb129e3398 --- src/Makefile.test.include | 1 - src/test/coins_tests.cpp | 1 - src/test/crypto_tests.cpp | 1 - src/test/merkle_tests.cpp | 1 - src/test/pmt_tests.cpp | 1 - src/test/prevector_tests.cpp | 1 - src/test/sighash_tests.cpp | 1 - src/test/skiplist_tests.cpp | 1 - src/test/test_bitcoin.h | 19 +++++++++++++++++++ src/test/test_random.h | 29 ----------------------------- src/test/util_tests.cpp | 1 - src/test/versionbits_tests.cpp | 1 - src/wallet/test/crypto_tests.cpp | 3 +-- 13 files changed, 20 insertions(+), 41 deletions(-) delete mode 100644 src/test/test_random.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 39aba1e3b..d33af3911 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -130,7 +130,6 @@ BITCOIN_TESTS =\ test/streams_tests.cpp \ test/test_bitcoin.cpp \ test/test_bitcoin.h \ - test/test_random.h \ test/testutil.cpp \ test/testutil.h \ test/timedata_tests.cpp \ diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 42f133b74..ae85a1eda 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -8,7 +8,6 @@ #include "undo.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include "validation.h" #include "consensus/validation.h" diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 72e562808..4b76cc102 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -13,7 +13,6 @@ #include "random.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index af02d67f7..2db510d6d 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -4,7 +4,6 @@ #include "consensus/merkle.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index a1cb32019..e3a4f90aa 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -10,7 +10,6 @@ #include "arith_uint256.h" #include "version.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index cfed5e347..45bcac683 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -9,7 +9,6 @@ #include "streams.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 5279cb243..34069af45 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -11,7 +11,6 @@ #include "serialize.h" #include "streams.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include "util.h" #include "utilstrencodings.h" #include "version.h" diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 0b2fe0ef9..9e09533b9 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -5,7 +5,6 @@ #include "chain.h" #include "util.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 96f477319..b0cf19940 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -9,11 +9,30 @@ #include "fs.h" #include "key.h" #include "pubkey.h" +#include "random.h" #include "txdb.h" #include "txmempool.h" #include +extern uint256 insecure_rand_seed; +extern FastRandomContext insecure_rand_ctx; + +static inline void seed_insecure_rand(bool fDeterministic = false) +{ + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); +} + +static inline uint32_t insecure_rand(void) +{ + return insecure_rand_ctx.rand32(); +} + /** Basic testing setup. * This just configures logging and chain parameters. */ diff --git a/src/test/test_random.h b/src/test/test_random.h deleted file mode 100644 index 318c44df4..000000000 --- a/src/test/test_random.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_TEST_RANDOM_H -#define BITCOIN_TEST_RANDOM_H - -#include "random.h" - -extern uint256 insecure_rand_seed; -extern FastRandomContext insecure_rand_ctx; - -static inline void seed_insecure_rand(bool fDeterministic = false) -{ - if (fDeterministic) { - insecure_rand_seed = uint256(); - } else { - insecure_rand_seed = GetRandHash(); - } - insecure_rand_ctx = FastRandomContext(insecure_rand_seed); -} - -static inline uint32_t insecure_rand(void) -{ - return insecure_rand_ctx.rand32(); -} - -#endif diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 641655621..89f7025d0 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -10,7 +10,6 @@ #include "utilstrencodings.h" #include "utilmoneystr.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include #include diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 96d6845fc..10d2345bd 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -6,7 +6,6 @@ #include "chain.h" #include "versionbits.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include "chainparams.h" #include "validation.h" #include "consensus/params.h" diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index 2251d886f..eec916c9d 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -2,9 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "test/test_random.h" -#include "utilstrencodings.h" #include "test/test_bitcoin.h" +#include "utilstrencodings.h" #include "wallet/crypter.h" #include From 2ee602e3ce2de467959f308e4794e32f7581d852 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 15:00:46 -0700 Subject: [PATCH 11/19] Add various insecure_rand wrappers for tests Cherry-picked from: 1119927df03c94f9306e4d92f55d147b900522fb --- src/test/test_bitcoin.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index b0cf19940..eecd8635e 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -28,10 +28,12 @@ static inline void seed_insecure_rand(bool fDeterministic = false) insecure_rand_ctx = FastRandomContext(insecure_rand_seed); } -static inline uint32_t insecure_rand(void) -{ - return insecure_rand_ctx.rand32(); -} +static inline uint32_t insecure_rand() { return insecure_rand_ctx.rand32(); } +static inline uint256 insecure_rand256() { return insecure_rand_ctx.rand256(); } +static inline uint64_t insecure_randbits(int bits) { return insecure_rand_ctx.randbits(bits); } +static inline uint64_t insecure_randrange(uint64_t range) { return insecure_rand_ctx.randrange(range); } +static inline bool insecure_randbool() { return insecure_rand_ctx.randbool(); } +static inline std::vector insecure_randbytes(size_t len) { return insecure_rand_ctx.randbytes(len); } /** Basic testing setup. * This just configures logging and chain parameters. From fe5b7016347873d5ce963aee334b84cdcfa34f48 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Mar 2024 14:32:26 -0700 Subject: [PATCH 12/19] scripted-diff: use insecure_rand256/randrange more -BEGIN VERIFY SCRIPT- sed -i "s/\::iterator it; - it = mapOrphanTransactions.lower_bound(GetRandHash()); + it = mapOrphanTransactions.lower_bound(insecure_rand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = insecure_rand256(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 6d8e59bc4..4789152b5 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -30,16 +30,16 @@ static CBlock BuildBlockTestCase() { block.vtx.resize(3); block.vtx[0] = MakeTransactionRef(tx); block.nVersion = 1; - block.hashPrevBlock = GetRandHash(); + block.hashPrevBlock = insecure_rand256(); block.nBits = 0x207fffff; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = insecure_rand256(); tx.vin[0].prevout.n = 0; block.vtx[1] = MakeTransactionRef(tx); tx.vin.resize(10); for (size_t i = 0; i < tx.vin.size(); i++) { - tx.vin[i].prevout.hash = GetRandHash(); + tx.vin[i].prevout.hash = insecure_rand256(); tx.vin[i].prevout.n = 0; } block.vtx[2] = MakeTransactionRef(tx); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(std::move(coinbase)); block.nVersion = 1; - block.hashPrevBlock = GetRandHash(); + block.hashPrevBlock = insecure_rand256(); block.nBits = 0x207fffff; bool mutated; @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BlockTransactionsRequest req1; - req1.blockhash = GetRandHash(); + req1.blockhash = insecure_rand256(); req1.indexes.resize(4); req1.indexes[0] = 0; req1.indexes[1] = 1; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 4da07c12f..5f3b21ca9 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -463,7 +463,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none) static std::vector RandomData() { - uint256 r = GetRandHash(); + uint256 r = insecure_rand256(); return std::vector(r.begin(), r.end()); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index af134ad31..2e7a4d1a5 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -160,7 +160,7 @@ void Correct_Queue_range(std::vector range) FakeCheckCheckCompletion::n_calls = 0; CCheckQueueControl control(small_queue.get()); while (total) { - vChecks.resize(std::min(total, (size_t) GetRand(10))); + vChecks.resize(std::min(total, (size_t) insecure_randrange(10))); total -= vChecks.size(); control.Add(vChecks); } @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) { std::vector range; range.reserve(100000/1000); - for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)GetRand(std::min((size_t)1000, ((size_t)100000) - i)))) + for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)insecure_randrange(std::min((size_t)1000, ((size_t)100000) - i)))) range.push_back(i); Correct_Queue_range(range); } @@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) CCheckQueueControl control(fail_queue.get()); size_t remaining = i; while (remaining) { - size_t r = GetRand(10); + size_t r = insecure_randrange(10); std::vector vChecks; vChecks.reserve(r); @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { CCheckQueueControl control(queue.get()); while (total) { - size_t r = GetRand(10); + size_t r = insecure_randrange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) vChecks.emplace_back(--total); @@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { CCheckQueueControl control(queue.get()); while (total) { - size_t r = GetRand(10); + size_t r = insecure_randrange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) { total--; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index ae85a1eda..379a597b3 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -34,7 +34,7 @@ public: return false; } coins = it->second; - if (coins.IsPruned() && insecure_rand() % 2 == 0) { + if (coins.IsPruned() && insecure_randrange(2) == 0) { // Randomly return false in case of an empty entry. return false; } @@ -55,7 +55,7 @@ public: if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Same optimization used in CCoinsViewDB is to only write dirty entries. map_[it->first] = it->second.coins; - if (it->second.coins.IsPruned() && insecure_rand() % 3 == 0) { + if (it->second.coins.IsPruned() && insecure_randrange(3) == 0) { // Randomly delete empty entries on write. map_.erase(it->first); } @@ -125,7 +125,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) std::vector txids; txids.resize(NUM_SIMULATION_ITERATIONS / 8); for (unsigned int i = 0; i < txids.size(); i++) { - txids[i] = GetRandHash(); + txids[i] = insecure_rand256(); } for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); BOOST_CHECK(coins == *entry); - if (insecure_rand() % 5 == 0 || coins.IsPruned()) { + if (insecure_randrange(5) == 0 || coins.IsPruned()) { if (coins.IsPruned()) { added_an_entry = true; } else { @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { @@ -169,22 +169,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } } - if (insecure_rand() % 100 == 0) { + if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_rand() % 2 == 0) { + if (stack.size() > 1 && insecure_randrange(2) == 0) { unsigned int flushIndex = insecure_rand() % (stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_rand() % 100 == 0) { + if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && insecure_randrange(2) == 0) { //Remove the top cache stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { //Add a new cache CCoinsView* tip = &base; if (stack.size() > 0) { @@ -222,7 +222,7 @@ std::map alltxs; TxData &FindRandomFrom(const std::set &txidset) { assert(txidset.size()); - std::set::iterator txIt = txidset.lower_bound(GetRandHash()); + std::set::iterator txIt = txidset.lower_bound(insecure_rand256()); if (txIt == txidset.end()) { txIt = txidset.begin(); } @@ -269,7 +269,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // 2/20 times create a new coinbase if (randiter % 20 < 2 || coinbaseids.size() < 10) { // 1/10 of those times create a duplicate coinbase - if (insecure_rand() % 10 == 0 && coinbaseids.size()) { + if (insecure_randrange(10) == 0 && coinbaseids.size()) { TxData &txd = FindRandomFrom(coinbaseids); // Reuse the exact same coinbase tx = std::get<0>(txd); @@ -384,7 +384,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { @@ -395,21 +395,21 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } } - if (insecure_rand() % 100 == 0) { + if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_rand() % 2 == 0) { + if (stack.size() > 1 && insecure_randrange(2) == 0) { unsigned int flushIndex = insecure_rand() % (stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_rand() % 100 == 0) { + if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && insecure_randrange(2) == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 9b25a58d5..2380ee202 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = insecure_rand256(); uint256 res; // Ensure that we're doing real obfuscation when obfuscate=true @@ -55,11 +55,11 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; - uint256 in = GetRandHash(); + uint256 in = insecure_rand256(); char key2 = 'j'; - uint256 in2 = GetRandHash(); + uint256 in2 = insecure_rand256(); char key3 = 'k'; - uint256 in3 = GetRandHash(); + uint256 in3 = insecure_rand256(); uint256 res; CDBBatch batch(dbw); @@ -93,10 +93,10 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) // The two keys are intentionally chosen for ordering char key = 'j'; - uint256 in = GetRandHash(); + uint256 in = insecure_rand256(); BOOST_CHECK(dbw.Write(key, in)); char key2 = 'k'; - uint256 in2 = GetRandHash(); + uint256 in2 = insecure_rand256(); BOOST_CHECK(dbw.Write(key2, in2)); std::unique_ptr it(const_cast(&dbw)->NewIterator()); @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = insecure_rand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string - uint256 in2 = GetRandHash(); + uint256 in2 = insecure_rand256(); uint256 res3; // Check that we can write successfully @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = insecure_rand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_CHECK(!odbw.Read(key, res2)); BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); - uint256 in2 = GetRandHash(); + uint256 in2 = insecure_rand256(); uint256 res3; // Check that we can write successfully diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 2db510d6d..011e7217c 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) { for (int i = 0; i < 32; i++) { // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes. - int ntx = (i <= 16) ? i : 17 + (insecure_rand() % 4000); + int ntx = (i <= 16) ? i : 17 + (insecure_randrange(4000)); // Try up to 3 mutations. for (int mutate = 0; mutate <= 3; mutate++) { int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first. diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 2f55b4986..77eded091 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (chainActive.Tip()->nHeight < 209999) { CBlockIndex* prev = chainActive.Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(GetRandHash()); + next->phashBlock = new uint256(insecure_rand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; @@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (chainActive.Tip()->nHeight < 210000) { CBlockIndex* prev = chainActive.Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(GetRandHash()); + next->phashBlock = new uint256(insecure_rand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index e3a4f90aa..3572505af 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -22,7 +22,7 @@ public: // flip one bit in one of the hashes - this should break the authentication void Damage() { unsigned int n = insecure_rand() % vHash.size(); - int bit = insecure_rand() % 256; + int bit = insecure_randrange(256); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } }; diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index cff396673..d881edbd7 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -86,9 +86,9 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) } for (int j = 0; j < 1000; j++) { - CBlockIndex *p1 = &blocks[GetRand(10000)]; - CBlockIndex *p2 = &blocks[GetRand(10000)]; - CBlockIndex *p3 = &blocks[GetRand(10000)]; + CBlockIndex *p1 = &blocks[insecure_randrange(10000)]; + CBlockIndex *p2 = &blocks[insecure_randrange(10000)]; + CBlockIndex *p3 = &blocks[insecure_randrange(10000)]; int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params); BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime()); diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 45bcac683..28f72a9b9 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -206,14 +206,14 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) test.erase(insecure_rand() % test.size()); } if (((r >> 4) % 8) == 2) { - int new_size = std::max(0, std::min(30, test.size() + (insecure_rand() % 5) - 2)); + int new_size = std::max(0, std::min(30, test.size() + (insecure_randrange(5)) - 2)); test.resize(new_size); } if (((r >> 7) % 8) == 3) { - test.insert(insecure_rand() % (test.size() + 1), 1 + (insecure_rand() % 2), insecure_rand()); + test.insert(insecure_rand() % (test.size() + 1), 1 + (insecure_randrange(2)), insecure_rand()); } if (((r >> 10) % 8) == 4) { - int del = std::min(test.size(), 1 + (insecure_rand() % 2)); + int del = std::min(test.size(), 1 + (insecure_randrange(2))); int beg = insecure_rand() % (test.size() + 1 - del); test.erase(beg, beg + del); } @@ -225,20 +225,20 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) } if (((r >> 21) % 32) == 7) { int values[4]; - int num = 1 + (insecure_rand() % 4); + int num = 1 + (insecure_randrange(4)); for (int k = 0; k < num; k++) { values[k] = insecure_rand(); } test.insert_range(insecure_rand() % (test.size() + 1), values, values + num); } if (((r >> 26) % 32) == 8) { - int del = std::min(test.size(), 1 + (insecure_rand() % 4)); + int del = std::min(test.size(), 1 + (insecure_randrange(4))); int beg = insecure_rand() % (test.size() + 1 - del); test.erase(beg, beg + del); } r = insecure_rand(); if (r % 32 == 9) { - test.reserve(insecure_rand() % 32); + test.reserve(insecure_randrange(32)); } if ((r >> 5) % 64 == 10) { test.shrink_to_fit(); @@ -250,7 +250,7 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) test.clear(); } if (((r >> 21) % 512) == 12) { - test.assign(insecure_rand() % 32, insecure_rand()); + test.assign(insecure_randrange(32), insecure_rand()); } if (((r >> 15) % 8) == 3) { test.swap(); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 34069af45..03a7d9ca6 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -89,7 +89,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un void static RandomScript(CScript &script) { static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR}; script = CScript(); - int ops = (insecure_rand() % 10); + int ops = (insecure_randrange(10)); for (int i=0; i Date: Wed, 7 Jun 2017 11:34:55 -0700 Subject: [PATCH 13/19] Replace more rand() % NUM by randranges Cherry-picked from: 3ecabae36364e905e7821fba3e60aa7f8418de6c --- src/test/coins_tests.cpp | 6 +++--- src/test/crypto_tests.cpp | 2 +- src/test/merkle_tests.cpp | 2 +- src/test/pmt_tests.cpp | 2 +- src/test/prevector_tests.cpp | 14 +++++++------- src/test/sighash_tests.cpp | 4 ++-- src/test/skiplist_tests.cpp | 8 ++++---- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 379a597b3..fddd0dfe2 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { // Do a random modification. { - uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. + uint256 txid = txids[insecure_randrange(500) % txids.size()]; // txid we're going to modify in this iteration. CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); BOOST_CHECK(coins == *entry); @@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache if (stack.size() > 1 && insecure_randrange(2) == 0) { - unsigned int flushIndex = insecure_rand() % (stack.size() - 1); + unsigned int flushIndex = insecure_randrange(stack.size() - 1); stack[flushIndex]->Flush(); } } @@ -398,7 +398,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache if (stack.size() > 1 && insecure_randrange(2) == 0) { - unsigned int flushIndex = insecure_rand() % (stack.size() - 1); + unsigned int flushIndex = insecure_randrange(stack.size() - 1); stack[flushIndex]->Flush(); } } diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 4b76cc102..ab3e6fc1f 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -38,7 +38,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { - size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); + size_t len = insecure_randrange((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 011e7217c..118f2a66a 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) // If ntx <= 16, try all branches. Otherise, try 16 random ones. int mtx = loop; if (ntx > 16) { - mtx = insecure_rand() % ntx; + mtx = insecure_randrange(ntx); } std::vector newBranch = BlockMerkleBranch(block, mtx); std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 3572505af..d07a9f395 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -21,7 +21,7 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree public: // flip one bit in one of the hashes - this should break the authentication void Damage() { - unsigned int n = insecure_rand() % vHash.size(); + unsigned int n = insecure_randrange(vHash.size()); int bit = insecure_randrange(256); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 28f72a9b9..d951a6c3c 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -200,21 +200,21 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) for (int i = 0; i < 2048; i++) { int r = insecure_rand(); if ((r % 4) == 0) { - test.insert(insecure_rand() % (test.size() + 1), insecure_rand()); + test.insert(insecure_randrange(test.size() + 1), insecure_rand()); } if (test.size() > 0 && ((r >> 2) % 4) == 1) { - test.erase(insecure_rand() % test.size()); + test.erase(insecure_randrange(test.size())); } if (((r >> 4) % 8) == 2) { int new_size = std::max(0, std::min(30, test.size() + (insecure_randrange(5)) - 2)); test.resize(new_size); } if (((r >> 7) % 8) == 3) { - test.insert(insecure_rand() % (test.size() + 1), 1 + (insecure_randrange(2)), insecure_rand()); + test.insert(insecure_randrange(test.size() + 1), 1 + insecure_randrange(2), insecure_rand()); } if (((r >> 10) % 8) == 4) { int del = std::min(test.size(), 1 + (insecure_randrange(2))); - int beg = insecure_rand() % (test.size() + 1 - del); + int beg = insecure_randrange(test.size() + 1 - del); test.erase(beg, beg + del); } if (((r >> 13) % 16) == 5) { @@ -229,11 +229,11 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) for (int k = 0; k < num; k++) { values[k] = insecure_rand(); } - test.insert_range(insecure_rand() % (test.size() + 1), values, values + num); + test.insert_range(insecure_randrange(test.size() + 1), values, values + num); } if (((r >> 26) % 32) == 8) { int del = std::min(test.size(), 1 + (insecure_randrange(4))); - int beg = insecure_rand() % (test.size() + 1 - del); + int beg = insecure_randrange(test.size() + 1 - del); test.erase(beg, beg + del); } r = insecure_rand(); @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) test.shrink_to_fit(); } if (test.size() > 0) { - test.update(insecure_rand() % test.size(), insecure_rand()); + test.update(insecure_randrange(test.size()), insecure_rand()); } if (((r >> 11) % 1024) == 11) { test.clear(); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 03a7d9ca6..d65b057c6 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -91,7 +91,7 @@ void static RandomScript(CScript &script) { script = CScript(); int ops = (insecure_randrange(10)); for (int i=0; inTimeMax >= test_time); From 9fa9876e4c837a6ac0c929a8fd90ab77e20f89f8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jun 2017 11:34:58 -0700 Subject: [PATCH 14/19] Replace rand() & ((1 << N) - 1) with randbits(N) Cherry-picked from: 5f0b04eedc5bbdb9319c9f1f1a6c599337f5bbe3 --- src/test/pmt_tests.cpp | 2 +- src/test/versionbits_tests.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index d07a9f395..32086ead5 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) std::vector vMatch(nTx, false); std::vector vMatchTxid1; for (unsigned int j=0; j Date: Tue, 23 May 2017 16:14:51 -0700 Subject: [PATCH 15/19] Use randbits instead of ad-hoc emulation in prevector tests Cherry-picked from: 2ada67852174a76753080d65a7adbe27241a9caa --- src/test/prevector_tests.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index d951a6c3c..674221e00 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -198,32 +198,31 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) for (int j = 0; j < 64; j++) { prevector_tester<8, int> test; for (int i = 0; i < 2048; i++) { - int r = insecure_rand(); - if ((r % 4) == 0) { + if (insecure_randbits(2) == 0) { test.insert(insecure_randrange(test.size() + 1), insecure_rand()); } - if (test.size() > 0 && ((r >> 2) % 4) == 1) { + if (test.size() > 0 && insecure_randbits(2) == 1) { test.erase(insecure_randrange(test.size())); } - if (((r >> 4) % 8) == 2) { + if (insecure_randbits(3) == 2) { int new_size = std::max(0, std::min(30, test.size() + (insecure_randrange(5)) - 2)); test.resize(new_size); } - if (((r >> 7) % 8) == 3) { + if (insecure_randbits(3) == 3) { test.insert(insecure_randrange(test.size() + 1), 1 + insecure_randrange(2), insecure_rand()); } - if (((r >> 10) % 8) == 4) { + if (insecure_randbits(3) == 4) { int del = std::min(test.size(), 1 + (insecure_randrange(2))); int beg = insecure_randrange(test.size() + 1 - del); test.erase(beg, beg + del); } - if (((r >> 13) % 16) == 5) { + if (insecure_randbits(4) == 5) { test.push_back(insecure_rand()); } - if (test.size() > 0 && ((r >> 17) % 16) == 6) { + if (test.size() > 0 && insecure_randbits(4) == 6) { test.pop_back(); } - if (((r >> 21) % 32) == 7) { + if (insecure_randbits(5) == 7) { int values[4]; int num = 1 + (insecure_randrange(4)); for (int k = 0; k < num; k++) { @@ -231,34 +230,33 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) } test.insert_range(insecure_randrange(test.size() + 1), values, values + num); } - if (((r >> 26) % 32) == 8) { + if (insecure_randbits(5) == 8) { int del = std::min(test.size(), 1 + (insecure_randrange(4))); int beg = insecure_randrange(test.size() + 1 - del); test.erase(beg, beg + del); } - r = insecure_rand(); - if (r % 32 == 9) { + if (insecure_randbits(5) == 9) { test.reserve(insecure_randrange(32)); } - if ((r >> 5) % 64 == 10) { + if (insecure_randbits(6) == 10) { test.shrink_to_fit(); } if (test.size() > 0) { test.update(insecure_randrange(test.size()), insecure_rand()); } - if (((r >> 11) % 1024) == 11) { + if (insecure_randbits(10) == 11) { test.clear(); } - if (((r >> 21) % 512) == 12) { + if (insecure_randbits(9) == 12) { test.assign(insecure_randrange(32), insecure_rand()); } - if (((r >> 15) % 8) == 3) { + if (insecure_randbits(3) == 3) { test.swap(); } - if (((r >> 15) % 16) == 8) { + if (insecure_randbits(4) == 8) { test.copy(); } - if (((r >> 15) % 32) == 18) { + if (insecure_randbits(5) == 18) { test.move(); } } From 7abc3c6c6d6f708fc3b8db2d9452fddadbbcbaf9 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 16:18:06 -0700 Subject: [PATCH 16/19] scripted-diff: Use randbits/bool instead of randrange where possible -BEGIN VERIFY SCRIPT- sed -i 's/insecure_randbits(1)/insecure_randbool()/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(2)/insecure_randbool()/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(4)/insecure_randbits(2)/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(32)/insecure_randbits(5)/g' src/test/*_tests.cpp sed -i 's/insecure_randrange(256)/insecure_randbits(8)/g' src/test/*_tests.cpp -END VERIFY SCRIPT- Cherry-picked from: 2fcd9cc86bfce944e3312e9a24685403250f3bdc --- src/test/coins_tests.cpp | 14 +++++++------- src/test/pmt_tests.cpp | 2 +- src/test/prevector_tests.cpp | 12 ++++++------ src/test/sighash_tests.cpp | 10 +++++----- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index fddd0dfe2..aaf665403 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -34,7 +34,7 @@ public: return false; } coins = it->second; - if (coins.IsPruned() && insecure_randrange(2) == 0) { + if (coins.IsPruned() && insecure_randbool() == 0) { // Randomly return false in case of an empty entry. return false; } @@ -171,20 +171,20 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_randrange(2) == 0) { + if (stack.size() > 1 && insecure_randbool() == 0) { unsigned int flushIndex = insecure_randrange(stack.size() - 1); stack[flushIndex]->Flush(); } } if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randrange(2) == 0) { + if (stack.size() > 0 && insecure_randbool() == 0) { //Remove the top cache stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { //Add a new cache CCoinsView* tip = &base; if (stack.size() > 0) { @@ -397,19 +397,19 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) if (insecure_randrange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_randrange(2) == 0) { + if (stack.size() > 1 && insecure_randbool() == 0) { unsigned int flushIndex = insecure_randrange(stack.size() - 1); stack[flushIndex]->Flush(); } } if (insecure_randrange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randrange(2) == 0) { + if (stack.size() > 0 && insecure_randbool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randrange(2))) { + if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 32086ead5..408937415 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -22,7 +22,7 @@ public: // flip one bit in one of the hashes - this should break the authentication void Damage() { unsigned int n = insecure_randrange(vHash.size()); - int bit = insecure_randrange(256); + int bit = insecure_randbits(8); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } }; diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 674221e00..5d9d18726 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -209,10 +209,10 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) test.resize(new_size); } if (insecure_randbits(3) == 3) { - test.insert(insecure_randrange(test.size() + 1), 1 + insecure_randrange(2), insecure_rand()); + test.insert(insecure_randrange(test.size() + 1), 1 + insecure_randbool(), insecure_rand()); } if (insecure_randbits(3) == 4) { - int del = std::min(test.size(), 1 + (insecure_randrange(2))); + int del = std::min(test.size(), 1 + (insecure_randbool())); int beg = insecure_randrange(test.size() + 1 - del); test.erase(beg, beg + del); } @@ -224,19 +224,19 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) } if (insecure_randbits(5) == 7) { int values[4]; - int num = 1 + (insecure_randrange(4)); + int num = 1 + (insecure_randbits(2)); for (int k = 0; k < num; k++) { values[k] = insecure_rand(); } test.insert_range(insecure_randrange(test.size() + 1), values, values + num); } if (insecure_randbits(5) == 8) { - int del = std::min(test.size(), 1 + (insecure_randrange(4))); + int del = std::min(test.size(), 1 + (insecure_randbits(2))); int beg = insecure_randrange(test.size() + 1 - del); test.erase(beg, beg + del); } if (insecure_randbits(5) == 9) { - test.reserve(insecure_randrange(32)); + test.reserve(insecure_randbits(5)); } if (insecure_randbits(6) == 10) { test.shrink_to_fit(); @@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) test.clear(); } if (insecure_randbits(9) == 12) { - test.assign(insecure_randrange(32), insecure_rand()); + test.assign(insecure_randbits(5), insecure_rand()); } if (insecure_randbits(3) == 3) { test.swap(); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index d65b057c6..c2813286a 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -98,16 +98,16 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { tx.nVersion = insecure_rand(); tx.vin.clear(); tx.vout.clear(); - tx.nLockTime = (insecure_randrange(2)) ? insecure_rand() : 0; - int ins = (insecure_randrange(4)) + 1; - int outs = fSingle ? ins : (insecure_randrange(4)) + 1; + tx.nLockTime = (insecure_randbool()) ? insecure_rand() : 0; + int ins = (insecure_randbits(2)) + 1; + int outs = fSingle ? ins : (insecure_randbits(2)) + 1; for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = insecure_rand256(); - txin.prevout.n = insecure_randrange(4); + txin.prevout.n = insecure_randbits(2); RandomScript(txin.scriptSig); - txin.nSequence = (insecure_randrange(2)) ? insecure_rand() : (unsigned int)-1; + txin.nSequence = (insecure_randbool()) ? insecure_rand() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); From 265f258540ed36982a43ba38f55b5f3558f0bf74 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jun 2017 12:03:17 -0700 Subject: [PATCH 17/19] scripted-diff: Use new naming style for insecure_rand* functions -BEGIN VERIFY SCRIPT- sed -i 's/\::iterator it; - it = mapOrphanTransactions.lower_bound(insecure_rand256()); + it = mapOrphanTransactions.lower_bound(InsecureRand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = insecure_rand256(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 4789152b5..59a052f3f 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -30,16 +30,16 @@ static CBlock BuildBlockTestCase() { block.vtx.resize(3); block.vtx[0] = MakeTransactionRef(tx); block.nVersion = 1; - block.hashPrevBlock = insecure_rand256(); + block.hashPrevBlock = InsecureRand256(); block.nBits = 0x207fffff; - tx.vin[0].prevout.hash = insecure_rand256(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].prevout.n = 0; block.vtx[1] = MakeTransactionRef(tx); tx.vin.resize(10); for (size_t i = 0; i < tx.vin.size(); i++) { - tx.vin[i].prevout.hash = insecure_rand256(); + tx.vin[i].prevout.hash = InsecureRand256(); tx.vin[i].prevout.n = 0; } block.vtx[2] = MakeTransactionRef(tx); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(std::move(coinbase)); block.nVersion = 1; - block.hashPrevBlock = insecure_rand256(); + block.hashPrevBlock = InsecureRand256(); block.nBits = 0x207fffff; bool mutated; @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BlockTransactionsRequest req1; - req1.blockhash = insecure_rand256(); + req1.blockhash = InsecureRand256(); req1.indexes.resize(4); req1.indexes[0] = 0; req1.indexes[1] = 1; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 5f3b21ca9..29bc5dd12 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -463,7 +463,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none) static std::vector RandomData() { - uint256 r = insecure_rand256(); + uint256 r = InsecureRand256(); return std::vector(r.begin(), r.end()); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 2e7a4d1a5..36b8768cd 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -160,7 +160,7 @@ void Correct_Queue_range(std::vector range) FakeCheckCheckCompletion::n_calls = 0; CCheckQueueControl control(small_queue.get()); while (total) { - vChecks.resize(std::min(total, (size_t) insecure_randrange(10))); + vChecks.resize(std::min(total, (size_t) InsecureRandRange(10))); total -= vChecks.size(); control.Add(vChecks); } @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) { std::vector range; range.reserve(100000/1000); - for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)insecure_randrange(std::min((size_t)1000, ((size_t)100000) - i)))) + for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)InsecureRandRange(std::min((size_t)1000, ((size_t)100000) - i)))) range.push_back(i); Correct_Queue_range(range); } @@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) CCheckQueueControl control(fail_queue.get()); size_t remaining = i; while (remaining) { - size_t r = insecure_randrange(10); + size_t r = InsecureRandRange(10); std::vector vChecks; vChecks.reserve(r); @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { CCheckQueueControl control(queue.get()); while (total) { - size_t r = insecure_randrange(10); + size_t r = InsecureRandRange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) vChecks.emplace_back(--total); @@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { CCheckQueueControl control(queue.get()); while (total) { - size_t r = insecure_randrange(10); + size_t r = InsecureRandRange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) { total--; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index aaf665403..f480b3c9f 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -34,7 +34,7 @@ public: return false; } coins = it->second; - if (coins.IsPruned() && insecure_randbool() == 0) { + if (coins.IsPruned() && InsecureRandBool() == 0) { // Randomly return false in case of an empty entry. return false; } @@ -55,7 +55,7 @@ public: if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Same optimization used in CCoinsViewDB is to only write dirty entries. map_[it->first] = it->second.coins; - if (it->second.coins.IsPruned() && insecure_randrange(3) == 0) { + if (it->second.coins.IsPruned() && InsecureRandRange(3) == 0) { // Randomly delete empty entries on write. map_.erase(it->first); } @@ -125,25 +125,25 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) std::vector txids; txids.resize(NUM_SIMULATION_ITERATIONS / 8); for (unsigned int i = 0; i < txids.size(); i++) { - txids[i] = insecure_rand256(); + txids[i] = InsecureRand256(); } for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { // Do a random modification. { - uint256 txid = txids[insecure_randrange(500) % txids.size()]; // txid we're going to modify in this iteration. + uint256 txid = txids[InsecureRandRange(500) % txids.size()]; // txid we're going to modify in this iteration. CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); BOOST_CHECK(coins == *entry); - if (insecure_randrange(5) == 0 || coins.IsPruned()) { + if (InsecureRandRange(5) == 0 || coins.IsPruned()) { if (coins.IsPruned()) { added_an_entry = true; } else { updated_an_entry = true; } - coins.nVersion = insecure_rand(); + coins.nVersion = InsecureRand32(); coins.vout.resize(1); - coins.vout[0].nValue = insecure_rand(); + coins.vout[0].nValue = InsecureRand32(); *entry = coins; } else { coins.Clear(); @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { @@ -169,22 +169,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_randbool() == 0) { - unsigned int flushIndex = insecure_randrange(stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randbool() == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { //Remove the top cache stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { //Add a new cache CCoinsView* tip = &base; if (stack.size() > 0) { @@ -222,7 +222,7 @@ std::map alltxs; TxData &FindRandomFrom(const std::set &txidset) { assert(txidset.size()); - std::set::iterator txIt = txidset.lower_bound(insecure_rand256()); + std::set::iterator txIt = txidset.lower_bound(InsecureRand256()); if (txIt == txidset.end()) { txIt = txidset.begin(); } @@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) std::set utxoset; for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { - uint32_t randiter = insecure_rand(); + uint32_t randiter = InsecureRand32(); // 19/20 txs add a new transaction if (randiter % 20 < 19) { @@ -263,13 +263,13 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) tx.vin.resize(1); tx.vout.resize(1); tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate - unsigned int height = insecure_rand(); + unsigned int height = InsecureRand32(); CCoins oldcoins; // 2/20 times create a new coinbase if (randiter % 20 < 2 || coinbaseids.size() < 10) { // 1/10 of those times create a duplicate coinbase - if (insecure_randrange(10) == 0 && coinbaseids.size()) { + if (InsecureRandRange(10) == 0 && coinbaseids.size()) { TxData &txd = FindRandomFrom(coinbaseids); // Reuse the exact same coinbase tx = std::get<0>(txd); @@ -384,7 +384,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { @@ -395,21 +395,21 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_randbool() == 0) { - unsigned int flushIndex = insecure_randrange(stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_randrange(100) == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_randbool() == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_randbool())) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index ab3e6fc1f..a4f0e17c9 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -38,7 +38,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { - size_t len = insecure_randrange((in.size() - pos + 1) / 2 + 1); + size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 2380ee202..34692c399 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; - uint256 in = insecure_rand256(); + uint256 in = InsecureRand256(); uint256 res; // Ensure that we're doing real obfuscation when obfuscate=true @@ -55,11 +55,11 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; - uint256 in = insecure_rand256(); + uint256 in = InsecureRand256(); char key2 = 'j'; - uint256 in2 = insecure_rand256(); + uint256 in2 = InsecureRand256(); char key3 = 'k'; - uint256 in3 = insecure_rand256(); + uint256 in3 = InsecureRand256(); uint256 res; CDBBatch batch(dbw); @@ -93,10 +93,10 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) // The two keys are intentionally chosen for ordering char key = 'j'; - uint256 in = insecure_rand256(); + uint256 in = InsecureRand256(); BOOST_CHECK(dbw.Write(key, in)); char key2 = 'k'; - uint256 in2 = insecure_rand256(); + uint256 in2 = InsecureRand256(); BOOST_CHECK(dbw.Write(key2, in2)); std::unique_ptr it(const_cast(&dbw)->NewIterator()); @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = insecure_rand256(); + uint256 in = InsecureRand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string - uint256 in2 = insecure_rand256(); + uint256 in2 = InsecureRand256(); uint256 res3; // Check that we can write successfully @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = insecure_rand256(); + uint256 in = InsecureRand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_CHECK(!odbw.Read(key, res2)); BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); - uint256 in2 = insecure_rand256(); + uint256 in2 = InsecureRand256(); uint256 res3; // Check that we can write successfully diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 118f2a66a..aae84a4fd 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) { for (int i = 0; i < 32; i++) { // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes. - int ntx = (i <= 16) ? i : 17 + (insecure_randrange(4000)); + int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000)); // Try up to 3 mutations. for (int mutate = 0; mutate <= 3; mutate++) { int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first. @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) // If ntx <= 16, try all branches. Otherise, try 16 random ones. int mtx = loop; if (ntx > 16) { - mtx = insecure_randrange(ntx); + mtx = InsecureRandRange(ntx); } std::vector newBranch = BlockMerkleBranch(block, mtx); std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 77eded091..53a9874fa 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (chainActive.Tip()->nHeight < 209999) { CBlockIndex* prev = chainActive.Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(insecure_rand256()); + next->phashBlock = new uint256(InsecureRand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; @@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (chainActive.Tip()->nHeight < 210000) { CBlockIndex* prev = chainActive.Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(insecure_rand256()); + next->phashBlock = new uint256(InsecureRand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 408937415..708a9ca50 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -21,8 +21,8 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree public: // flip one bit in one of the hashes - this should break the authentication void Damage() { - unsigned int n = insecure_randrange(vHash.size()); - int bit = insecure_randbits(8); + unsigned int n = InsecureRandRange(vHash.size()); + int bit = InsecureRandBits(8); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } }; @@ -31,7 +31,7 @@ BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(pmt_test1) { - seed_insecure_rand(false); + SeedInsecureRand(false); static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095}; for (int i = 0; i < 12; i++) { @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) std::vector vMatch(nTx, false); std::vector vMatchTxid1; for (unsigned int j=0; jGetBlockTime() - p2->GetBlockTime()); diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 5d9d18726..354fed1c1 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -187,7 +187,7 @@ public: } prevector_tester() { - seed_insecure_rand(); + SeedInsecureRand(); rand_seed = insecure_rand_seed; rand_cache = insecure_rand_ctx; } @@ -198,65 +198,65 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) for (int j = 0; j < 64; j++) { prevector_tester<8, int> test; for (int i = 0; i < 2048; i++) { - if (insecure_randbits(2) == 0) { - test.insert(insecure_randrange(test.size() + 1), insecure_rand()); + if (InsecureRandBits(2) == 0) { + test.insert(InsecureRandRange(test.size() + 1), InsecureRand32()); } - if (test.size() > 0 && insecure_randbits(2) == 1) { - test.erase(insecure_randrange(test.size())); + if (test.size() > 0 && InsecureRandBits(2) == 1) { + test.erase(InsecureRandRange(test.size())); } - if (insecure_randbits(3) == 2) { - int new_size = std::max(0, std::min(30, test.size() + (insecure_randrange(5)) - 2)); + if (InsecureRandBits(3) == 2) { + int new_size = std::max(0, std::min(30, test.size() + (InsecureRandRange(5)) - 2)); test.resize(new_size); } - if (insecure_randbits(3) == 3) { - test.insert(insecure_randrange(test.size() + 1), 1 + insecure_randbool(), insecure_rand()); + if (InsecureRandBits(3) == 3) { + test.insert(InsecureRandRange(test.size() + 1), 1 + InsecureRandBool(), InsecureRand32()); } - if (insecure_randbits(3) == 4) { - int del = std::min(test.size(), 1 + (insecure_randbool())); - int beg = insecure_randrange(test.size() + 1 - del); + if (InsecureRandBits(3) == 4) { + int del = std::min(test.size(), 1 + (InsecureRandBool())); + int beg = InsecureRandRange(test.size() + 1 - del); test.erase(beg, beg + del); } - if (insecure_randbits(4) == 5) { - test.push_back(insecure_rand()); + if (InsecureRandBits(4) == 5) { + test.push_back(InsecureRand32()); } - if (test.size() > 0 && insecure_randbits(4) == 6) { + if (test.size() > 0 && InsecureRandBits(4) == 6) { test.pop_back(); } - if (insecure_randbits(5) == 7) { + if (InsecureRandBits(5) == 7) { int values[4]; - int num = 1 + (insecure_randbits(2)); + int num = 1 + (InsecureRandBits(2)); for (int k = 0; k < num; k++) { - values[k] = insecure_rand(); + values[k] = InsecureRand32(); } - test.insert_range(insecure_randrange(test.size() + 1), values, values + num); + test.insert_range(InsecureRandRange(test.size() + 1), values, values + num); } - if (insecure_randbits(5) == 8) { - int del = std::min(test.size(), 1 + (insecure_randbits(2))); - int beg = insecure_randrange(test.size() + 1 - del); + if (InsecureRandBits(5) == 8) { + int del = std::min(test.size(), 1 + (InsecureRandBits(2))); + int beg = InsecureRandRange(test.size() + 1 - del); test.erase(beg, beg + del); } - if (insecure_randbits(5) == 9) { - test.reserve(insecure_randbits(5)); + if (InsecureRandBits(5) == 9) { + test.reserve(InsecureRandBits(5)); } - if (insecure_randbits(6) == 10) { + if (InsecureRandBits(6) == 10) { test.shrink_to_fit(); } if (test.size() > 0) { - test.update(insecure_randrange(test.size()), insecure_rand()); + test.update(InsecureRandRange(test.size()), InsecureRand32()); } - if (insecure_randbits(10) == 11) { + if (InsecureRandBits(10) == 11) { test.clear(); } - if (insecure_randbits(9) == 12) { - test.assign(insecure_randbits(5), insecure_rand()); + if (InsecureRandBits(9) == 12) { + test.assign(InsecureRandBits(5), InsecureRand32()); } - if (insecure_randbits(3) == 3) { + if (InsecureRandBits(3) == 3) { test.swap(); } - if (insecure_randbits(4) == 8) { + if (InsecureRandBits(4) == 8) { test.copy(); } - if (insecure_randbits(5) == 18) { + if (InsecureRandBits(5) == 18) { test.move(); } } diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index c2813286a..eb671cb87 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -89,30 +89,30 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un void static RandomScript(CScript &script) { static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR}; script = CScript(); - int ops = (insecure_randrange(10)); + int ops = (InsecureRandRange(10)); for (int i=0; inTimeMax >= test_time); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 129c4a82e..b85f61132 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -67,7 +67,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha RegisterAllCoreRPCCommands(tableRPC); ClearDatadirCache(); - pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(insecure_randrange(100000))); + pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000))); fs::create_directories(pathTemp); ForceSetArg("-datadir", pathTemp.string()); mempool.setSanityCheck(1.0); diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index eecd8635e..3a62b14fe 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -18,7 +18,7 @@ extern uint256 insecure_rand_seed; extern FastRandomContext insecure_rand_ctx; -static inline void seed_insecure_rand(bool fDeterministic = false) +static inline void SeedInsecureRand(bool fDeterministic = false) { if (fDeterministic) { insecure_rand_seed = uint256(); @@ -28,12 +28,12 @@ static inline void seed_insecure_rand(bool fDeterministic = false) insecure_rand_ctx = FastRandomContext(insecure_rand_seed); } -static inline uint32_t insecure_rand() { return insecure_rand_ctx.rand32(); } -static inline uint256 insecure_rand256() { return insecure_rand_ctx.rand256(); } -static inline uint64_t insecure_randbits(int bits) { return insecure_rand_ctx.randbits(bits); } -static inline uint64_t insecure_randrange(uint64_t range) { return insecure_rand_ctx.randrange(range); } -static inline bool insecure_randbool() { return insecure_rand_ctx.randbool(); } -static inline std::vector insecure_randbytes(size_t len) { return insecure_rand_ctx.randbytes(len); } +static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); } +static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); } +static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); } +static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); } +static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); } +static inline std::vector InsecureRandBytes(size_t len) { return insecure_rand_ctx.randbytes(len); } /** Basic testing setup. * This just configures logging and chain parameters. diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 89f7025d0..d33c4f1cb 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -242,7 +242,7 @@ BOOST_AUTO_TEST_CASE(util_IsHex) BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { - seed_insecure_rand(true); + SeedInsecureRand(true); for (int mod=2;mod<11;mod++) { int mask = 1; @@ -256,7 +256,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) for (int i = 0; i < 10000; i++) { uint32_t rval; do{ - rval=insecure_rand()&mask; + rval=InsecureRand32()&mask; }while(rval>=(uint32_t)mod); count += rval==0; } diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 051d905c0..d8b4675b4 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -81,7 +81,7 @@ public: VersionBitsTester& TestStateSinceHeight(int height) { for (int i = 0; i < CHECKERS; i++) { - if (insecure_randbits(i) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? NULL : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num)); } } @@ -91,7 +91,7 @@ public: VersionBitsTester& TestDefined() { for (int i = 0; i < CHECKERS; i++) { - if (insecure_randbits(i) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num)); } } @@ -101,7 +101,7 @@ public: VersionBitsTester& TestStarted() { for (int i = 0; i < CHECKERS; i++) { - if (insecure_randbits(i) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num)); } } @@ -111,7 +111,7 @@ public: VersionBitsTester& TestLockedIn() { for (int i = 0; i < CHECKERS; i++) { - if (insecure_randbits(i) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num)); } } @@ -121,7 +121,7 @@ public: VersionBitsTester& TestActive() { for (int i = 0; i < CHECKERS; i++) { - if (insecure_randbits(i) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num)); } } @@ -131,7 +131,7 @@ public: VersionBitsTester& TestFailed() { for (int i = 0; i < CHECKERS; i++) { - if (insecure_randbits(i) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num)); } } diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index eec916c9d..cbd74b6f9 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(passphrase) { std::string hash(GetRandHash().ToString()); std::vector vchSalt(8); GetRandBytes(&vchSalt[0], vchSalt.size()); - uint32_t rounds = insecure_rand(); + uint32_t rounds = InsecureRand32(); if (rounds > 30000) rounds = 30000; TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds); From 743c3acd3d9535dc07a66b232458622b76ae7cae Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Thu, 27 Jul 2017 15:34:09 +0300 Subject: [PATCH 18/19] Check if sys/random.h is required for getentropy on OSX. Cherry-picked from: ee2d10ad0c0e04d0b9da4535a6fff265ac2501e5 --- configure.ac | 8 ++++++++ src/random.cpp | 14 +++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f0c9926d6..fe7a63c00 100644 --- a/configure.ac +++ b/configure.ac @@ -655,6 +655,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [ AC_MSG_RESULT(no)] ) +AC_MSG_CHECKING(for getentropy via random.h) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], + [[ getentropy(nullptr, 32) ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY_RAND, 1,[Define this symbol if the BSD getentropy system call is available with sys/random.h]) ], + [ AC_MSG_RESULT(no)] +) + AC_MSG_CHECKING(for sysctl KERN_ARND) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], diff --git a/src/random.cpp b/src/random.cpp index 0e8f83dd8..766934d0b 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -25,9 +25,12 @@ #include #include #endif -#ifdef HAVE_GETENTROPY +#if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)) #include #endif +#if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) +#include +#endif #ifdef HAVE_SYSCTL_ARND #include #endif @@ -164,6 +167,15 @@ void GetOSRand(unsigned char *ent32) if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { RandFailure(); } +#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) + // We need a fallback for OSX < 10.12 + if (&getentropy != NULL) { + if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { + RandFailure(); + } + } else { + GetDevURandom(ent32); + } #elif defined(HAVE_SYSCTL_ARND) /* FreeBSD and similar. It is possible for the call to return less * bytes than requested, so need to read in a loop. From d693d4a0086f84daaea6b091e7be80d4a08eb413 Mon Sep 17 00:00:00 2001 From: xanimo Date: Fri, 19 May 2023 10:14:35 +0100 Subject: [PATCH 19/19] random: getentropy on macOS does not need unistd.h change sys/random.h to random.h in AC_MSG_CHECK remove definitions that are applicable to macos which include unistd.h additionally change comparator argument from NULL to nullptr when evaluating &getentropy Inspired by: c13c97dbf846cf0e6a5581ac414ef96a215b0dc6 --- configure.ac | 4 ++-- src/random.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index fe7a63c00..dab2cecb4 100644 --- a/configure.ac +++ b/configure.ac @@ -655,8 +655,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [ AC_MSG_RESULT(no)] ) -AC_MSG_CHECKING(for getentropy via random.h) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +AC_MSG_CHECKING([for getentropy via sys/random.h]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ getentropy(nullptr, 32) ]])], [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY_RAND, 1,[Define this symbol if the BSD getentropy system call is available with sys/random.h]) ], diff --git a/src/random.cpp b/src/random.cpp index 766934d0b..0243511ff 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -25,7 +25,7 @@ #include #include #endif -#if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)) +#if defined(HAVE_GETENTROPY) #include #endif #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) @@ -169,7 +169,7 @@ void GetOSRand(unsigned char *ent32) } #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) // We need a fallback for OSX < 10.12 - if (&getentropy != NULL) { + if (&getentropy != nullptr) { if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { RandFailure(); }