Skip to content

Validate a Gloas/Amsterdam block in the simulation role - #571

Open
0w3n-d wants to merge 1 commit into
od/gloas-bal-wire-step2from
od/gloas-sim-amsterdam-step3
Open

Validate a Gloas/Amsterdam block in the simulation role#571
0w3n-d wants to merge 1 commit into
od/gloas-bal-wire-step2from
od/gloas-sim-amsterdam-step3

Conversation

@0w3n-d

@0w3n-d 0w3n-d commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Issue: #561 (step 3 of 6)

What this PR does

Teaches the simulation role to validate a Gloas/Amsterdam block. The header's
EIP-7928 block_access_list_hash and EIP-7843 slot_number come from the
submission — the wire ExecutionPayloadV3 carries neither — and the list is
then checked against the one execution recomputes. The relay routes Gloas to
SSZ simulators again, sending the Gloas wire shape so the list travels with it.

Two decisions worth review:

  • The list is hashed as received, never re-encoded. The block hash commits
    to those exact bytes, so re-encoding could silently change it. This matches
    ethrex's own engine_newPayloadV5.
  • A missing recomputed list fails the block. ethrex skips its BAL check
    when the VM returns no list (if let Some(bal) = &bal); a relay simulator
    cannot afford that, so this fails closed instead.

Two checks fall out of setting the header field, rather than being added:

  • A list that disagrees with the block hash the builder signed is caught by the
    existing hash check.
  • A well-formed list that is not what execution produced is caught by
    validate_block_access_list_hash, which also enforces EIP-7928's index
    bounds and size cap.

It also closes a hole step 2 left: decode_dehydrated and decode_merge would
decode a Gloas submission into a Fulu shape and drop its list. Both now refuse
the combination. Step 3 is what starts routing Gloas to simulators, so leaving
it would have been exploitable.

What this PR deliberately does not do

  • The merged route still refuses Gloas. /validate_merged keeps its
    shorter fork list; the merging protocol carries ExecutionPayloadV3 only.
    That is step 5.
  • No building. The building role still produces Fulu blocks. That is step 4.
  • The reth simulator is untouched beyond keeping it compiling, per Gloas (ePBS) support in helix-simulator #518.
  • No request-struct refactor. validate and validate_merged now take
    eight and nine arguments, silenced with #[allow]. Grouping them touches all
    49 call sites and belongs in its own change.

Tests

Tests were written first and approved before implementation, as in every
earlier step of this issue. 20 new tests; 399 pass in total.

The fixture gained Fixture::amsterdam(), which needs the two EIP-8282
predeploys in genesis — without them every Amsterdam block is invalid. The
first test exists only to prove the fixture really is on Amsterdam, so the rest
cannot silently pass under Fulu rules.

Existing call sites now pass built.amsterdam() rather than a literal None,
so the whole pre-existing suite re-runs unchanged for Fulu and the same
assertions cover Amsterdam wherever an Amsterdam fixture is used.

Covered:

  • the fixture builds a block with a list and a slot number, and the header's
    hash is keccak of the submitted bytes
  • an Amsterdam payload round-trips to the same block hash
  • a valid Amsterdam block is accepted, end to end through /validate in the
    relay's own request shape
  • a tampered list is rejected (block hash mismatch)
  • a well-formed list that contradicts execution is rejected, asserting the
    reason is the access list and not another post-execution check
  • an empty list is rejected by name, not as a hash mismatch
  • a fork and payload that disagree are rejected, in both directions
  • the relay's SSZ request carries the list and names its shape; every other
    fork's bytes are unchanged
  • dehydrated and mergeable Gloas are refused

Reviewer checklist

  • CI (lint, unit-test) is green
  • Matches the linked issue/step
  • No unexplained scope creep or unrelated files touched

Set the header's EIP-7928 block access list hash and EIP-7843 slot number
from the submission, and compare the list against the one execution
recomputes. Route Gloas to SSZ simulators again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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