Skip to content

exec: partial block at snapshot boundary passes incomplete receipts to Finalize #20452

Description

@mh0lt

Summary

When resuming execution from a snapshot boundary with initialBlockTxOffset > 0 (partial block), the receipts passed to engine.Finalize() only contain receipts from the re-executed portion (txs startTxIndex to end), not the full block. This causes the Pectra requests hash validation to fail because deposit request extraction needs ALL receipt logs.

Impact

  • Prevents starting execution from any snapshot boundary that falls mid-block after Pectra activation
  • Affects both serial (exec3_serial.go:436) and parallel (exec3_parallel.go:2389) executors
  • The serial executor skips post-validation for partial blocks (startTxIndex > 0) but still runs Finalize which can return an error

Root Cause

Receipt building accumulates receipts only from the re-executed portion:

  • Serial: blockReceipts starts from startTxIndex (exec3_serial.go:489)
  • Parallel: receipts built from be.results which only has re-executed txs (exec3_parallel.go:2310)

The prior receipts (txs 0 to startTxIndex-1) exist in the RCache domain history but are not loaded.

Proposed Fix

For partial blocks, load prior receipts from rawdb.ReadReceiptsCacheV2 (or reconstruct from rawtemporaldb.ReceiptAsOf) for txNums before the re-execution start, and prepend them to the receipts list before calling Finalize.

Workaround

Pass skipReceiptsEval=true to Finalize for partial blocks. The syscall state writes still execute; only the requests hash validation is skipped. The commitment trie root check catches any state inconsistency.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions