Skip to content

Glamsterdam (Sepolia Amsterdam) L1 compatibility: op-geth pin, L1 header parser, batcher gas floor - #52

Merged
max-sanchez merged 3 commits into
hemifrom
glamsterdam-l1-compat
Oct 5, 2026
Merged

max-sanchez merged 3 commits into
hemifrom
glamsterdam-l1-compat

Conversation

@max-sanchez

Copy link
Copy Markdown

Why

Sepolia activates Glamsterdam (EL fork Amsterdam) at timestamp 1791294816 (2026-10-06 13:53:36 UTC). Post-fork L1 headers carry blockAccessListHash and slotNumber after requestsHash. op-node recomputes every L1 header hash from RPC JSON and from op-geth's types.Header (L1 head signal, batcher L1 tip) and rejects mismatches, so L1 tracking and derivation stop at the first post-fork block on the current image. --l1.trustrpc is not a workaround: the head-signal path hashes headers regardless.

What (three commits)

  1. deps: pin op-geth to hemilabs/op-geth f5c491e251ce (branch glamsterdam-l1-header-compat, tag glamsterdam-l1-header-compat-20261005), which decodes and hash-verifies Amsterdam headers, and adapt every call site to the op-geth API changes since the January pin. In particular op-node now passes the block gas limit into extraData validation, matching the consensus rule Hemi's op-geth already enforces (op-geth Error Handling and Logging around OVM -> EVM Tx hash map ethereum-optimism/optimism#89), so op-node and op-geth cannot disagree on a block.
  2. op-service/sources, op-batcher: map both fields in RPCHeader/CreateGethHeader (port of acceptance: support newer L1 forks ethereum-optimism/optimism#21920, op-node v1.19.5) and use a calldata gas floor valid on both sides of the fork (port of acceptance: test Glamsterdam L1 transition ethereum-optimism/optimism#21921, op-batcher v1.17.0). Hemi's batchers run with blobs, so the floor only matters if DA is ever switched.
  3. tests: fix stale hemitrap call sites so the touched packages' tests compile.

Relation to #50: the API adaptations are re-done by adapting call sites instead of vendoring; the #50 pin (a mid-ethereum-optimism#110 commit without the access-list hash), the txmgr floor formula (under-counts zero bytes), the pre-flight removal, the L1 tracker cache removal and the BatchPast case are deliberately not taken (reasons in the review notes).

Verification

  • go mod tidy is a no-op and go mod verify passes against the pushed op-geth commit; the shipped binaries build in plain module mode.
  • op-node's header path verified over all 53,300 official Amsterdam fixture headers (zero mismatches) and against a live in-process RPC for the head-signal and newHeads paths.
  • Three independent review rounds; no new test failures versus hemi (three previously uncompilable test packages now compile and pass).

Rollout

Merge, let CI build the image, and roll it out to op-node, op-batcher and op-proposer before 2026-10-06 13:53:36 UTC. No flag changes. The paired L2 EL must be hemi at 6ceee9fc3 or later.

🤖 Generated with Claude Code

max-sanchez and others added 3 commits October 5, 2026 08:11
…pt to its API

Point the go-ethereum replace at hemilabs/op-geth f5c491e251ce (branch
glamsterdam-l1-header-compat, on top of hemi 6ceee9fc3), which decodes and
hash-verifies post-Glamsterdam Sepolia L1 headers. This pin is load-bearing on
its own: op-node's L1 head signal (eth_getBlockByNumber latest / newHeads ->
*types.Header -> Hash()) and op-batcher's L1 tip hash headers through op-geth's
types.Header, which the --l1.trustrpc flag does not bypass, so only an image
built from this pin tracks Sepolia past the fork.

