Skip to content

feat(L1): bake the Cobalt speedup activation into AggregateVerifier - #433

Closed
0xth4nh wants to merge 1 commit into
mainfrom
feat/verifier-cobalt-fork-timestamp
Closed

feat(L1): bake the Cobalt speedup activation into AggregateVerifier#433
0xth4nh wants to merge 1 commit into
mainfrom
feat/verifier-cobalt-fork-timestamp

Conversation

@0xth4nh

@0xth4nh 0xth4nh commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #431 (merged).

What changed?

AggregateVerifier no longer reads the fast-block activation from ProtocolVersions.

  • ScheduleConfig gains uint64 fastBlockActivationTimestamp, exposed as uint64 public immutable FAST_BLOCK_ACTIVATION_TIMESTAMP.
  • FAST_BLOCK_UPGRADE_INDEX (the hardcoded getSchedule()[12] lookup) is deleted. _firstFastBlock() now derives the boundary from the immutable and the L2 genesis/block-time immutables.
  • 0 means "speedup unscheduled" — every game uses the slow-block intervals. This lets the implementation ship before the activation time is agreed, at the cost of a redeploy once it is.
  • Deploy path gains a multiproofFastBlockActivationTimestamp config key (defaults to 0), plumbed through DeployConfigSystemDeploy with a uint64 overflow check.
  • Semver 0.2.00.3.0; snapshots/semver-lock.json regenerated (only the AggregateVerifier entry moves).

PROTOCOL_VERSIONS is deliberately retained — activatedScheduleId(claimTimestamp) still drives scheduleId pinning. Only the interval selection stops depending on the registry.

Why?

ProtocolVersions will not be activated for Cobalt. It runs in metrics-only mode on sepolia and mainnet (--upgrade-signal.mode), so index 12 of getSchedule() is never written on those chains.

The old lookup fails open: an index past the end of the schedule returns type(uint256).max, so _firstFastBlock() sits beyond every real block number and the verifier keeps handing out slow-block intervals forever. On a chain that has already switched to 200ms blocks, that is a silent mismatch between the proposer's cadence and the verifier's expectation — no revert, no event, just wrong intervals.

An immutable also removes a class of race the registry has: every game backed by a given implementation resolves the same boundary, and there is no mutation that can move an in-flight game across it. Changing the activation means deploying a new implementation, which is a new game type in the factory, so it can never apply retroactively.

How to test?

just build-go-ffi
forge test --match-contract AggregateVerifier

The new case is the one that pins the behaviour change:

forge test --match-test test_intervalsForStartingBlock_activationIndependentOfRegistry_succeeds -vv

It writes a ProtocolVersions schedule that stops one entry short of index 12 — i.e. a chain that never signalled the speedup — asserts getSchedule().length == 12, then deploys a verifier with fastBlockActivationTimestamp = L2_GENESIS_TIMESTAMP + 100 and checks the boundary lands at block 50 (divUp(100, 2)): block 49 gets the slow interval pair, block 50 gets the fast pair. On main this test cannot pass — with the registry short of index 12 the verifier stays slow at every block.

Full suite on this branch: 1232 passed, 0 failed, 1 skipped.

Deploy-time check: multiproofFastBlockActivationTimestamp is absent from every existing config, so readUintOr(..., 0) yields 0 and existing deployments keep slow intervals — forge test --match-contract SystemDeploy covers that path unchanged.

Replace the ProtocolVersions schedule lookup in `_firstFastBlock()` with an
immutable activation timestamp supplied at construction.

`ProtocolVersions` is not being activated for Cobalt — it runs in metrics-only
mode on sepolia and mainnet — so index 12 of `getSchedule()` will never be
written there. The old lookup fails open: an unwritten entry returns
`type(uint256).max`, which keeps every game on the slow-block intervals while
L2 runs at 200ms, silently.

`PROTOCOL_VERSIONS` is retained for `activatedScheduleId` scheduleId pinning.

Co-Authored-By: Claude <noreply@anthropic.com>
@cb-heimdall

Copy link
Copy Markdown
Collaborator

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

@0xth4nh

0xth4nh commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing — we're keeping ProtocolVersions as the single source for the activation time rather than introducing a second one.

@0xth4nh 0xth4nh closed this Sep 8, 2026
@0xth4nh
0xth4nh deleted the feat/verifier-cobalt-fork-timestamp branch September 8, 2026 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants