Skip to content

Add builder execution requests (EIP-8282) - #5359

Merged
jtraglia merged 18 commits into
ethereum:masterfrom
jtraglia:eip8282
Jun 19, 2026
Merged

Add builder execution requests (EIP-8282)#5359
jtraglia merged 18 commits into
ethereum:masterfrom
jtraglia:eip8282

Conversation

@jtraglia

@jtraglia jtraglia commented Jun 11, 2026

Copy link
Copy Markdown
Member

This PR integrates EIP-8282 into Gloas.

Note: This was made in collaboration with @ensi321 🙂

@github-actions github-actions Bot added testing CI, actions, tests, testing infra gloas heze eip8148 Custom sweep threshold labels Jun 11, 2026
Comment thread specs/gloas/fork.md Outdated
@github-actions github-actions Bot added the eip8025 Optional Execution Proofs label Jun 12, 2026
lodekeeper added a commit to lodekeeper/lodestar that referenced this pull request Jun 12, 2026
The gloas bid and envelope carry an `ExecutionRequests` extended with
`builder_deposits` (0x03) and `builder_exits` (0x04) per
ethereum/consensus-specs#5359. Using `ssz.electra.ExecutionRequests.hashTreeRoot`
in the gloas-only code paths produced a root over the electra-shaped
container — wrong even when both builder lists are empty, because the
gloas container has two additional zero-hash leaves.

Switch the four gloas-only call sites to `ssz.gloas.ExecutionRequests`:
* `produceBlockBody.ts` self-build bid construction
* `verifyExecutionPayloadEnvelope.ts` bid↔envelope cross-check
* `executionPayloadEnvelope.ts` gossip validation
* `upgradeStateToGloas.ts` genesis bid default-value root

Refs: ethereum/consensus-specs#5359, ethereum/EIPs#11760

🤖 Generated with AI assistance
lodekeeper added a commit to lodekeeper/lodestar that referenced this pull request Jun 12, 2026
processBuilderDepositRequest (3 cases):
* register on first appearance when PoP verifies
* drop silently when PoP fails
* top-up an existing builder without re-verifying signature and without
  rebinding withdrawal credentials (matches validator deposit contract
  semantics)

processBuilderExitRequest (5 cases):
* drop for unknown pubkey
* drop for inactive builder (`deposit_epoch >= finalized_epoch`)
* drop when `source_address` ≠ builder execution address
* drop when builder already has pending withdrawal queued
* initiate exit on the happy path (sets withdrawableEpoch =
  currentEpoch + MIN_BUILDER_WITHDRAWABILITY_DELAY)

JSON shape (4 cases):
* BuilderDepositRequest snake_case round-trip
* BuilderExitRequest snake_case round-trip
* ExecutionRequests carries builder_deposits / builder_exits alongside
  the existing deposits/withdrawals/consolidations keys
* ExecutionPayloadEnvelope JSON round-trip with builder requests populated

Refs: ethereum/consensus-specs#5359, ethereum/EIPs#11760

🤖 Generated with AI assistance
Comment thread specs/gloas/validator.md Outdated
@ensi321

ensi321 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

On a side note, since there is concern about adding a lot of noise in the spec just for the builder onboarding mechanism at the fork. I wonder if we can extract that part from beacon-chain.md cleanly and put it in a separate file, labeling that this mechanism is a one time use only

Comment thread specs/gloas/builder.md

## Becoming a builder

### Builder withdrawal credentials

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.

Why is this removed? We still have withdrawal credentials for builders, instead of withdrawal prefix we have builder version for the first byte

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.

I guess we should also point out what the supposedly correct value of builder version should be in gloas, albeit it is not checked or enforced anywhere

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Why is this removed? We still have withdrawal credentials for builders, instead of withdrawal prefix we have builder version for the first byte

This section was removed because I believe it's sufficiently covered by the "submit deposit" section.

image

I guess we should also point out what the supposedly correct value of builder version should be in gloas, albeit it is not checked or enforced anywhere

If this PR is merged, I'm planning to follow up with a PR which states that new builder deposits should use version 0 instead of version 3 (BUILDER_WITHDRAWAL_PREFIX). This change is independent of EIP-8282 and I don't want to overcomplicate this PR. But yes, this will not be enforced by the protocol. It will be possible to create a builder with whatever version. Doing so would be unwise though, as it may restrict future abilities. We want to allow this so that future builder versions can exist at the fork. For example, we may decide to have separate versions for payload builders and proof builders, for when mandatory proofs are a thing.

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.

