Skip to content

test: close root-cause race in warpL2TimeAtLeastBy timestamp check - #24285

Closed
AztecBot wants to merge 1 commit into
merge-train/spartan-v5from
cb/harden-cheat-code-timestamp-race
Closed

test: close root-cause race in warpL2TimeAtLeastBy timestamp check#24285
AztecBot wants to merge 1 commit into
merge-train/spartan-v5from
cb/harden-cheat-code-timestamp-race

Conversation

@AztecBot

Copy link
Copy Markdown
Collaborator

Why

The merge-train/spartan-v5 train PR (#24272) was dequeued from the merge queue. Investigating the two merge-queue runs showed two distinct causes:

  • First dequeue (merge-queue run at 18:34 UTC, before test: retry composed cheat code timestamp race #24279 landed): a genuine test failure — e2e_cheat_codes › warpL2TimeAtLeastBy with sub-slot duration auto-adjusts to next slot threw warpL2TimeAtLeastTo: target timestamp <T> is not in the future (current L1 timestamp is <T+11>). This is the composed cheat-code timestamp race.
  • Most recent dequeue (merge-queue run at 01:40 UTC): infrastructure, not a test failure — the x8-full grind's build instance went unreachable (SSM command … did not succeed … status=Failed, statusDetails=Undeliverable, responseCode=-1) after ~76 min; the other 7 grinds passed with #24279 present.

#24279 mitigated the race at the test level with a 5-attempt retry helper. This PR removes the race at its root so the retry is no longer load-bearing.

The race

warpL2TimeAtLeastBy reads the L1 timestamp to derive target = max(L2, L1) + duration, then delegated to warpL2TimeAtLeastTo, which re-read L1 for its future-check guard. A live sequencer can warp L1 forward by a full slot between those two reads, so for a small sub-slot duration the freshly-read L1 overtakes target and the guard throws is not in the future — even though the downstream slot/mine logic uses fresh rollup state and would have advanced time correctly.

The fix

Funnel both public methods through a private #warpL2TimeAtLeastTo(node, targetBigInt, currentTimestamp) that takes the caller's already-observed L1 timestamp. warpL2TimeAtLeastBy now reuses the single L1 read its target was derived from, so target = base + duration (with base ≥ currentL1 and duration > 0) is always strictly in the future — the throw window is gone. The public warpL2TimeAtLeastTo still reads L1 itself for direct callers, preserving the warpL2TimeAtLeastTo with past timestamp throws behavior. Public signatures are unchanged.

Testing

  • Static: change is isolated to cheat_codes.ts; all external callers use the unchanged public methods. A full local ./bootstrap.sh ci was not runnable in this environment (it orchestrates remote EC2 grind instances and the composed e2e_cheat_codes test needs a live docker-compose network), so verification runs through the train's merge-queue CI.

Created by claudebox · group: slackbot

warpL2TimeAtLeastBy reads the L1 timestamp to derive its target, then
warpL2TimeAtLeastTo re-read L1 for its future-check guard. A live sequencer
can warp L1 forward by a full slot between the two reads, pushing the small
sub-slot target into the past and throwing 'is not in the future' even though
the downstream slot/mine logic uses fresh rollup state and would advance time
correctly. This is the composed e2e_cheat_codes flake that #24279 mitigated
with a test-level retry.

Funnel both public methods through a private #warpL2TimeAtLeastTo that takes
the caller's already-observed L1 timestamp, so warpL2TimeAtLeastBy reuses the
single read its target was derived from. target = base + duration (base >=
currentL1, duration > 0) is then always strictly in the future, closing the
race window at its root. Public signatures are unchanged; the direct
warpL2TimeAtLeastTo guard (and its 'past timestamp throws' test) still reads
L1 itself.
@AztecBot AztecBot added ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure claudebox Owned by claudebox. it can push to this PR. labels Jun 25, 2026
@AztecBot

Copy link
Copy Markdown
Collaborator Author

Automatically closing this stale claudebox draft PR (no updates for 5+ days). Re-open if still needed.

@AztecBot AztecBot closed this Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure claudebox Owned by claudebox. it can push to this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant