diff --git a/apis/beacon/pool/proposer_preferences.yaml b/apis/beacon/pool/proposer_preferences.yaml new file mode 100644 index 00000000..9ecb7288 --- /dev/null +++ b/apis/beacon/pool/proposer_preferences.yaml @@ -0,0 +1,32 @@ +get: + operationId: "getPoolProposerPreferences" + summary: Get proposer preferences from the operation pool. + description: | + Retrieves all known signed proposer preferences from the beacon node's + operation pool. Builders can use this to discover proposer preferences + for upcoming slots. + tags: + - Beacon + parameters: + - name: slot + in: query + required: false + description: "Filter by proposal slot. If not specified, returns all known preferences." + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/Uint64" + responses: + "200": + description: "Successful response" + content: + application/json: + schema: + title: GetPoolProposerPreferencesResponse + type: object + required: [data] + properties: + data: + type: array + items: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/Gloas.SignedProposerPreferences" + "500": + $ref: "../../../beacon-node-oapi.yaml#/components/responses/InternalError" diff --git a/apis/eventstream/index.yaml b/apis/eventstream/index.yaml index 8f8d2298..7ea39055 100644 --- a/apis/eventstream/index.yaml +++ b/apis/eventstream/index.yaml @@ -42,6 +42,7 @@ get: - execution_payload_available - execution_payload_bid - payload_attestation_message + - proposer_preferences responses: "200": description: Opened SSE stream. diff --git a/apis/validator/prepare_beacon_proposer.yaml b/apis/validator/prepare_beacon_proposer.yaml index 59c2ca19..45a136fc 100644 --- a/apis/validator/prepare_beacon_proposer.yaml +++ b/apis/validator/prepare_beacon_proposer.yaml @@ -1,7 +1,12 @@ post: operationId: "prepareBeaconProposer" summary: Provide beacon node with proposals for the given validators. + deprecated: true description: | + **Deprecated for Gloas and later forks.** Use `POST /eth/v1/validator/proposer_preferences` + instead, which provides a signed, gossip-compatible mechanism for communicating + fee recipient and gas limit preferences to builders. + Prepares the beacon node for potential proposers by supplying information required when proposing blocks for the given validators. The information supplied for each validator index will persist through the epoch in which diff --git a/apis/validator/proposer_preferences.yaml b/apis/validator/proposer_preferences.yaml new file mode 100644 index 00000000..62984bb5 --- /dev/null +++ b/apis/validator/proposer_preferences.yaml @@ -0,0 +1,53 @@ +post: + operationId: "submitProposerPreferences" + summary: Submit signed proposer preferences to the beacon node for gossip broadcast. + description: | + Submits signed proposer preferences to the beacon node. The beacon node + will validate the preferences and broadcast them to the `proposer_preferences` + gossip topic. This allows builders to discover the proposer's preferred + `fee_recipient` and `gas_limit` for upcoming proposal slots. + + Validators SHOULD call this endpoint at the beginning of each epoch for + all upcoming proposal slots in the next epoch. If a validator does not + broadcast preferences for a slot, builders will not submit trustless bids + for that slot. + + This endpoint replaces `prepareBeaconProposer` and `registerValidator` + for Gloas and later forks. + tags: + - ValidatorRequiredApi + - Validator + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '../../beacon-node-oapi.yaml#/components/schemas/Gloas.SignedProposerPreferences' + application/octet-stream: + schema: + description: "SSZ serialized `List[SignedProposerPreferences]` bytes. Use content type header to indicate that SSZ data is contained in the request body." + responses: + "200": + description: | + Proposer preferences have been received and will be broadcast. + "400": + description: | + Invalid request. Preferences may be malformed, have invalid signatures, + or reference slots outside the accepted range. + content: + application/json: + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + examples: + InvalidSlot: + value: + code: 400 + message: "Preferences proposal_slot is not in the current or next epoch" + InvalidSignature: + value: + code: 400 + message: "Invalid signature for proposer preferences" + "500": + $ref: "../../beacon-node-oapi.yaml#/components/responses/InternalError" diff --git a/apis/validator/register_validator.yaml b/apis/validator/register_validator.yaml index e7682dc2..39fa93b4 100644 --- a/apis/validator/register_validator.yaml +++ b/apis/validator/register_validator.yaml @@ -1,7 +1,13 @@ post: operationId: "registerValidator" summary: Provide beacon node with registrations for the given validators to the external builder network. + deprecated: true description: | + **Deprecated for Gloas and later forks.** Use `POST /eth/v1/validator/proposer_preferences` + instead. In Gloas (ePBS), builders are protocol-level participants and proposer + preferences are broadcast via the `proposer_preferences` gossip topic. External + builder registration is no longer needed. + Prepares the beacon node for engaging with external builders. The information must be sent by the beacon node to the builder network. It is expected that the validator client will send this information periodically diff --git a/beacon-node-oapi.yaml b/beacon-node-oapi.yaml index 1e5014de..d6ba056d 100644 --- a/beacon-node-oapi.yaml +++ b/beacon-node-oapi.yaml @@ -140,6 +140,8 @@ paths: $ref: "./apis/beacon/pool/attestations.v2.yaml" /eth/v1/beacon/pool/payload_attestations: $ref: "./apis/beacon/pool/payload_attestations.yaml" + /eth/v1/beacon/pool/proposer_preferences: + $ref: "./apis/beacon/pool/proposer_preferences.yaml" /eth/v2/beacon/pool/attester_slashings: $ref: "./apis/beacon/pool/attester_slashings.v2.yaml" /eth/v1/beacon/pool/proposer_slashings: @@ -222,6 +224,8 @@ paths: $ref: "./apis/validator/liveness.yaml" /eth/v1/validator/execution_payload_bid/{slot}/{builder_index}: $ref: "./apis/validator/execution_payload_bid.yaml" + /eth/v1/validator/proposer_preferences: + $ref: "./apis/validator/proposer_preferences.yaml" /eth/v1/events: $ref: "./apis/eventstream/index.yaml" @@ -465,6 +469,10 @@ components: $ref: "./types/gloas/payload_attestation.yaml#/Gloas/PayloadAttestation" Gloas.PayloadAttestationMessage: $ref: "./types/gloas/payload_attestation.yaml#/Gloas/PayloadAttestationMessage" + Gloas.ProposerPreferences: + $ref: "./types/gloas/proposer_preferences.yaml#/Gloas/ProposerPreferences" + Gloas.SignedProposerPreferences: + $ref: "./types/gloas/proposer_preferences.yaml#/Gloas/SignedProposerPreferences" Fulu.BlockContents: $ref: "./types/fulu/block_contents.yaml#/Fulu/BlockContents" Fulu.SignedBlockContents: diff --git a/types/gloas/proposer_preferences.yaml b/types/gloas/proposer_preferences.yaml new file mode 100644 index 00000000..45eee307 --- /dev/null +++ b/types/gloas/proposer_preferences.yaml @@ -0,0 +1,24 @@ +Gloas: + ProposerPreferences: + type: object + description: "The [`ProposerPreferences`](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/p2p-interface.md#new-proposerpreferences) object from the CL Gloas spec." + required: [proposal_slot, validator_index, fee_recipient, gas_limit] + properties: + proposal_slot: + $ref: "../primitive.yaml#/Uint64" + validator_index: + $ref: "../primitive.yaml#/Uint64" + fee_recipient: + $ref: "../primitive.yaml#/ExecutionAddress" + gas_limit: + $ref: "../primitive.yaml#/Uint64" + + SignedProposerPreferences: + type: object + description: "The [`SignedProposerPreferences`](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/p2p-interface.md#new-signedproposerpreferences) object from the CL Gloas spec." + required: [message, signature] + properties: + message: + $ref: "#/Gloas/ProposerPreferences" + signature: + $ref: "../primitive.yaml#/Signature" diff --git a/validator-flow.md b/validator-flow.md index 95214c90..b0258089 100644 --- a/validator-flow.md +++ b/validator-flow.md @@ -69,6 +69,22 @@ PTC Attesting: Monitor chain block reorganization events (TBD) as they could change PTC assignments. If reorg is detected, ask for new PTC duties and proceed from 1.. +### Proposer Preferences (Gloas+) + +At the beginning of each epoch (starting from the Gloas fork), validators that have upcoming proposal slots +in the next epoch SHOULD broadcast their preferences to allow builders to construct valid bids. + +1. [Fetch proposer duties](#/Validator/getProposerDuties) for the next epoch to identify upcoming proposal slots +2. For each upcoming proposal slot, construct `ProposerPreferences` with `fee_recipient` and `gas_limit` +3. Sign each `ProposerPreferences` to create `SignedProposerPreferences` +4. [Submit SignedProposerPreferences](#/ValidatorRequiredApi/submitProposerPreferences) to beacon node for gossip broadcast + +If a validator does not broadcast preferences for a slot, builders will not submit trustless bids for that slot +(as the `execution_payload_bid` gossip validation requires a matching `SignedProposerPreferences`). + +**Note:** This replaces `prepareBeaconProposer` and `registerValidator` for Gloas and later forks. +Validators no longer need to separately register with external builder networks. + ### Builder (Optional) Post-Gloas fork, builders are separate non-validating staked actors that submit execution payload bids for block inclusion.