Skip to content

fix: alt da: handle no commitments case when finalized head is updated#18866

Merged
raffaele-oplabs merged 3 commits intoethereum-optimism:developfrom
draghi444:fix/altda-no-commitments-finality
Feb 10, 2026
Merged

fix: alt da: handle no commitments case when finalized head is updated#18866
raffaele-oplabs merged 3 commits intoethereum-optimism:developfrom
draghi444:fix/altda-no-commitments-finality

Conversation

@draghi444
Copy link
Contributor

@draghi444 draghi444 commented Jan 20, 2026

Description

When there are no alt-DA commitments being tracked (e.g., batcher is using calldata/blobs instead of alt-DA), the updateFinalizedHead function was overwriting finalizedHead with lastPrunedCommitment, which could be zero or stale.

With this fix, the finalizedHead in the "no commitments" case should be managed by updateFinalizedFromL1 (called from AdvanceL1Origin), which calculates it as l1FinalizedHead - challengeWindow. The fix is in the updateFinalizedHead function and aims to preserve that value when there are no commitments to track.

Tests

Added TestUpdateFinalizedHead with 5 sub-tests covering:

  • Verifies that when no commitments exist, the existing finalizedHead is preserved
  • Verifies that after all commitments are pruned, subsequent Finalize calls preserve finalizedHead
  • Verifies that with pending commitments, Prune is called and lastPrunedCommitment is used
  • Verifies multiple commitments are pruned correctly
  • Verifies the signal handler receives the correct finalizedHead

@draghi444 draghi444 requested review from a team as code owners January 20, 2026 19:02
@draghi444 draghi444 requested a review from serpixel January 20, 2026 19:02
@sebastianst
Copy link
Member

sebastianst commented Feb 4, 2026

/ci authorize f022e4d

Copy link
Member

@sebastianst sebastianst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Disclaimer: Did a manual review & sanity check with @claude, whose review follows below.

Code Review: fix: alt da: handle no commitments case when finalized head is updated

Overview

This PR fixes a bug where the updateFinalizedHead function was incorrectly overwriting finalizedHead with lastPrunedCommitment even when there are no alt-DA commitments being tracked. This could result in finalizedHead being set to a zero or stale value when the batcher is using calldata/blobs instead of alt-DA.

The fix: Early return from updateFinalizedHead when state.NoCommitments() is true, preserving the finalizedHead that was set by updateFinalizedFromL1.

Analysis

Code correctness: ✅ Good

The fix is logically sound:

  • When no commitments are tracked, finalizedHead is managed by updateFinalizedFromL1 (called from AdvanceL1Origin), which calculates it as l1FinalizedHead - challengeWindow
  • The early return preserves this value rather than overwriting it with lastPrunedCommitment
  • The l1FinalizedHead is still updated before the early return, which is correct

Code style: ✅ Good

  • The comment explains why this early return is needed, not just what it does
  • Follows existing code conventions in the file

Test coverage: ✅ Comprehensive

The new test TestUpdateFinalizedHead covers:

  1. No commitments → preserves existing finalizedHead
  2. No commitments after all pruned → preserves existing finalizedHead
  3. With pending commitments → prunes and uses lastPrunedCommitment
  4. Multiple commitments → prunes correctly up to l1Finalized
  5. Signal handler → receives correct finalizedHead value

Minor Questions (non-blocking)

  1. Race condition consideration: The test directly sets da.finalizedHead to simulate what updateFinalizedFromL1 would do. In production, is there a scenario where Finalize could be called before updateFinalizedFromL1 has set the initial value? If so, finalizedHead would remain at its zero value.

  2. Edge case - transition from "has commitments" to "no commitments": After all commitments are pruned, lastPrunedCommitment still holds the last pruned value. The fix preserves the externally-set finalizedHead in this case — just want to confirm this is always the desired behavior.

Summary

Verdict: Approve 👍

This is a well-targeted fix with comprehensive test coverage. The logic is correct and the tests verify the key scenarios.

@sebastianst
Copy link
Member

/ci authorize f022e4d

@sebastianst sebastianst removed the request for review from serpixel February 10, 2026 13:45
@sebastianst sebastianst disabled auto-merge February 10, 2026 13:45
@sebastianst sebastianst disabled auto-merge February 10, 2026 17:45
@raffaele-oplabs raffaele-oplabs added this pull request to the merge queue Feb 10, 2026
Merged via the queue into ethereum-optimism:develop with commit 95cde13 Feb 10, 2026
98 checks passed
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.

op-alt-da: op-proposer fails with GameAlreadyExists due to stalled finalized head

3 participants