mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-16 16:11:47 +02:00
tests: overhaul deterministic test randomness
The existing code provides two randomness mechanisms for test purposes: - g_insecure_rand_ctx (with its wrappers InsecureRand*), which during tests is initialized using either zeros (SeedRand::ZEROS), or using environment-provided randomness (SeedRand::SEED). - g_mock_deterministic_tests, which controls some (but not all) of the normal randomness output if set, but then makes it extremely predictable (identical output repeatedly). Replace this with a single mechanism, which retains the SeedRand modes to control all randomness. There is a new internal deterministic PRNG inside the random module, which is used in GetRandBytes() when in test mode, and which is also used to initialize g_insecure_rand_ctx. This means that during tests, all random numbers are made deterministic. There is one exception, GetStrongRandBytes(), which even in test mode still uses the normal PRNG state. This probably opens the door to removing a lot of the ad-hoc "deterministic" mode functions littered through the codebase (by simply running relevant tests in SeedRand::ZEROS mode), but this isn't done yet.
This commit is contained in:
parent
6cfdc5b104
commit
810cdf6b4e
@ -23,6 +23,7 @@
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
|
||||
#ifdef WIN32
|
||||
@ -417,6 +418,10 @@ class RNGState {
|
||||
uint64_t m_counter GUARDED_BY(m_mutex) = 0;
|
||||
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
|
||||
|
||||
/** If not nullopt, the output of this RNGState is redirected and drawn from here
|
||||
* (unless always_use_real_rng is passed to MixExtract). */
|
||||
std::optional<ChaCha20> m_deterministic_prng GUARDED_BY(m_mutex);
|
||||
|
||||
Mutex m_events_mutex;
|
||||
CSHA256 m_events_hasher GUARDED_BY(m_events_mutex);
|
||||
|
||||
@ -457,11 +462,21 @@ public:
|
||||
m_events_hasher.Write(events_hash, 32);
|
||||
}
|
||||
|
||||
/** Make the output of MixExtract (unless always_use_real_rng) deterministic, with specified seed. */
|
||||
void MakeDeterministic(const uint256& seed) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
LOCK(m_mutex);
|
||||
m_deterministic_prng.emplace(MakeByteSpan(seed));
|
||||
}
|
||||
|
||||
/** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
|
||||
*
|
||||
* If this function has never been called with strong_seed = true, false is returned.
|
||||
*
|
||||
* If always_use_real_rng is false, and MakeDeterministic has been called before, output
|
||||
* from the deterministic PRNG instead.
|
||||
*/
|
||||
bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed, bool always_use_real_rng) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
assert(num <= 32);
|
||||
unsigned char buf[64];
|
||||
@ -479,6 +494,13 @@ public:
|
||||
hasher.Finalize(buf);
|
||||
// Store the last 32 bytes of the hash output as new RNG state.
|
||||
memcpy(m_state, buf + 32, 32);
|
||||
// Handle requests for deterministic randomness.
|
||||
if (!always_use_real_rng && m_deterministic_prng.has_value()) [[unlikely]] {
|
||||
// Overwrite the beginning of buf, which will be used for output.
|
||||
m_deterministic_prng->Keystream(AsWritableBytes(Span{buf, num}));
|
||||
// Do not require strong seeding for deterministic output.
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
// If desired, copy (up to) the first 32 bytes of the hash output as output.
|
||||
if (num) {
|
||||
@ -552,8 +574,9 @@ static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
|
||||
static void SeedStrengthen(CSHA512& hasher, RNGState& rng, SteadyClock::duration dur) noexcept
|
||||
{
|
||||
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
|
||||
// Never use the deterministic PRNG for this, as the result is only used internally.
|
||||
unsigned char strengthen_seed[32];
|
||||
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
|
||||
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false, /*always_use_real_rng=*/true);
|
||||
// Strengthen the seed, and feed it into hasher.
|
||||
Strengthen(strengthen_seed, dur, hasher);
|
||||
}
|
||||
@ -604,7 +627,7 @@ enum class RNGLevel {
|
||||
PERIODIC, //!< Called by RandAddPeriodic()
|
||||
};
|
||||
|
||||
static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
|
||||
static void ProcRand(unsigned char* out, int num, RNGLevel level, bool always_use_real_rng) noexcept
|
||||
{
|
||||
// Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
|
||||
RNGState& rng = GetRNGState();
|
||||
@ -625,24 +648,40 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
|
||||
}
|
||||
|
||||
// Combine with and update state
|
||||
if (!rng.MixExtract(out, num, std::move(hasher), false)) {
|
||||
if (!rng.MixExtract(out, num, std::move(hasher), false, always_use_real_rng)) {
|
||||
// On the first invocation, also seed with SeedStartup().
|
||||
CSHA512 startup_hasher;
|
||||
SeedStartup(startup_hasher, rng);
|
||||
rng.MixExtract(out, num, std::move(startup_hasher), true);
|
||||
rng.MixExtract(out, num, std::move(startup_hasher), true, always_use_real_rng);
|
||||
}
|
||||
}
|
||||
|
||||
void GetRandBytes(Span<unsigned char> bytes) noexcept { ProcRand(bytes.data(), bytes.size(), RNGLevel::FAST); }
|
||||
void GetStrongRandBytes(Span<unsigned char> bytes) noexcept { ProcRand(bytes.data(), bytes.size(), RNGLevel::SLOW); }
|
||||
void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
|
||||
void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
|
||||
/** Internal function to set g_determinstic_rng. Only accessed from tests. */
|
||||
void MakeRandDeterministicDANGEROUS(const uint256& seed) noexcept
|
||||
{
|
||||
GetRNGState().MakeDeterministic(seed);
|
||||
}
|
||||
|
||||
bool g_mock_deterministic_tests{false};
|
||||
void GetRandBytes(Span<unsigned char> bytes) noexcept
|
||||
{
|
||||
ProcRand(bytes.data(), bytes.size(), RNGLevel::FAST, /*always_use_real_rng=*/false);
|
||||
}
|
||||
|
||||
void GetStrongRandBytes(Span<unsigned char> bytes) noexcept
|
||||
{
|
||||
ProcRand(bytes.data(), bytes.size(), RNGLevel::SLOW, /*always_use_real_rng=*/true);
|
||||
}
|
||||
|
||||
void RandAddPeriodic() noexcept
|
||||
{
|
||||
ProcRand(nullptr, 0, RNGLevel::PERIODIC, /*always_use_real_rng=*/false);
|
||||
}
|
||||
|
||||
void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
|
||||
|
||||
uint64_t GetRandInternal(uint64_t nMax) noexcept
|
||||
{
|
||||
return FastRandomContext(g_mock_deterministic_tests).randrange(nMax);
|
||||
return FastRandomContext().randrange(nMax);
|
||||
}
|
||||
|
||||
uint256 GetRandHash() noexcept
|
||||
@ -708,7 +747,7 @@ bool Random_SanityCheck()
|
||||
CSHA512 to_add;
|
||||
to_add.Write((const unsigned char*)&start, sizeof(start));
|
||||
to_add.Write((const unsigned char*)&stop, sizeof(stop));
|
||||
GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false);
|
||||
GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false, /*always_use_real_rng=*/true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -734,7 +773,7 @@ FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexce
|
||||
void RandomInit()
|
||||
{
|
||||
// Invoke RNG code to trigger initialization (if not already performed)
|
||||
ProcRand(nullptr, 0, RNGLevel::FAST);
|
||||
ProcRand(nullptr, 0, RNGLevel::FAST, /*always_use_real_rng=*/true);
|
||||
|
||||
ReportHardwareRand();
|
||||
}
|
||||
|
@ -63,6 +63,12 @@
|
||||
* When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
|
||||
* (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
|
||||
* become the new RNG state.
|
||||
*
|
||||
* During tests, the RNG can be put into a special deterministic mode, in which the output
|
||||
* of all RNG functions, with the exception of GetStrongRandBytes(), is replaced with the
|
||||
* output of a deterministic RNG. This deterministic RNG does not gather entropy, and is
|
||||
* unaffected by RandAddPeriodic() or RandAddEvent(). It produces pseudorandom data that
|
||||
* only depends on the seed it was initialized with, possibly until it is reinitialized.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -340,6 +346,7 @@ private:
|
||||
void RandomSeed() noexcept;
|
||||
|
||||
public:
|
||||
/** Construct a FastRandomContext with GetRandHash()-based entropy (or zero key if fDeterministic). */
|
||||
explicit FastRandomContext(bool fDeterministic = false) noexcept;
|
||||
|
||||
/** Initialize with explicit seed (only for testing) */
|
||||
|
@ -463,8 +463,7 @@ static std::vector<unsigned char> RandomData()
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rolling_bloom)
|
||||
{
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
g_mock_deterministic_tests = true;
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
|
||||
// last-100-entry, 1% false positive:
|
||||
CRollingBloomFilter rb1(100, 0.01);
|
||||
@ -491,7 +490,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
|
||||
++nHits;
|
||||
}
|
||||
// Expect about 100 hits
|
||||
BOOST_CHECK_EQUAL(nHits, 75U);
|
||||
BOOST_CHECK_EQUAL(nHits, 71U);
|
||||
|
||||
BOOST_CHECK(rb1.contains(data[DATASIZE-1]));
|
||||
rb1.reset();
|
||||
@ -519,7 +518,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
|
||||
++nHits;
|
||||
}
|
||||
// Expect about 5 false positives
|
||||
BOOST_CHECK_EQUAL(nHits, 6U);
|
||||
BOOST_CHECK_EQUAL(nHits, 3U);
|
||||
|
||||
// last-1000-entry, 0.01% false positive:
|
||||
CRollingBloomFilter rb2(1000, 0.001);
|
||||
@ -530,7 +529,6 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
|
||||
for (int i = 0; i < DATASIZE; i++) {
|
||||
BOOST_CHECK(rb2.contains(data[i]));
|
||||
}
|
||||
g_mock_deterministic_tests = false;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -307,8 +307,7 @@ UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
|
||||
// has the expected effect (the other duplicate is overwritten at all cache levels)
|
||||
BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
|
||||
{
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
g_mock_deterministic_tests = true;
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
|
||||
bool spent_a_duplicate_coinbase = false;
|
||||
// A simple map to track what we expect the cache stack to represent.
|
||||
@ -496,8 +495,6 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
|
||||
|
||||
// Verify coverage.
|
||||
BOOST_CHECK(spent_a_duplicate_coinbase);
|
||||
|
||||
g_mock_deterministic_tests = false;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_serialization)
|
||||
|
@ -37,7 +37,7 @@ BOOST_AUTO_TEST_SUITE(cuckoocache_tests);
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
|
||||
{
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
CuckooCache::cache<uint256, SignatureCacheHasher> cc{};
|
||||
size_t megabytes = 4;
|
||||
cc.setup_bytes(megabytes << 20);
|
||||
@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
|
||||
template <typename Cache>
|
||||
static double test_cache(size_t megabytes, double load)
|
||||
{
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
std::vector<uint256> hashes;
|
||||
Cache set{};
|
||||
size_t bytes = megabytes * (1 << 20);
|
||||
@ -126,7 +126,7 @@ template <typename Cache>
|
||||
static void test_cache_erase(size_t megabytes)
|
||||
{
|
||||
double load = 1;
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
std::vector<uint256> hashes;
|
||||
Cache set{};
|
||||
size_t bytes = megabytes * (1 << 20);
|
||||
@ -189,7 +189,7 @@ template <typename Cache>
|
||||
static void test_cache_erase_parallel(size_t megabytes)
|
||||
{
|
||||
double load = 1;
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
std::vector<uint256> hashes;
|
||||
Cache set{};
|
||||
size_t bytes = megabytes * (1 << 20);
|
||||
@ -293,7 +293,7 @@ static 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.
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
|
||||
// block_activity models a chunk of network activity. n_insert elements are
|
||||
// added to the cache. The first and last n/4 are stored for removal later
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <netaddress.h>
|
||||
#include <netbase.h>
|
||||
#include <test/util/random.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/check.h>
|
||||
#include <util/fs.h>
|
||||
|
@ -210,7 +210,7 @@ public:
|
||||
}
|
||||
|
||||
prevector_tester() {
|
||||
SeedInsecureRand();
|
||||
SeedRandomForTest();
|
||||
rand_seed = InsecureRand256();
|
||||
rand_cache = FastRandomContext(rand_seed);
|
||||
}
|
||||
|
@ -20,19 +20,30 @@ BOOST_AUTO_TEST_CASE(osrandom_tests)
|
||||
BOOST_CHECK(Random_SanityCheck());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fastrandom_tests)
|
||||
BOOST_AUTO_TEST_CASE(fastrandom_tests_deterministic)
|
||||
{
|
||||
// Check that deterministic FastRandomContexts are deterministic
|
||||
g_mock_deterministic_tests = true;
|
||||
FastRandomContext ctx1(true);
|
||||
FastRandomContext ctx2(true);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
FastRandomContext ctx1{true};
|
||||
FastRandomContext ctx2{true};
|
||||
|
||||
for (int i = 10; i > 0; --i) {
|
||||
BOOST_CHECK_EQUAL(GetRand<uint64_t>(), uint64_t{10393729187455219830U});
|
||||
BOOST_CHECK_EQUAL(GetRand<int>(), int{769702006});
|
||||
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 2917185654);
|
||||
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2144374);
|
||||
{
|
||||
BOOST_CHECK_EQUAL(GetRand<uint64_t>(), uint64_t{9330418229102544152u});
|
||||
BOOST_CHECK_EQUAL(GetRand<int>(), int{618925161});
|
||||
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 1271170921);
|
||||
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2803534);
|
||||
|
||||
BOOST_CHECK_EQUAL(GetRand<uint64_t>(), uint64_t{10170981140880778086u});
|
||||
BOOST_CHECK_EQUAL(GetRand<int>(), int{1689082725});
|
||||
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 2464643716);
|
||||
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2312205);
|
||||
|
||||
BOOST_CHECK_EQUAL(GetRand<uint64_t>(), uint64_t{5689404004456455543u});
|
||||
BOOST_CHECK_EQUAL(GetRand<int>(), int{785839937});
|
||||
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 93558804);
|
||||
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 507022);
|
||||
}
|
||||
|
||||
{
|
||||
constexpr SteadySeconds time_point{1s};
|
||||
FastRandomContext ctx{true};
|
||||
@ -65,15 +76,28 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
|
||||
// Check with time-point type
|
||||
BOOST_CHECK_EQUAL(2782, ctx.rand_uniform_duration<SteadySeconds>(9h).count());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fastrandom_tests_nondeterministic)
|
||||
{
|
||||
// Check that a nondeterministic ones are not
|
||||
g_mock_deterministic_tests = false;
|
||||
for (int i = 10; i > 0; --i) {
|
||||
BOOST_CHECK(GetRand<uint64_t>() != uint64_t{10393729187455219830U});
|
||||
BOOST_CHECK(GetRand<int>() != int{769702006});
|
||||
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}) != std::chrono::microseconds{2917185654});
|
||||
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}) != std::chrono::milliseconds{2144374});
|
||||
{
|
||||
BOOST_CHECK(GetRand<uint64_t>() != uint64_t{9330418229102544152u});
|
||||
BOOST_CHECK(GetRand<int>() != int{618925161});
|
||||
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 1271170921);
|
||||
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 2803534);
|
||||
|
||||
BOOST_CHECK(GetRand<uint64_t>() != uint64_t{10170981140880778086u});
|
||||
BOOST_CHECK(GetRand<int>() != int{1689082725});
|
||||
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 2464643716);
|
||||
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 2312205);
|
||||
|
||||
BOOST_CHECK(GetRand<uint64_t>() != uint64_t{5689404004456455543u});
|
||||
BOOST_CHECK(GetRand<int>() != int{785839937});
|
||||
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 93558804);
|
||||
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 507022);
|
||||
}
|
||||
|
||||
{
|
||||
FastRandomContext ctx3, ctx4;
|
||||
BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal
|
||||
|
@ -436,7 +436,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file_skip)
|
||||
BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)
|
||||
{
|
||||
// Make this test deterministic.
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
|
||||
fs::path streams_test_filename = m_args.GetDataDirBase() / "streams_test_tmp";
|
||||
for (int rep = 0; rep < 50; ++rep) {
|
||||
|
@ -13,21 +13,26 @@
|
||||
|
||||
FastRandomContext g_insecure_rand_ctx;
|
||||
|
||||
/** Return the unsigned from the environment var if available, otherwise 0 */
|
||||
static uint256 GetUintFromEnv(const std::string& env_name)
|
||||
{
|
||||
const char* num = std::getenv(env_name.c_str());
|
||||
if (!num) return {};
|
||||
return uint256S(num);
|
||||
}
|
||||
extern void MakeRandDeterministicDANGEROUS(const uint256& seed) noexcept;
|
||||
|
||||
void Seed(FastRandomContext& ctx)
|
||||
void SeedRandomForTest(SeedRand seedtype)
|
||||
{
|
||||
// Should be enough to get the seed once for the process
|
||||
static uint256 seed{};
|
||||
static const std::string RANDOM_CTX_SEED{"RANDOM_CTX_SEED"};
|
||||
if (seed.IsNull()) seed = GetUintFromEnv(RANDOM_CTX_SEED);
|
||||
if (seed.IsNull()) seed = GetRandHash();
|
||||
|
||||
// Do this once, on the first call, regardless of seedtype, because once
|
||||
// MakeRandDeterministicDANGEROUS is called, the output of GetRandHash is
|
||||
// no longer truly random. It should be enough to get the seed once for the
|
||||
// process.
|
||||
static const uint256 ctx_seed = []() {
|
||||
// If RANDOM_CTX_SEED is set, use that as seed.
|
||||
const char* num = std::getenv(RANDOM_CTX_SEED.c_str());
|
||||
if (num) return uint256S(num);
|
||||
// Otherwise use a (truly) random value.
|
||||
return GetRandHash();
|
||||
}();
|
||||
|
||||
const uint256& seed{seedtype == SeedRand::SEED ? ctx_seed : uint256::ZERO};
|
||||
LogPrintf("%s: Setting random seed for current tests to %s=%s\n", __func__, RANDOM_CTX_SEED, seed.GetHex());
|
||||
ctx = FastRandomContext(seed);
|
||||
MakeRandDeterministicDANGEROUS(seed);
|
||||
g_insecure_rand_ctx = FastRandomContext(GetRandHash());
|
||||
}
|
||||
|
@ -19,27 +19,13 @@
|
||||
*/
|
||||
extern FastRandomContext g_insecure_rand_ctx;
|
||||
|
||||
/**
|
||||
* Flag to make GetRand in random.h return the same number
|
||||
*/
|
||||
extern bool g_mock_deterministic_tests;
|
||||
|
||||
enum class SeedRand {
|
||||
ZEROS, //!< Seed with a compile time constant of zeros
|
||||
SEED, //!< Call the Seed() helper
|
||||
SEED, //!< Use (and report) random seed from environment, or a (truly) random one.
|
||||
};
|
||||
|
||||
/** Seed the given random ctx or use the seed passed in via an environment var */
|
||||
void Seed(FastRandomContext& ctx);
|
||||
|
||||
static inline void SeedInsecureRand(SeedRand seed = SeedRand::SEED)
|
||||
{
|
||||
if (seed == SeedRand::ZEROS) {
|
||||
g_insecure_rand_ctx = FastRandomContext(/*fDeterministic=*/true);
|
||||
} else {
|
||||
Seed(g_insecure_rand_ctx);
|
||||
}
|
||||
}
|
||||
/** Seed the RNG for testing. This affects all randomness, except GetStrongRandBytes(). */
|
||||
void SeedRandomForTest(SeedRand seed = SeedRand::SEED);
|
||||
|
||||
static inline uint32_t InsecureRand32()
|
||||
{
|
||||
|
@ -178,7 +178,7 @@ BasicTestingSetup::BasicTestingSetup(const ChainType chainType, const std::vecto
|
||||
gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root));
|
||||
|
||||
SelectParams(chainType);
|
||||
SeedInsecureRand();
|
||||
SeedRandomForTest();
|
||||
if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN);
|
||||
InitLogging(*m_node.args);
|
||||
AppInitParameterInteraction(*m_node.args);
|
||||
|
@ -459,7 +459,7 @@ BOOST_AUTO_TEST_CASE(util_IsHexNumber)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
|
||||
{
|
||||
SeedInsecureRand(SeedRand::ZEROS);
|
||||
SeedRandomForTest(SeedRand::ZEROS);
|
||||
for (int mod=2;mod<11;mod++)
|
||||
{
|
||||
int mask = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user