/Users/mcomp/contrib/bitcoin/src/test/util/random.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 1 | { |
21 | 1 | 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 | 1 | static const auto g_ctx_seed = []() -> std::optional<uint256> { |
28 | 1 | if constexpr (G_FUZZING) return {}; |
29 | | // If RANDOM_CTX_SEED is set, use that as seed. |
30 | 1 | if (const char* num{std::getenv(RANDOM_CTX_SEED)}) { |
31 | 1 | if (auto num_parsed{uint256::FromUserHex(num)}) { |
32 | 1 | return *num_parsed; |
33 | 1 | } else { |
34 | 1 | 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 | 1 | std::abort(); |
36 | 1 | } |
37 | 1 | } |
38 | | // Otherwise use a (truly) random value. |
39 | 1 | return GetRandHash(); |
40 | 1 | }(); |
41 | | |
42 | 1 | g_seeded_g_prng_zero = seedtype == SeedRand::ZEROS; |
43 | 1 | if constexpr (G_FUZZING) { |
44 | 1 | Assert(g_seeded_g_prng_zero); // Only SeedRandomStateForTest(SeedRand::ZEROS) is allowed in fuzz tests |
45 | 1 | Assert(!g_used_g_prng); // The global PRNG must not have been used before SeedRandomStateForTest(SeedRand::ZEROS) |
46 | 1 | } |
47 | 1 | const uint256& seed{seedtype == SeedRand::FIXED_SEED ? g_ctx_seed.value() : uint256::ZERO}; |
48 | 1 | LogInfo("Setting random seed for current tests to %s=%s\n", RANDOM_CTX_SEED, seed.GetHex()); |
49 | 1 | MakeRandDeterministicDANGEROUS(seed); |
50 | 1 | } |