Skip to content

execution/protocol: implement EIP-8282 Builder Execution Requests#22093

Merged
taratorio merged 81 commits into
mainfrom
worktree-gd6-eip-8282
Jul 10, 2026
Merged

execution/protocol: implement EIP-8282 Builder Execution Requests#22093
taratorio merged 81 commits into
mainfrom
worktree-gd6-eip-8282

Conversation

@taratorio

@taratorio taratorio commented Jun 29, 2026

Copy link
Copy Markdown
Member

continuation of #21844
merge after #22060
for #22008


EIP-8282

Contract Req Type Type Address
Builder deposit 0x03 0x0000884d2AA32eAa155F59A2f24eFa73D9008282
Builder exit 0x04 0x000014574A74c805590AFF9499fc7A690f008282

#22008
https://notes.ethereum.org/@ethpandaops/glamsterdam-devnet-6

taratorio and others added 30 commits June 25, 2026 18:53
@taratorio taratorio requested a review from sudeepdino008 as a code owner July 7, 2026 10:47
pull Bot pushed a commit to Dustin4444/erigon that referenced this pull request Jul 9, 2026
## Summary

Catches Caplin/Gloas up with the `consensus-specs` `v1.7.0-alpha.11`
execution-request and builder-request shape, while keeping the broader
EL syscall/contract/devnet work in erigontech#22093.

- Adds Gloas builder deposit and builder exit request handling through
CL state transition, block production, CL execution-request decoding,
and SSZREST getPayload encoding.
- Aligns builder deposit signature domain/version handling and execution
payload bid validation with alpha11 semantics.
- Keeps alpha11 exited-builder top-up behavior: top-ups reset
`withdrawable_epoch` for exited builders, matching the current
repository spectest fixtures.
- Rejects spec-invalid builder deposit transitions for balance overflow
and full/unavailable builder registry instead of silently no-oping.
- Uses forkchoice `get_shuffling_dependent_root` semantics for execution
payload bid proposer-preference matching, avoids redundant full-state
reads before bid deduplication, and keeps pending bids queued while
parent state is temporarily unavailable.
- Fixes Beacon API Gloas edge cases: payload-attestation SSZ request
sizing is based on `PTC_SIZE`, PTC duties POST no longer has a synthetic
item cap beyond the existing body bound, and queued execution payload
bids return gossip `IGNORE` while waiting for dependencies/preferences.
- Preserves Electra/Fulu `ExecutionRequests` SSZ/JSON/hash shape while
using the Gloas request shape at Gloas-specific boundaries, including
JSON `null` list handling and zero-value `ExecutionRequests` fallback
behavior.
- Deep-copies `ExecutionRequests.Clone()` contents, including builder
request lists, to avoid mutable-list aliasing.
- Aggregates payload attestations through one shared helper for API and
block production, including duplicate PTC positions, out-of-PTC
messages, deterministic selection, and malformed aggregate-signature
groups.
- Keeps only minimal shared EIP-8282 execution request type constants on
the EL protocol side; broader EL syscall/contract/devnet handling
remains in erigontech#22093.

Refs erigontech#22008.

## Spec note

The repository fixture source is currently pinned to `consensus-specs`
`v1.7.0-alpha.11` in `test-fixtures.json`. A later consensus-specs
master change adds the swept-only top-up predicate for exited builders
(`withdrawable_epoch != FAR_FUTURE_EPOCH && balance == 0`); this PR
intentionally keeps the alpha11 fixture behavior so `make -C cl/spectest
gloas` stays green.

## Validation

- `GOCACHE=/private/tmp/erigon-gloas-go-cache go test
./cl/beacon/handler -run
'TestPostPayloadAttestations|TestPostPtcDuties|TestAggregatePayloadAttestation'
-count=1`
- `GOCACHE=/private/tmp/erigon-gloas-go-cache go test
./cl/phase1/network/services -run 'TestExecutionPayloadBidService'
-count=1`
- `GOCACHE=/private/tmp/erigon-gloas-go-cache
CGO_CFLAGS=-D__BLST_PORTABLE__ go test ./cl/transition/impl/eth2 -run
'Test.*(Attestation|Builder|Gloas|Payment)' -count=1`
- `GOCACHE=/private/tmp/erigon-gloas-go-cache
GOLANGCI_LINT_CACHE=/private/tmp/golangci-gloas-cache-22091-reviewfix
make lint`

`go test ./cl/beacon/handler ./cl/phase1/network/services -count=1` was
also attempted inside the sandbox; `cl/phase1/network/services` passed,
while `cl/beacon/handler` hit the sandbox's `httptest` port bind
restriction in `TestGetBlobsFromFrozenSnapshots`, unrelated to this PR.