Just leaving a random thought that version might be an overengineering or a wise forward-thinking decision. No idea at the moment 🤷‍♂️

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah 😅 hopefully the latter. Good to have options though I guess.

@jtraglia

Copy link
Copy Markdown
Member Author

On a side note, since there is concern about adding a lot of noise in the spec just for the builder onboarding mechanism at the fork. I wonder if we can extract that part from beacon-chain.md cleanly and put it in a separate file, labeling that this mechanism is a one time use only

For the most part, this is already the case. The onboarding function is in fork.md which implies it's only used at the fork. I intend to move some of the helper functions (there are two) which are only used for onboarding from beacon-chain.md to fork.md in a separate PR though.

| Name | Value |
| ------------------------ | -------------------------- |
| `DOMAIN_EXECUTION_PROOF` | `DomainType('0x0E000000')` |
| `DOMAIN_EXECUTION_PROOF` | `DomainType('0x0F000000')` |

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.

Suggested change
| `DOMAIN_EXECUTION_PROOF` | `DomainType('0x0F000000')` |
| `DOMAIN_EXECUTION_PROOF` | `DomainType('0x0G000000')` |

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Hmm 0x0F doesn't exist yet here. Since this is based on Gloas, not Heze. But yeah, we can change this optimistically.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If this comes before Heze, the domain in Heze would change instead. If that makes sense.

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.

Either this or Heze's one should be changed. Slightly prefer to change this one to G because it's not entirely scheduled to ship this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

To be clear, since both are currently based off Gloas they do not need to be different right now. After thinking about this for a while, I have just pushed a commit with changes Heze's DOMAIN_INCLUSION_LIST_COMMITTEE to 0x10000000. I changed this instead of DOMAIN_EXECUTION_PROOF because (1) I consider optional proofs to be part of Gloas and (2) I expect optional proofs to go live on mainnet before Heze does.