go.mod carries the two indirect requirements the new op-geth needs. go.sum
carries their entries plus the two entries for the op-geth pseudo-version,
computed from the local checkout with the same module-zip code go uses (the
method was validated by reproducing the previous pin's real hashes). The
op-geth commit is not on GitHub yet: push that branch unchanged (amending or
rebasing it changes the pseudo-version and the hashes), then run `go mod tidy`
and confirm it produces no diff; a checksum mismatch would mean the pushed
commit differs from f5c491e251ce.

The previous pin (e92aa4e51692, January 2026) predates two op-geth API changes.
Every call site, including tests, is adapted rather than vendoring old copies:

  - consensus/misc/eip1559.ValidateOptimismExtraData / ValidateHoloceneExtraData /
    ValidateJovianExtraData take the block gas limit (op-geth ethereum-optimism#89 rejects an
    elasticity larger than the gas limit, and a zero denominator/elasticity pair).
    op-node must apply the same rule when validating attributes against blocks,
    otherwise it could accept extraData that op-geth rejects, so the gas limit of
    the object whose extraData is validated is passed through
    checkExtraDataParamsMatch and the payload-to-SystemConfig path. Test fixtures
    that relied on arbitrary elasticity bytes or on a zero-elasticity attribute
    set are updated to realistic values and to the stricter op-geth messages (the
    blocks are rejected either way); cases for the translated-zero mismatch and
    for the gas-limit rule are added.
  - state.StateDB.SetCode/SetBalance take a tracing reason; core.ChainContext
    embeds consensus.ChainHeaderReader; ethdb.Database gained AncientBytes;
    core.NewBlockChain's Hemi signature. Mechanical updates in op-chain-ops,
    cannon, op-wheel, op-sync-tester and op-program.

Against the new pin `go build ./...` fails in a strict subset of the packages
that already fail on hemi with the old pin (check-jovian, op-simulate,
sync-tester, fakebeacon and op-wheel/cheat now compile); the shipped binaries
(op-node, op-batcher, op-proposer) build, and no package that built before
stops building.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ation

Sepolia activates Glamsterdam (EL fork Amsterdam) at timestamp 1791294816
(2026-10-06 13:53:36 UTC). Together with the op-geth pin bump, this fixes the
two remaining things in this repository that break at that block:

  - op-node rebuilds every L1 header it fetches from the RPC's JSON fields and
    rejects it if the recomputed hash differs from the one the node reported.
    Post-fork headers carry blockAccessListHash (EIP-7928) and slotNumber
    (EIP-7843) after requestsHash; without them the recomputed hash is wrong and
    L1 head tracking and derivation stop at the first post-fork block. Map both
    fields in RPCHeader and CreateGethHeader (port of
    ethereum-optimism#21920, shipped upstream in op-node v1.19.5). The
    tests pin a header produced by go-ethereum v1.17.7: the hash verifies with
    both fields, fails without either, and the same header without the fields
    hashes as a 21-field pre-fork header. Verified separately against all 3,277
    official execution-spec-tests Amsterdam blockchain fixtures (53,300 headers,
    zero mismatches).
  - op-batcher sets calldata batch transactions' gas limit from
    core.FloorDataGas, which op-geth deliberately keeps at the pre-Amsterdam
    (L2) rule. Sepolia will reject those transactions under EIP-2780/EIP-7976
    (15,000 base plus 64 gas per calldata byte, zero bytes included). Use the
    larger of the pre- and post-Amsterdam floors (port of
    ethereum-optimism#21921, shipped upstream in op-batcher v1.17.0),
    which is valid on both sides of the fork. Hemi's batchers currently run
    with --data-availability-type=blobs, whose transactions carry no calldata
    (gas limit 21,000, above Amsterdam's 15,000 intrinsic cost), so this matters
    only if the DA type is ever switched; the auto-DA cost model is left on
    pre-Amsterdam pricing for the same reason.

Receipts, logs, transactions, blob retrieval and the L1 blob base fee are
unaffected by the fork and need no change. Rebuild the image and roll it out to
op-node, op-batcher and op-proposer before the activation; --l1.trustrpc is not
a substitute, because the L1 head signal path hashes headers regardless.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s' tests compile

NewAttributesHandler, NewL1Retrieval, DataSourceFactory.OpenData and
NewRPCReceiptsFetcher gained a hemitrap flag without their tests being updated,
so the op-node/rollup/attributes, op-node/rollup/derive and op-service/sources
test packages did not compile. Pass the flag (disabled, preserving the original
test behaviour) so the Glamsterdam tests in those packages can run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@max-sanchez
max-sanchez merged commit 8394fdf into hemi Oct 5, 2026
7 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.

1 participant