Skip to content

Add allowed and reserved list of builder versions#5422

Open
potuz wants to merge 4 commits into
ethereum:masterfrom
potuz:whitelist-builders
Open

Add allowed and reserved list of builder versions#5422
potuz wants to merge 4 commits into
ethereum:masterfrom
potuz:whitelist-builders

Conversation

@potuz

@potuz potuz commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

This PR adds two different lists. A list of allowed builder versions and a list of reserved builder versions.

Any builder deposit for a version that is reserved is ignored at deposit processing time. This means that a builder that sends a version that is larger than PAYLOAD_BUILDER_RESERVED_VERSION will lose its deposit.

Any builder with a version that is above PAYLOAD_BUILDER_ALLOWED_VERSION will not be able to land bids on chain. Their bids are ignored over P2P and blocks that include such bids are invalid.

Rationale for the reserved list:

It allows the protocol to make certain that no builder with version larger than PAYLOAD_BUILDER_RESERVED_VERSION exists on state, thus, if in future forks we want to create a special type of builder that requires that no such builder existed, we still have this option.

Rationale for the allowed list.

It allows the protocol to onboard builders with different versions that are able to send bids during the current fork. Thus, if we ever want to create some custom type of builders in the future that requires at fork N + 1 to have had landed a bid on fork N, this can be achieved.

Rationale for these lists to be different

We want allowed to be a strict subset of not reserved to

  • Allow builders to desposit with whatever version they want at the current fork as long as it's not reserved, potentially allowing some offchain mechanisms that would otherwise be forbidden.
  • Allow the protocol to create new builders for fork N+1 that can be deposited during fork N but that are required to never have landed a bid onchain before the fork.

Protocols that prove against beacon block roots have guarantees that the bid's builder version lives on each of the above lists because of these features and because all these lists are separated:

  • Builders onboarded at Gloas are guaranteed to have version 0.
  • Builders onboarded after the Gloas fork are guaranteed to not be reserved
  • Builders that landed a block during Gloas are guaranteed to be allowed.

@github-actions github-actions Bot added testing CI, actions, tests, testing infra gloas labels Jul 3, 2026
@jtraglia

jtraglia commented Jul 3, 2026

Copy link
Copy Markdown
Member

The way this is written is a bit confusing to me. It reads like there's a single allowed version and a single reserved version. Also, generic constants for builders shouldn't include "payload" in the name. To be clear, maybe there should be PAYLOAD_BUILDER_VERSION_MIN and PAYLOAD_BUILDER_VERSION_MAX. And RESERVED_BUILDER_VERSIONS_START. Could you make some improvements like this?

@potuz potuz force-pushed the whitelist-builders branch from 9b2a6ec to 1560a1a Compare July 3, 2026 16:37
assert len(post_state.builders) == 1
assert post_state.builders[0].pubkey == builder_pubkey
assert post_state.builders[0].version == post_spec.PAYLOAD_BUILDER_VERSION
assert post_state.builders[0].version == spec.uint8(spec.PAYLOAD_BUILDERS_RESERVED_VERSION)

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.

There's an outdated reference to PAYLOAD_BUILDERS_RESERVED_VERSION here.

assert is_active_builder(state, builder_index)
# Verify that the builder is a payload builder
assert state.builders[builder_index].version == PAYLOAD_BUILDER_VERSION
assert state.builders[builder_index].version <= BUILDER_MAX_VERSION

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 do not like that we allow builderV1 to submit execution payload bids; only builderV0 should be able to do this. We do not know what builderV1 will be responsible for. I suspect builderV1 will be added with mandatory execution proofs, when there needs to be some in-protocol entity responsible for making proofs.

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.

To be clear, I would like for us to do this:

Suggested change
assert state.builders[builder_index].version <= BUILDER_MAX_VERSION
assert state.builders[builder_index].version == uint8(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.

Yeah, agree with this, having some allowlist to try to anticipate a scenario that ends up as pure technical dead weight unless it's exactly matched, and therefore also require some reserved list, seems excessive.

The explanation that

Rationale for the reserved list:

It allows the protocol to make certain that no builder with version larger than PAYLOAD_BUILDER_RESERVED_VERSION exists on state, thus, if in future forks we want to create a special type of builder that requires that no such builder existed, we still have this option.

Rationale for the allowed list.

It allows the protocol to onboard builders with different versions that are able to send bids during the current fork. Thus, if we ever want to create some custom type of builders in the future that requires at fork N + 1 to have had landed a bid on fork N, this can be achieved.

is backwards: without the allowed list to begin with, the reserved list is pointless. So the motivating structure of this PR is that it wants an allowed list to happen. Without that the entire thing dissolves, including the reserved list.

prefix = uint8(request.withdrawal_credentials[0])
is_valid_version = prefix >= BUILDER_MIN_WITHDRAWAL_PREFIX
version = prefix - BUILDER_MIN_WITHDRAWAL_PREFIX
if is_valid_builder_deposit_signature(request) and is_valid_version:

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.

We should swap these so the cheap one is performed first.

Suggested change
if is_valid_builder_deposit_signature(request) and is_valid_version:
if is_valid_version and is_valid_builder_deposit_signature(request):


| Name | Value |
| ------------------------- | ---------- |
| `PAYLOAD_BUILDER_VERSION` | `uint8(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.

I'm okay with deleting this constant for now, but we may introduce new constants for this later when another builder version is added. It's difficult to name these when we don't know what the future holds.

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

Labels

gloas testing CI, actions, tests, testing infra

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants