test: Use FakeNodeClock in more places
What changed, and why it matters
This commit only changes Bitcoin Core's internal test code. It replaces the old global SetMockTime() helper with a new local FakeNodeClock object in three test files so that test time adjustments are scoped to each test and easier to read. There is no change to the actual Bitcoin node software that users run, so it cannot affect live wallets, transactions, or network security.
No security action needed. Treat as a normal code-quality/test-maintenance change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch is a pure test refactor in miner_tests.cpp, peerman_tests.cpp, and wallet/test/wallet_tests.cpp. It switches from the global mock-time facility (SetMockTime/GetTime) to a FakeNodeClock instance that is passed around or kept locally. The behavior under test is unchanged; only the way simulated time is set and advanced is cleaned up. No production code, consensus logic, P2P protocol handling, or wallet runtime code is modified.
Changed components
src/test/miner_tests.cppsrc/test/peerman_tests.cppsrc/wallet/test/wallet_tests.cppInspect captured patch +24 / −23
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index fd9559b5..2c1983fa 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -26,13 +26,13 @@
#include <test/util/common.h>
#include <test/util/setup_common.h>
#include <test/util/transaction_utils.h>
+#include <test/util/time.h>
#include <test/util/txmempool.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/check.h>
#include <util/feefrac.h>
#include <util/strencodings.h>
-#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <versionbits.h>
@@ -342,6 +342,8 @@ std::vector<CTransactionRef> CreateBigSigOpsCluster(const CTransactionRef& first
void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight)
{
+ FakeNodeClock clock{};
+
Txid hash;
CMutableTransaction tx;
TestMemPoolEntryHelper entry;
@@ -565,7 +567,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
LOCK(tx_mempool.cs);
// non-final txs in mempool
- SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
+ clock.set(std::chrono::seconds{m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1});
const int flags{LOCKTIME_VERIFY_SEQUENCE};
// height map
std::vector<int> prevheights;
@@ -670,7 +672,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
ancestor->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
}
m_node.chainman->ActiveChain().Tip()->nHeight++;
- SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
+ clock.set(std::chrono::seconds{m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1});
block_template = mining->createNewBlock(options, /*cooldown=*/false);
BOOST_REQUIRE(block_template);
@@ -896,12 +898,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
TestBasicMining(scriptPubKey, txFirst, baseheight);
m_node.chainman->ActiveChain().Tip()->nHeight--;
- SetMockTime(0);
TestPackageSelection(scriptPubKey, txFirst);
m_node.chainman->ActiveChain().Tip()->nHeight--;
- SetMockTime(0);
TestPrioritisedMining(scriptPubKey, txFirst);
}
diff --git a/src/test/peerman_tests.cpp b/src/test/peerman_tests.cpp
index 9044e9c2..a2d88ea5 100644
--- a/src/test/peerman_tests.cpp
+++ b/src/test/peerman_tests.cpp
@@ -12,8 +12,8 @@
#include <protocol.h>
#include <sync.h>
#include <test/util/setup_common.h>
+#include <test/util/time.h>
#include <util/check.h>
-#include <util/time.h>
#include <validation.h>
#include <validationinterface.h>
@@ -27,17 +27,17 @@ BOOST_FIXTURE_TEST_SUITE(peerman_tests, RegTestingSetup)
/** Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers */
static constexpr int64_t NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS = 144;
-static void mineBlock(node::NodeContext& node, std::chrono::seconds block_time)
+static void mineBlock(node::NodeContext& node, FakeNodeClock& clock, std::chrono::seconds block_time)
{
auto curr_time = GetTime<std::chrono::seconds>();
- SetMockTime(block_time); // update time so the block is created with it
+ clock.set(block_time); // update time so the block is created with it
auto mining{interfaces::MakeMining(node)};
auto block_template{mining->createNewBlock({}, /*cooldown=*/false)};
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce;
block.fChecked = true; // little speedup
- SetMockTime(curr_time); // process block at current time
+ clock.set(curr_time); // process block at current time
Assert(node.chainman->ProcessNewBlock(std::make_shared<const CBlock>(block), /*force_processing=*/true, /*min_pow_checked=*/true, nullptr));
node.validation_signals->SyncWithValidationInterfaceQueue(); // drain events queue
}
@@ -45,6 +45,7 @@ static void mineBlock(node::NodeContext& node, std::chrono::seconds block_time)
// Verifying when network-limited peer connections are desirable based on the node's proximity to the tip
BOOST_AUTO_TEST_CASE(connections_desirable_service_flags)
{
+ FakeNodeClock clock{};
std::unique_ptr<PeerManager> peerman = PeerManager::make(*m_node.connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.warnings, {});
auto consensus = m_node.chainman->GetParams().GetConsensus();
@@ -58,15 +59,15 @@ BOOST_AUTO_TEST_CASE(connections_desirable_service_flags)
int tip_block_height = tip->nHeight;
peerman->SetBestBlock(tip_block_height, std::chrono::seconds{tip_block_time});
- SetMockTime(tip_block_time + 1); // Set node time to tip time
+ clock.set(std::chrono::seconds{tip_block_time + 1}); // Set node time to tip time
BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
// Check we don't disallow limited peers connections when we are behind but still recoverable (below the connection safety window)
- SetMockTime(GetTime<std::chrono::seconds>() + std::chrono::seconds{consensus.nPowTargetSpacing * (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS - 1)});
+ clock += std::chrono::seconds{consensus.nPowTargetSpacing * (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS - 1)};
BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
// Check we disallow limited peers connections when we are further than the limited peers safety window
- SetMockTime(GetTime<std::chrono::seconds>() + std::chrono::seconds{consensus.nPowTargetSpacing * 2});
+ clock += std::chrono::seconds{consensus.nPowTargetSpacing * 2};
BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
// By now, we tested that the connections desirable services flags change based on the node's time proximity to the tip.
@@ -75,15 +76,15 @@ BOOST_AUTO_TEST_CASE(connections_desirable_service_flags)
// First, verify a block in the past doesn't enable limited peers connections
// At this point, our time is (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1) * 10 minutes ahead the tip's time.
- mineBlock(m_node, /*block_time=*/std::chrono::seconds{tip_block_time + 1});
+ mineBlock(m_node, clock, /*block_time=*/std::chrono::seconds{tip_block_time + 1});
BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
// Verify a block close to the tip enables limited peers connections
- mineBlock(m_node, /*block_time=*/GetTime<std::chrono::seconds>());
+ mineBlock(m_node, clock, /*block_time=*/GetTime<std::chrono::seconds>());
BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
// Lastly, verify the stale tip checks can disallow limited peers connections after not receiving blocks for a prolonged period.
- SetMockTime(GetTime<std::chrono::seconds>() + std::chrono::seconds{consensus.nPowTargetSpacing * NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1});
+ clock += std::chrono::seconds{consensus.nPowTargetSpacing * NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1};
BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
}
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 9d890c8f..11d4f4bf 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -246,12 +246,12 @@ BOOST_FIXTURE_TEST_CASE(write_wallet_settings_concurrently, TestingSetup)
/*num_expected_wallets=*/0);
}
-static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
+static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lockTime, std::chrono::seconds mock_time, int64_t blockTime)
{
CMutableTransaction tx;
TxState state = TxStateInactive{};
tx.nLockTime = lockTime;
- SetMockTime(mockTime);
+ FakeNodeClock clock{mock_time};
CBlockIndex* block = nullptr;
if (blockTime > 0) {
LOCK(cs_main);
@@ -277,24 +277,24 @@ static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lock
BOOST_AUTO_TEST_CASE(ComputeTimeSmart)
{
// New transaction should use clock time if lower than block time.
- BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 1, 100, 120), 100);
+ BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 1, 100s, 120), 100);
// Test that updating existing transaction does not change smart time.
- BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 1, 200, 220), 100);
+ BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 1, 200s, 220), 100);
// New transaction should use clock time if there's no block time.
- BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 2, 300, 0), 300);
+ BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 2, 300s, 0), 300);
// New transaction should use block time if lower than clock time.
- BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 3, 420, 400), 400);
+ BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 3, 420s, 400), 400);
// New transaction should use latest entry time if higher than
// min(block time, clock time).
- BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 4, 500, 390), 400);
+ BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 4, 500s, 390), 400);
// If there are future entries, new transaction should use time of the
// newest entry that is no more than 300 seconds ahead of the clock time.
- BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 5, 50, 600), 300);
+ BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 5, 50s, 600), 300);
}
void TestLoadWallet(const std::string& name, DatabaseFormat format, std::function<void(std::shared_ptr<CWallet>)> f)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.