Comment thread tests/infra/helpers/deposit_requests.py Outdated
Comment thread specs/gloas/beacon-chain.md Outdated
Comment thread specs/gloas/fork.md Outdated
Comment thread specs/gloas/fork.md
add_builder_to_registry(
state,
request.pubkey,
uint8(request.withdrawal_credentials[0]),

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.

can't this be set to any arbitrary value between 0x00 and 0xFF?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes it can. And that's intentional. This would work the same as validators do today. For instance, there's nothing stopping you from creating a validator with a 0x04 withdrawal credential. Do you think we should restrict this to some value? It would make it difficult/impossible to have another builder version at the fork. For example say builders v0 are for execution payloads and builders v1 are for block proofs. At the fork for mandatory proofs, we may want v1 builders to exist in the registry already.

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.

yeah we have the same for validators today, I don't see any harm, not right now anyways since version is unused. seems reasonable to keep the door open to have new type of builders before the actual fork, but would be good then if we can ensure that tooling will set the version to 0x00 in gloas

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yup will ensure tooling uses 0x00 for builders.

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.

I believe it's better to constrain this value, it's fine if you want to have it configurable in a range. But allowing any value to be used now would preclude us from actually enforcing behavior on a version if we need to in the future. Eg. Suppose we want to force in the future that all builders of type 0xEF must have execution address potuz.eth. Some builder can frontrun and prevent that behavior right now by sending an 0xEF builder right now. It would be better to at least reserve an unused section right now, eg for example assert request.withdrawal_credentials[0] & 0xF0 == 0x00.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@potuz let's debate this later. I'm not strongly opposed to reserving those versions just in case, but I don't believe there will be a situation in which it would be necessary. As said on discord, I believe such checks should exist elsewhere, not when deciding if the builder should be added to the registry.

Comment thread tests/infra/helpers/deposit_requests.py Outdated
@jtraglia
jtraglia marked this pull request as ready for review June 18, 2026 14:41
@ethereum ethereum deleted a comment from jihoonsong Jun 18, 2026
Comment thread specs/gloas/builder.md Outdated
Comment thread specs/gloas/builder.md Outdated
Comment thread specs/gloas/validator.md Outdated
Comment thread specs/gloas/builder.md
@jtraglia
jtraglia requested a review from nflaig June 19, 2026 09:46
@with_gloas_and_later
@spec_state_test
def test_process_parent_execution_payload__builder_deposit_after_pending_validator(spec, state):
def test_process_parent_execution_payload__builder_credential_deposits_queued(spec, state):

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.

test case(s) for builder exit requests are missing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

What kind of tests do you have in mind here? Feel free to commit some. To be clear, we do have builder exit requests here but these are not with process_parent_execution_payload.

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.

if I comment out L1211 does any test catch this?

https://github.com/jtraglia/consensus-specs/blob/c15bd91e3693b3006f050fd1c9048019f47f3a9f/specs/gloas/beacon-chain.md?plain=1#L1210-L1211

the tests you referenced are calling process_builder_exit_request directly but not if it's wired up correctly in process_parent_execution_payload, I might be missing a test that catches this

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm pretty sure the answer is no, that would not be caught with the current tests. We should add a test for this. I'm a bit busy at the moment. Would you have time to add a test for this?

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.

yes I can push a test for that, currently running the existing tests against lodestar to make sure we are passing them

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.

pushed a test for this c84f2e4, this will catch if process_parent_execution_payload is incomplete and doesn't call process_builder_exit_request

# 2**8 (= 256) builder deposit requests
MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD: 256
# 2**4 (= 16) builder exit requests
MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD: 16

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.

This may be very costly, but with these numbers assymmetric, someone could make a ton of deposits and then withdraw all of them and take the whole churn for a long time.

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.

I don't think there is a good reason to use such a low value for exits as they are generally cheap to process

@jtraglia jtraglia Jun 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Staying in the target of 2 exit requests per payload, it would require locking up 14,400 ETH ($30m) to delay the builder exit queue by one day. This doesn't feel like a realistic concern.

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.

no, not a concern imo, we have a really high MIN_BUILDER_WITHDRAWABILITY_DELAY so this would be way too expensive, and exiting builders isn't actually time sensitive and already takes a long time


### Withdrawal prefixes

*Note*: `BUILDER_WITHDRAWAL_PREFIX` is a temporary constant which is only used

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.

A postteriori it would've been cooler to have this one be 0x0B or 0xBB

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We still can do this btw. I would support this.

```python
class BuilderExitRequest(Container):
source_address: ExecutionAddress
pubkey: BLSPubkey

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.

For validators, this entry is called validator_pubkey, perhaps this one should be called builder_pubkey for symmetry.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Eh I would prefer not to change this, but not strongly opposed.

  1. WithdrawalRequest (which you're comparing it to) uses validator_pubkey but I would argue that it's necessary there because the structure name does not contain "validator". This is unlike BuilderExitRequest in which it's explicit that the pubkey is associated with a builder.
  2. pubkey is used in BuilderDepositRequest, so if we change this we would have to change that too, and then it's non-symmetric with DepositRequest which also uses pubkey.

add_builder_to_registry(
state,
request.pubkey,
uint8(request.withdrawal_credentials[0]),

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.

I believe it's better to constrain this value, it's fine if you want to have it configurable in a range. But allowing any value to be used now would preclude us from actually enforcing behavior on a version if we need to in the future. Eg. Suppose we want to force in the future that all builders of type 0xEF must have execution address potuz.eth. Some builder can frontrun and prevent that behavior right now by sending an 0xEF builder right now. It would be better to at least reserve an unused section right now, eg for example assert request.withdrawal_credentials[0] & 0xF0 == 0x00.

@nflaig nflaig 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.

LGTM

@terencechain terencechain 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.

Lgtm

@jtraglia
jtraglia merged commit bc8470b into ethereum:master Jun 19, 2026
16 checks passed
@jtraglia
jtraglia deleted the eip8282 branch June 19, 2026 14:07
ensi321 added a commit to ChainSafe/lodestar that referenced this pull request Jun 26, 2026
implements the following spec changes required to pass `v1.7.0-alpha.11`
spec tests
- ethereum/consensus-specs#5359
- ethereum/consensus-specs#5377
- ethereum/consensus-specs#5373
- ethereum/consensus-specs#5365
- ethereum/consensus-specs#5364
- ethereum/consensus-specs#5368

---------

Co-authored-by: NC <17676176+ensi321@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

eip8025 Optional Execution Proofs eip8148 Custom sweep threshold gloas heze testing CI, actions, tests, testing infra

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants