From 2a4ef42d34edf6499e4185c2fc7c6fed8b071ae7 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Fri, 19 Jun 2026 19:31:43 +0800 Subject: [PATCH] fuzz: share a single FakeNodeClock in the chainman-resetting fuzz targets cmpctblock, process_message, process_messages, and utxo_snapshot rebuild the chainman from a helper called out of the target body, while the body itself holds or mutates mocktime through a FakeNodeClock. Since FakeNodeClock is a LimitOne type, the helper cannot hold one of its own and reaches for the SetMockTime() global mutator instead, so it is unclear which of the two owns mocktime. Add a GetFakeNodeClock() that returns a single process-wide FakeNodeClock and route these targets through it, replacing their local FakeNodeClock and genesis-time SetMockTime() calls. It is initialized with 0s rather than a default-constructed FakeNodeClock{}, which would read mocktime at whatever point the static happens to be constructed. Every user sets the time before use anyway. --- src/test/fuzz/cmpctblock.cpp | 8 ++++---- src/test/fuzz/process_message.cpp | 6 +++--- src/test/fuzz/process_messages.cpp | 6 +++--- src/test/fuzz/utxo_snapshot.cpp | 4 ++-- src/test/util/time.h | 6 ++++++ 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/test/fuzz/cmpctblock.cpp b/src/test/fuzz/cmpctblock.cpp index e2aea86a89e..ffa67d4bb63 100644 --- a/src/test/fuzz/cmpctblock.cpp +++ b/src/test/fuzz/cmpctblock.cpp @@ -109,7 +109,7 @@ public: void ResetChainmanAndMempool(TestingSetup& setup) { - SetMockTime(Params().GenesisBlock().Time()); + GetFakeNodeClock().set(Params().GenesisBlock().Time()); bilingual_str error{}; setup.m_node.mempool.reset(); @@ -163,7 +163,7 @@ FUZZ_TARGET(cmpctblock, .init = initialize_cmpctblock) SeedRandomStateForTest(SeedRand::ZEROS); FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - FakeNodeClock clock{1610000000s}; + GetFakeNodeClock().set(1610000000s); FakeSteadyClock steady_clock; auto setup = g_setup; @@ -453,10 +453,10 @@ FUZZ_TARGET(cmpctblock, .init = initialize_cmpctblock) [&]() { // Set mock time randomly or to tip's time. if (fuzzed_data_provider.ConsumeBool()) { - clock.set(ConsumeTime(fuzzed_data_provider)); + GetFakeNodeClock().set(ConsumeTime(fuzzed_data_provider)); } else { const NodeSeconds tip_time = WITH_LOCK(::cs_main, return chainman.ActiveChain().Tip()->Time()); - clock.set(tip_time); + GetFakeNodeClock().set(tip_time); } sent_net_msg = false; diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 7712ea6fcda..b4a08cfdd29 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -46,7 +46,7 @@ std::string_view LIMIT_TO_MESSAGE_TYPE{}; void ResetChainman(TestingSetup& setup) { - SetMockTime(setup.m_node.chainman->GetParams().GenesisBlock().Time()); + GetFakeNodeClock().set(setup.m_node.chainman->GetParams().GenesisBlock().Time()); setup.m_node.chainman.reset(); setup.m_make_chainman(); setup.LoadVerifyActivateChainstate(); @@ -83,7 +83,7 @@ FUZZ_TARGET(process_message, .init = initialize_process_message) connman.Reset(); auto& chainman{static_cast(*node.chainman)}; const auto block_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())}; - FakeNodeClock clock{1610000000s}; // any time to successfully reset ibd + GetFakeNodeClock().set(1610000000s); // any time to successfully reset ibd FakeSteadyClock steady_clock; chainman.ResetIbd(); chainman.DisableNextWrite(); @@ -117,7 +117,7 @@ FUZZ_TARGET(process_message, .init = initialize_process_message) connman.AddTestNode(p2p_node); FillNode(fuzzed_data_provider, connman, p2p_node); - clock.set(ConsumeTime(fuzzed_data_provider)); + GetFakeNodeClock().set(ConsumeTime(fuzzed_data_provider)); CSerializedNetMsg net_msg; net_msg.m_type = random_message_type; diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index 89c03fa6183..cec2bc3fb5d 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -40,7 +40,7 @@ TestingSetup* g_setup; void ResetChainman(TestingSetup& setup) { - SetMockTime(setup.m_node.chainman->GetParams().GenesisBlock().Time()); + GetFakeNodeClock().set(setup.m_node.chainman->GetParams().GenesisBlock().Time()); setup.m_node.chainman.reset(); setup.m_make_chainman(); setup.LoadVerifyActivateChainstate(); @@ -72,7 +72,7 @@ FUZZ_TARGET(process_messages, .init = initialize_process_messages) connman.Reset(); auto& chainman{static_cast(*node.chainman)}; const auto block_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())}; - FakeNodeClock clock{1610000000s}; // any time to successfully reset ibd + GetFakeNodeClock().set(1610000000s); // any time to successfully reset ibd FakeSteadyClock steady_clock; chainman.ResetIbd(); chainman.DisableNextWrite(); @@ -110,7 +110,7 @@ FUZZ_TARGET(process_messages, .init = initialize_process_messages) LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 30) { const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::MESSAGE_TYPE_SIZE).c_str()}; - clock.set(ConsumeTime(fuzzed_data_provider)); + GetFakeNodeClock().set(ConsumeTime(fuzzed_data_provider)); CSerializedNetMsg net_msg; net_msg.m_type = random_message_type; diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index 815517bc55c..e4098457916 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -73,7 +73,7 @@ void initialize_chain() const auto params{CreateChainParams(ArgsManager{}, ChainType::REGTEST)}; static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)}; g_chain = &chain; - SetMockTime(chain.back()->Time()); + GetFakeNodeClock().set(chain.back()->Time()); // Make sure we can generate a valid snapshot. sanity_check_snapshot(); @@ -104,7 +104,7 @@ void utxo_snapshot_fuzz(FuzzBufferType buffer) { SeedRandomStateForTest(SeedRand::ZEROS); FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - FakeNodeClock clock{ConsumeTime(fuzzed_data_provider, /*min=*/1296688602)}; // regtest genesis block timestamp + GetFakeNodeClock().set(ConsumeTime(fuzzed_data_provider, /*min=*/1296688602)); // regtest genesis block timestamp auto& setup{*g_setup}; bool dirty_chainman{false}; // Reuse the global chainman, but reset it when it is dirty auto& chainman{*setup.m_node.chainman}; diff --git a/src/test/util/time.h b/src/test/util/time.h index 213d7b2764c..e20df3fa75b 100644 --- a/src/test/util/time.h +++ b/src/test/util/time.h @@ -76,4 +76,10 @@ public: void operator-=(std::chrono::seconds d) { set(m_t -= d); } }; +inline FakeNodeClock& GetFakeNodeClock() +{ + static FakeNodeClock g_fake_node_clock{0s}; + return g_fake_node_clock; +} + #endif // BITCOIN_TEST_UTIL_TIME_H