Repository navigation
tests: pin the pm_lifecycle clock instead of starting at now() - #212
Merged
Merged
Conversation
The harness takes genesis from fc::time_point::now(), so every case in pm_lifecycle_suite silently changed the rules it ran under on the day a date-gated hardfork activated. HF16 (2026-10-31T00:00:00Z) requires a QC over the parent on every block, exempting only the activation block's child: a chain whose first block is past the fork date dies at block 3 with "No QC for head #2", before any of the 72 cases tests what it is about. Yesterday's failure in run 41054140379 was this class: the long leverage cases crossed the date inside one run (HARDFORK 16 at block 13712), so the same master commit was green in the morning and red at noon. Pin the case clock two days before HF16 — after HF15, before HF16, i.e. the rules that were live on 2026-10-30. Two days leave room for the longest case (~11 h 26 min of virtual time), and both bounds are compile-time constants, so the pair stays ordered forever. This is the same cure test_pm_audit_fixes.cpp already applied to its own time bomb. Voting for head, as the HF16-aware scenarios do, would not be enough here: after the fork the slot shortens to CHAIN_BLOCK_INTERVAL_HF16 (1 s), while this file's block-count arithmetic is written against 3 s blocks. Single-TU -fsyntax-only (testnet defines, nice/ionice): clean.
On1x
force-pushed
the
fix/pm-lifecycle-hf16-vote
branch
from
October 30, 2026 13:46
a647cba to
14cc5b5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
pm_lifecycle_suitestarts every case atfc::time_point::now(), and the harness takes genesis from the same clock (init_genesisindatabase.cpp). So these 72 cases silently change the rules they run under on the day a date-gated hardfork activates.HF16 (
CHAIN_HARDFORK_16_TIME, 2026-10-31T00:00:00Z) requires a QC over the parent on every block, exempting only the activation block's child (block_needs_parent_qc, round-anchor clause). A chain whose first block is already past the fork date therefore dies at block 3 withNo QC for head #2, before any case tests what it is about:That failure was run 41054140379 (PR #211, which only touches
share/vizd/vizd.sh). The long leverage cases were the first to cross the date inside one run — the same master commit was green at 08:21 UTC and red at 12:34 UTC. From 00:00 UTC tonight it is not one case and not two jobs: all 72 cases, in all threeconsensus_simjobs.Change
Pin the case clock two days before HF16 — after HF15, before HF16, i.e. exactly the rules that were live on 2026-10-30. Two days of headroom for the longest case (~11 h 26 min of virtual time); both bounds are compile-time constants, so the pair stays ordered forever. One helper plus a mechanical replacement of the 72
startlines.This is the cure
test_pm_audit_fixes.cppalready applied to its own time bomb (its header says so).test_agent_access.cpppins the same way.Why not "vote for head"
Voting, as the HF16-aware scenarios do, is not enough here: after the fork the slot shortens to
CHAIN_BLOCK_INTERVAL_HF16(1 s) and_generate_blockasserts the producer is the validator scheduled for the slot ofwhen. This file's block-count arithmetic (blocks = (grace + 240) / CHAIN_BLOCK_INTERVAL + 80and friends) is written against 3 s blocks, so a run that legitimately crossed the fork would under-cover its deadlines. Pinning keeps the file honest: it tests PM lifecycle under pre-HF16 rules, and HF16 itself is covered bytest_hf16_boundary.cpp/test_hf16_production_safety.cpp.Scope check
Four scenario files take the real wall clock; the other three vote for head already or pin (see above), and the rest start at 2026-01-01 or epoch. This file was the only one that both starts at
now()and never votes.Verification
-fsyntax-only(testnet defines,nice -n 19 ionice -c3): clean.No QC for headmust not appear.Merge is the owner's, as usual.