random.cpp
1 // Copyright (c) 2023-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <test/util/random.h> 6 7 #include <logging.h> 8 #include <random.h> 9 #include <uint256.h> 10 #include <util/check.h> 11 12 #include <cstdlib> 13 #include <iostream> 14 15 std::atomic<bool> g_seeded_g_prng_zero{false}; 16 17 extern void MakeRandDeterministicDANGEROUS(const uint256& seed) noexcept; 18 19 void SeedRandomStateForTest(SeedRand seedtype) 20 { 21 constexpr auto RANDOM_CTX_SEED{"RANDOM_CTX_SEED"}; 22 23 // Do this once, on the first call, regardless of seedtype, because once 24 // MakeRandDeterministicDANGEROUS is called, the output of GetRandHash is 25 // no longer truly random. It should be enough to get the seed once for the 26 // process. 27 static const auto g_ctx_seed = []() -> std::optional<uint256> { 28 if (EnableFuzzDeterminism()) return {}; 29 // If RANDOM_CTX_SEED is set, use that as seed. 30 if (const char* num{std::getenv(RANDOM_CTX_SEED)}) { 31 if (auto num_parsed{uint256::FromUserHex(num)}) { 32 return *num_parsed; 33 } else { 34 std::cerr << RANDOM_CTX_SEED << " must consist of up to " << uint256::size() * 2 << " hex digits (\"0x\" prefix allowed), it was set to: '" << num << "'.\n"; 35 std::abort(); 36 } 37 } 38 // Otherwise use a (truly) random value. 39 return GetRandHash(); 40 }(); 41 42 g_seeded_g_prng_zero = seedtype == SeedRand::ZEROS; 43 if (EnableFuzzDeterminism()) { 44 Assert(g_seeded_g_prng_zero); // Only SeedRandomStateForTest(SeedRand::ZEROS) is allowed in fuzz tests 45 Assert(!g_used_g_prng); // The global PRNG must not have been used before SeedRandomStateForTest(SeedRand::ZEROS) 46 } 47 const uint256& seed{seedtype == SeedRand::FIXED_SEED ? g_ctx_seed.value() : uint256::ZERO}; 48 LogInfo("Setting random seed for current tests to %s=%s\n", RANDOM_CTX_SEED, seed.GetHex()); 49 MakeRandDeterministicDANGEROUS(seed); 50 }