## Review

`adversarial-code-review` was run with the Erigon CL / Gloas
specialization and subagents until convergence.

Findings addressed during the latest convergence loop:

- Payload-attestation POST SSZ cap now uses `PTC_SIZE`, not
`MAX_PAYLOAD_ATTESTATIONS`.
- PTC duties POST no longer rejects valid large validator-index lists
solely due to a synthetic item cap.
- Execution payload bids queued for missing dependencies/preferences now
return `ErrIgnore`, and pending bids are retained while parent state is
temporarily unavailable.
- Builder pending payment weight updates now accumulate locally and
clone once before write-back.
- Block production now delegates payload-attestation aggregation to the
shared helper used by the API path.
- PR scope now explicitly targets alpha11 instead of claiming current
consensus-specs master semantics.

Final subagent follow-up on `c9fbcf4c8a` reported no remaining
Critical/High/Medium actionable findings for spec/regression/pre-fork
compatibility or data-race/performance/error-boundary/corner-case
safety.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds execution-layer support for EIP-8282 “Builder Execution Requests” (builder deposit / builder exit) under the Amsterdam fork, including new request types, system-contract predeploy wiring for tests/dev chains, and Merge rule updates to dequeue and hash these requests.

Changes:

  • Add EIP-8282 request type constants (0x03/0x04) and extend known request types.
  • Dequeue builder deposit/exit requests in Merge finalization when Amsterdam is active; introduce EIP-8282 system contract bytecode/constants and basic tests.
  • Update dev genesis allocs and multiple test harnesses to predeploy the Amsterdam system contracts.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/eest-spec-shards.yml Adjust EEST shard failure thresholds.
execution/types/eip7685_requests.go Add builder deposit/exit request type constants; extend known types list.
execution/tests/blockgen/chain_makers.go Add Amsterdam predeploy helper for builder contracts in test chains.
execution/protocol/rules/merge/merge.go Dequeue builder deposit/exit requests during Finalize under Amsterdam and include in requests hash.
execution/protocol/params/protocol.go Define default builder deposit/exit predeploy addresses.
execution/protocol/misc/eip8282.go Add builder deposit/exit contract bytecode and dequeue helpers.
execution/protocol/misc/eip8282_test.go Add tests for system-contract registration and dequeue empty-code guardrails.
execution/execmodule/execmoduletester/exec_module_tester.go Ensure Amsterdam system contracts are deployed at genesis when Amsterdam is scheduled.
execution/engineapi/sszrest_wire.go Update SSZ REST encoding path for execution requests (currently drops EIP-8282 types).
execution/engineapi/engineapitester/engine_api_tester.go Include builder contracts in engine-api tester genesis alloc.
execution/chain/spec/allocs/hoodi.json Formatting-only change at EOF.
execution/chain/spec/allocs/dev.json Add builder deposit/exit predeploy accounts (code + storage) to dev alloc.
execution/chain/chain_config.go Add chain-config fields + SystemContracts() entries and accessors for builder contract addresses.
cl/cltypes/execution_requests.go Add TODO note for extending CL ExecutionRequests to include builder_* lists.
.github/workflows/test-hive-eest.yml Adjust hive-eest max failure threshold.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread execution/tests/blockgen/chain_makers.go Outdated
Comment thread execution/engineapi/engineapitester/engine_api_tester.go
Comment thread execution/engineapi/sszrest_wire.go Outdated

@yperbasis yperbasis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Verified against the devnet-6 pin (EELS d0338f56, fixtures tests-glamsterdam-devnet@v6.1.1) and the canonical devnet-6 genesis (ethpandaops/glamsterdam-devnets network configs): both predeploy addresses and both embedded bytecodes are byte-identical to the pin (incl. nonce 1 and the slot-0 inhibitor in dev.json), and the checked-syscall semantics plus 0x00→0x04 request ordering match pinned EELS process_general_purpose_requests. The res != nil (vs len > 0) corner is safe — FlatRequests.Hash() skips zero-length data. Notes:

  1. Spec drift heads-up: EIP-8282 on EIPs master now pins different addresses (0x0000bFF4…0D8282 / 0x000064D6…0E8282) — the reference bytecode was revised after the devnet-6 pin, changing the Nick's-method addresses. Nothing to change here, but devnet-7 will need new bytecode + addresses in params, misc, dev.json and the testers; worth a tracking note. Same text-ahead-of-pin pattern as EIP-2780/8038.
  2. Rebase hazard: the sszrest_wire.go silent-ignore of 0x03/0x04 and the cl/cltypes TODO are stale-base shims — main already has the 5-list Gloas container (#22091) and replaced executionRequestsFromList with cltypes.DecodeExecutionRequestsList. Both hunks must be dropped when the stack rebases; please leave a note so the silent drop can't survive conflict resolution. This also supersedes Copilot's "return an error until cltypes is extended" — cltypes is already extended on main, and erroring on this branch would break every Gloas getPayload carrying builder requests.
  3. Copilot's engine-api tester comment is right in substance: the canonical genesis and this PR's own dev.json set the slot-0 inhibitor on both contracts, but the tester sets it only on the deposit entry — give the exit entry the same slot-0 value. (Impact is fee/acceptance before the first syscall, not dequeue semantics.)
  4. Copilot's InitAmsterdamPreDeploys comment (ignored UpdateAccountData/UpdateAccountCode errors, no inhibitor/nonce) is true but inherited verbatim from InitPraguePreDeploys — fix both helpers together or defer both; don't patch just one.
  5. Optional: a positive-path unit test (enqueue via calldata against the embedded bytecode → syscall → assert the 184/68-byte record and type prefix) would pin the bytecode's behavior rather than just its presence; EEST covers it end-to-end.

Trivia: stray blank line in merge.go Initialize.

@taratorio

Copy link
Copy Markdown
Member Author

Verified against the devnet-6 pin (EELS d0338f56, fixtures tests-glamsterdam-devnet@v6.1.1) and the canonical devnet-6 genesis (ethpandaops/glamsterdam-devnets network configs): both predeploy addresses and both embedded bytecodes are byte-identical to the pin (incl. nonce 1 and the slot-0 inhibitor in dev.json), and the checked-syscall semantics plus 0x00→0x04 request ordering match pinned EELS process_general_purpose_requests. The res != nil (vs len > 0) corner is safe — FlatRequests.Hash() skips zero-length data. Notes:

  1. Spec drift heads-up: EIP-8282 on EIPs master now pins different addresses (0x0000bFF4…0D8282 / 0x000064D6…0E8282) — the reference bytecode was revised after the devnet-6 pin, changing the Nick's-method addresses. Nothing to change here, but devnet-7 will need new bytecode + addresses in params, misc, dev.json and the testers; worth a tracking note. Same text-ahead-of-pin pattern as EIP-2780/8038.
  2. Rebase hazard: the sszrest_wire.go silent-ignore of 0x03/0x04 and the cl/cltypes TODO are stale-base shims — main already has the 5-list Gloas container (cl: catch up Gloas alpha11 execution requests #22091) and replaced executionRequestsFromList with cltypes.DecodeExecutionRequestsList. Both hunks must be dropped when the stack rebases; please leave a note so the silent drop can't survive conflict resolution. This also supersedes Copilot's "return an error until cltypes is extended" — cltypes is already extended on main, and erroring on this branch would break every Gloas getPayload carrying builder requests.
  3. Copilot's engine-api tester comment is right in substance: the canonical genesis and this PR's own dev.json set the slot-0 inhibitor on both contracts, but the tester sets it only on the deposit entry — give the exit entry the same slot-0 value. (Impact is fee/acceptance before the first syscall, not dequeue semantics.)
  4. Copilot's InitAmsterdamPreDeploys comment (ignored UpdateAccountData/UpdateAccountCode errors, no inhibitor/nonce) is true but inherited verbatim from InitPraguePreDeploys — fix both helpers together or defer both; don't patch just one.
  5. Optional: a positive-path unit test (enqueue via calldata against the embedded bytecode → syscall → assert the 184/68-byte record and type prefix) would pin the bytecode's behavior rather than just its presence; EEST covers it end-to-end.

Trivia: stray blank line in merge.go Initialize.

thanks, addressed in 2cc2121

  1. yes, that's gd7 spec, we're targeting gd6
  2. fixed
  3. fixed
  4. fixed
  5. n/a, covered by eest already
  6. fixed

@taratorio taratorio changed the title [DO-NOT-MERGE] execution/protocol: implement EIP-8282 Builder Execution Requests execution/protocol: implement EIP-8282 Builder Execution Requests Jul 10, 2026
Base automatically changed from worktree-gd6-eip-8038 to main July 10, 2026 10:21
@taratorio taratorio enabled auto-merge July 10, 2026 12:01
@taratorio taratorio added this pull request to the merge queue Jul 10, 2026
Merged via the queue into main with commit 4aad1d8 Jul 10, 2026
92 checks passed
@taratorio taratorio deleted the worktree-gd6-eip-8282 branch July 10, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Glamsterdam https://eips.ethereum.org/EIPS/eip-7773

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants