diff --git a/CHANGES.md b/CHANGES.md index b421091f..cd7104ab 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,11 +8,14 @@ There are likely to be descriptions etc outside of the list below, but new query | Endpoint | [Lighthouse](https://github.com/sigp/lighthouse) | [Lodestar](https://github.com/ChainSafe/lodestar) | [Nimbus](https://github.com/status-im/nimbus-eth2) | [Prysm](https://github.com/prysmaticlabs/prysm) | [Teku](https://github.com/ConsenSys/teku) | |---------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|---------------------------------------------------|----------------------------------------------------|-------------------------------------------------|-------------------------------------------| +| [#580](https://github.com/ethereum/beacon-APIs/pull/580) `GET /eth/v4/validator/blocks/{slot}` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v1/validator/execution_payload_bid/{slot}/{builder_index}` added | | | | | | +| [#580](https://github.com/ethereum/beacon-APIs/pull/580) `GET /eth/v1/validator/execution_payload_envelope/{slot}` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v1/validator/payload_attestation_data/{slot}` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `POST /eth/v1/validator/duties/ptc/{epoch}` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `POST /eth/v1/beacon/execution_payload_bid` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v1/beacon/execution_payload_envelope/{block_id}` added | | | | | | +| [#580](https://github.com/ethereum/beacon-APIs/pull/580) `POST /eth/v1/beacon/execution_payload_envelope` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v1/beacon/pool/payload_attestations` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `POST /eth/v1/beacon/pool/payload_attestations` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v2/beacon/blocks/{block_id}` updated | | | | | | diff --git a/apis/beacon/execution_payload/envelope_post.yaml b/apis/beacon/execution_payload/envelope_post.yaml new file mode 100644 index 00000000..67083bf1 --- /dev/null +++ b/apis/beacon/execution_payload/envelope_post.yaml @@ -0,0 +1,53 @@ +post: + operationId: publishExecutionPayloadEnvelope + summary: Publish signed execution payload envelope + description: | + Instructs the beacon node to broadcast a signed execution payload envelope to the network, + to be gossiped for payload validation. A success response (20x) indicates + that the envelope passed gossip validation and was successfully broadcast onto the network. + + The request body can be either: + - A `SignedExecutionPayloadEnvelopeContents` object containing the signed envelope along with + blobs and KZG proofs. This is used in stateless operation (multi-BN setups, DVs, failover) + where the receiving beacon node does not have the blobs cached. + - A `SignedExecutionPayloadEnvelope` object containing only the signed envelope. This is used + in stateful operation where the beacon node already has the blobs and KZG proofs cached + from block production. + tags: + - Beacon + - ValidatorRequiredApi + parameters: + - in: header + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ConsensusVersion" + required: true + name: Eth-Consensus-Version + description: "The active consensus version to which the execution payload envelope being submitted belongs." + requestBody: + description: "The `SignedExecutionPayloadEnvelopeContents` or `SignedExecutionPayloadEnvelope` object to be broadcast." + required: true + content: + application/json: + schema: + anyOf: + - $ref: "../../../beacon-node-oapi.yaml#/components/schemas/Gloas.SignedExecutionPayloadEnvelopeContents" + - $ref: "../../../beacon-node-oapi.yaml#/components/schemas/Gloas.SignedExecutionPayloadEnvelope" + application/octet-stream: + schema: + description: "SSZ serialized `SignedExecutionPayloadEnvelopeContents` or `SignedExecutionPayloadEnvelope` bytes. Use Content-Type header to specify this format" + responses: + "200": + description: "The envelope was validated successfully and has been broadcast." + "400": + description: "The SignedExecutionPayloadEnvelope object is invalid or failed gossip validation" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Invalid signed execution payload envelope" + "415": + $ref: "../../../beacon-node-oapi.yaml#/components/responses/UnsupportedMediaType" + "500": + $ref: "../../../beacon-node-oapi.yaml#/components/responses/InternalError" diff --git a/apis/validator/block.v4.yaml b/apis/validator/block.v4.yaml new file mode 100644 index 00000000..91bd4e72 --- /dev/null +++ b/apis/validator/block.v4.yaml @@ -0,0 +1,154 @@ +get: + tags: + - Validator + - ValidatorRequiredApi + operationId: "produceBlockV4" + summary: "Produce a new block, without signature." + description: | + Requests a beacon node to produce a valid block, which can then be signed by a validator. + + Post-Gloas, proposers submit execution payload bids rather than full execution payloads, + so there is no longer a concept of blinded or unblinded blocks. Builders release the + payload later. This endpoint is specific to the post-Gloas forks and is not backwards compatible + with previous forks. + + When self-building (local execution payload), the response will include the full block contents + including the beacon block, execution payload envelope, blobs, and KZG proofs. + When using an external builder bid, only the `BeaconBlock` is returned as the beacon node + does not have access to the builder's execution payload. + + The `Eth-Execution-Payload-Included` header and `execution_payload_included` response field + indicate which response type was returned. + parameters: + - name: slot + in: path + required: true + description: "The slot for which the block should be proposed." + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Uint64" + - name: randao_reveal + in: query + required: true + description: "The validator's randao reveal value." + schema: + $ref: '../../beacon-node-oapi.yaml#/components/schemas/Signature' + - name: graffiti + in: query + required: false + description: "Arbitrary data validator wants to include in block." + schema: + $ref: '../../beacon-node-oapi.yaml#/components/schemas/Graffiti' + - name: skip_randao_verification + $ref: '../../beacon-node-oapi.yaml#/components/parameters/SkipRandaoVerification' + - name: include_payload + in: query + required: false + description: | + Controls whether the execution payload envelope and blobs are included in the response + when self-building (using local execution payload). + + When `true` (default), the response includes the full block contents: beacon block, + execution payload envelope, blobs, and KZG proofs. This enables stateless operation + where the validator client can use multiple beacon nodes (multi-BN setups, DVs, failover). + + When `false`, only the beacon block is returned and the beacon node caches the execution + payload envelope and blobs internally. The validator client must then fetch them separately + via `GET /eth/v1/validator/execution_payload_envelope/{slot}`. This saves + bandwidth but requires the validator client to publish via the same beacon node that + produced the block (stateful operation). + + This parameter only affects self-building scenarios. When using an external builder's bid, + only the beacon block is returned regardless of this parameter (the beacon node does not + have access to the builder's execution payload). + schema: + type: boolean + default: true + - name: builder_boost_factor + in: query + required: false + description: | + Percentage multiplier to apply to the builder's payload value when choosing between a + builder payload header and payload from the paired execution node. This parameter is only + relevant if the beacon node is connected to a builder, deems it safe to produce a builder + payload, and receives valid responses from both the builder endpoint _and_ the paired + execution node. When these preconditions are met, the server MUST act as follows: + + * if `exec_node_payload_value >= builder_boost_factor * (builder_payload_value // 100)`, + then return a full (unblinded) block containing the execution node payload. + * otherwise, return a blinded block containing the builder payload header. + + Servers must support the following values of the boost factor which encode common + preferences: + + * `builder_boost_factor=0`: prefer the local execution node payload unless an error makes it + unviable. + * `builder_boost_factor=100`: profit maximization mode; choose whichever + payload pays more. + * `builder_boost_factor=2**64 - 1`: prefer the external builder payload unless an error or + beacon node health check makes it unviable. + + Servers should use saturating arithmetic or another technique to ensure that large values of + the `builder_boost_factor` do not trigger overflows or errors. If this parameter is + provided and the beacon node is not configured with a builder then the beacon node MUST + respond with a full block, which the caller can choose to reject if it wishes. + If the value is provided but out of range for a 64-bit unsigned integer, then an error + response with status code 400 MUST be returned. + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Uint64" + responses: + "200": + description: Success response + headers: + Eth-Consensus-Version: + $ref: '../../beacon-node-oapi.yaml#/components/headers/Eth-Consensus-Version' + Eth-Consensus-Block-Value: + $ref: '../../beacon-node-oapi.yaml#/components/headers/Eth-Consensus-Block-Value' + Eth-Execution-Payload-Included: + $ref: '../../beacon-node-oapi.yaml#/components/headers/Eth-Execution-Payload-Included' + content: + application/json: + schema: + title: "ProduceBlockV4Response" + type: object + required: [version, consensus_block_value, execution_payload_included, data] + properties: + version: + type: string + enum: [gloas] + example: "gloas" + consensus_block_value: + type: string + example: "12345" + description: "Consensus rewards for this block in Wei" + execution_payload_included: + type: boolean + description: | + Indicates whether the execution payload envelope is included in the response. + When `true`, the `data` field contains the full + execution payload envelope, blobs, and KZG proofs. When `false`, the `data` + field contains only a `BeaconBlock`. + example: false + data: + anyOf: + - $ref: "../../beacon-node-oapi.yaml#/components/schemas/Gloas.BeaconBlock" + - $ref: "../../beacon-node-oapi.yaml#/components/schemas/Gloas.BlockContents" + application/octet-stream: + schema: + description: "SSZ serialized `BeaconBlock` or `BlockContents` bytes. Use Accept header to choose this response type, version string is sent in header `Eth-Consensus-Version` and payload inclusion indicated by `Eth-Execution-Payload-Included` header." + "400": + description: "Invalid block production request" + content: + application/json: + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + examples: + InvalidRequest: + value: + code: 400 + message: "Invalid request to produce a block" + "406": + $ref: "../../beacon-node-oapi.yaml#/components/responses/NotAcceptable" + "500": + $ref: '../../beacon-node-oapi.yaml#/components/responses/InternalError' + "503": + $ref: '../../beacon-node-oapi.yaml#/components/responses/CurrentlySyncing' diff --git a/apis/validator/execution_payload_envelope.yaml b/apis/validator/execution_payload_envelope.yaml new file mode 100644 index 00000000..a6b92ad9 --- /dev/null +++ b/apis/validator/execution_payload_envelope.yaml @@ -0,0 +1,77 @@ +get: + operationId: getExecutionPayloadEnvelope + summary: Get execution payload envelope + description: | + Retrieves the cached execution payload envelope for the current proposer's slot, which can + then be signed and published by the validator. The envelope contains the full execution payload + along with associated metadata. + + The beacon node only caches the envelope for the current slot's self-built payload. Requests for + older slots or slots where no envelope has been cached will return a 404 error. This endpoint does + not fetch payloads from the execution layer. + + Depending on `Accept` header, the response can be returned either as JSON or as bytes serialized by SSZ. + tags: + - Validator + - ValidatorRequiredApi + parameters: + - name: slot + in: path + required: true + description: "Slot for which the execution payload envelope is requested." + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Uint64" + - name: beacon_block_root + in: query + required: false + description: | + Optional root of the beacon block associated with this execution payload envelope. + When provided, the beacon node will verify that the cached envelope matches the + given block root, returning a 404 if there is no match. This is useful for + disambiguation in fork scenarios where the same slot may have multiple competing blocks. + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Root" + responses: + "200": + description: "Successful response" + headers: + Eth-Consensus-Version: + $ref: "../../beacon-node-oapi.yaml#/components/headers/Eth-Consensus-Version" + content: + application/json: + schema: + title: GetExecutionPayloadEnvelopeResponse + type: object + required: [version, data] + properties: + version: + type: string + enum: [gloas] + example: "gloas" + data: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Gloas.ExecutionPayloadEnvelope" + application/octet-stream: + schema: + description: "SSZ serialized `ExecutionPayloadEnvelope` bytes. Use Accept header to choose this response type" + "400": + description: "Invalid execution payload envelope request" + content: + application/json: + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Invalid slot parameter" + "404": + description: "No cached execution payload envelope available for the requested slot. The beacon node only caches the envelope for the current proposer's self-built payload." + content: + application/json: + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 404 + message: "Execution payload envelope not available for slot" + "406": + $ref: "../../beacon-node-oapi.yaml#/components/responses/NotAcceptable" + "500": + $ref: "../../beacon-node-oapi.yaml#/components/responses/InternalError" diff --git a/beacon-node-oapi.yaml b/beacon-node-oapi.yaml index 1e5014de..6cde99fc 100644 --- a/beacon-node-oapi.yaml +++ b/beacon-node-oapi.yaml @@ -106,6 +106,8 @@ paths: $ref: "./apis/beacon/blocks/blocks.v2.yaml" /eth/v1/beacon/execution_payload_bid: $ref: "./apis/beacon/execution_payload/bid.yaml" + /eth/v1/beacon/execution_payload_envelope: + $ref: "./apis/beacon/execution_payload/envelope_post.yaml" /eth/v1/beacon/execution_payload_envelope/{block_id}: $ref: "./apis/beacon/execution_payload/envelope_get.yaml" /eth/v2/beacon/blocks/{block_id}: @@ -194,6 +196,8 @@ paths: $ref: "./apis/validator/duties/ptc.yaml" /eth/v3/validator/blocks/{slot}: $ref: "./apis/validator/block.v3.yaml" + /eth/v4/validator/blocks/{slot}: + $ref: "./apis/validator/block.v4.yaml" /eth/v1/validator/attestation_data: $ref: "./apis/validator/attestation_data.yaml" /eth/v1/validator/payload_attestation_data/{slot}: @@ -222,6 +226,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/execution_payload_envelope/{slot}: + $ref: "./apis/validator/execution_payload_envelope.yaml" /eth/v1/events: $ref: "./apis/eventstream/index.yaml" @@ -451,6 +457,8 @@ components: $ref: "./types/gloas/block.yaml#/Gloas/BeaconBlock" Gloas.SignedBeaconBlock: $ref: "./types/gloas/block.yaml#/Gloas/SignedBeaconBlock" + Gloas.BlockContents: + $ref: "./types/gloas/block_contents.yaml#/Gloas/BlockContents" Gloas.ExecutionPayloadBid: $ref: "./types/gloas/execution_payload_bid.yaml#/Gloas/ExecutionPayloadBid" Gloas.SignedExecutionPayloadBid: @@ -459,6 +467,8 @@ components: $ref: "./types/gloas/execution_payload_envelope.yaml#/Gloas/ExecutionPayloadEnvelope" Gloas.SignedExecutionPayloadEnvelope: $ref: "./types/gloas/execution_payload_envelope.yaml#/Gloas/SignedExecutionPayloadEnvelope" + Gloas.SignedExecutionPayloadEnvelopeContents: + $ref: "./types/gloas/execution_payload_envelope.yaml#/Gloas/SignedExecutionPayloadEnvelopeContents" Gloas.PayloadAttestationData: $ref: "./types/gloas/payload_attestation.yaml#/Gloas/PayloadAttestationData" Gloas.PayloadAttestation: @@ -538,3 +548,9 @@ components: required: true schema: $ref: './types/primitive.yaml#/Wei' + Eth-Execution-Payload-Included: + description: | + Indicates whether the execution payload envelope, blobs, and KZG proofs are included in the response. Required in response so client can deserialize returned data. + required: true + schema: + type: boolean diff --git a/types/gloas/block_contents.yaml b/types/gloas/block_contents.yaml new file mode 100644 index 00000000..84206540 --- /dev/null +++ b/types/gloas/block_contents.yaml @@ -0,0 +1,17 @@ +Gloas: + BlockContents: + type: object + description: | + Block contents for self-building, including the execution payload envelope + and blobs. This enables stateless failover to another beacon node for publishing, + as all required data is returned in a single response. + required: [block, execution_payload_envelope, kzg_proofs, blobs] + properties: + block: + $ref: "./block.yaml#/Gloas/BeaconBlock" + execution_payload_envelope: + $ref: "./execution_payload_envelope.yaml#/Gloas/ExecutionPayloadEnvelope" + kzg_proofs: + $ref: "../fulu/block_contents.yaml#/Fulu/KZGProofs" + blobs: + $ref: "../deneb/block_contents.yaml#/Deneb/Blobs" diff --git a/types/gloas/execution_payload_envelope.yaml b/types/gloas/execution_payload_envelope.yaml index 2f8e6c32..927146d0 100644 --- a/types/gloas/execution_payload_envelope.yaml +++ b/types/gloas/execution_payload_envelope.yaml @@ -31,3 +31,18 @@ Gloas: signature: $ref: "../primitive.yaml#/Signature" description: "BLS signature of the execution payload envelope" + + SignedExecutionPayloadEnvelopeContents: + type: object + description: | + Signed execution payload envelope bundled with blobs and KZG proofs for stateless + publishing. Used when the validator client publishes to a beacon node that does not + have the blobs cached (e.g. multi-BN setups, DVs, failover). + required: [signed_execution_payload_envelope, kzg_proofs, blobs] + properties: + signed_execution_payload_envelope: + $ref: "#/Gloas/SignedExecutionPayloadEnvelope" + kzg_proofs: + $ref: "../fulu/block_contents.yaml#/Fulu/KZGProofs" + blobs: + $ref: "../deneb/block_contents.yaml#/Deneb/Blobs" diff --git a/validator-flow.md b/validator-flow.md index 95214c90..da6c4619 100644 --- a/validator-flow.md +++ b/validator-flow.md @@ -15,11 +15,24 @@ On start of every epoch, validator should [fetch proposer duties](#/Validator/ge Result is array of objects, each containing proposer pubkey and slot at which he is suppose to propose. If proposing block, then at immediate start of slot: -1. Ask Beacon Node for BeaconBlock object: [produceBlockV3](#/Validator/produceBlockV3) - - TODO: Post-Gloas block production endpoint (produceBlockV4) to be added in separate PR +1. Ask Beacon Node for BeaconBlock object: + - Pre-Gloas forks: [produceBlockV3](#/Validator/produceBlockV3) + - Post-Gloas fork: [produceBlockV4](#/Validator/produceBlockV4) + - `include_payload=true` (default): returns `BlockContents` (beacon block, execution payload envelope, + blobs, and KZG proofs). Enables stateless operation (multi-BN setups, DVs, failover). + - `include_payload=false`: returns only the `BeaconBlock`. The beacon node caches the execution payload + envelope and blobs internally (stateful operation, must publish via the same beacon node). + - When using an external builder's bid, only the `BeaconBlock` is returned regardless of `include_payload`. 2. Sign block 3. [Submit SignedBeaconBlock](#/ValidatorRequiredApi/publishBlock) (BeaconBlock + signature) -4. TODO: Post-Gloas local block building flow (stateless vs. stateful) to be detailed in separate PR +4. Post-Gloas, if self-building (proposer's own bid included in block): + - Stateless (`include_payload=true`): envelope and blobs are already available from step 1. + Sign envelope and [submit `SignedExecutionPayloadEnvelopeContents`](#/Beacon/publishExecutionPayloadEnvelope) + (envelope + blobs + KZG proofs). + - Stateful (`include_payload=false`): [fetch ExecutionPayloadEnvelope](#/Validator/getExecutionPayloadEnvelope) + from the same beacon node. Sign envelope and [submit `SignedExecutionPayloadEnvelope`](#/Beacon/publishExecutionPayloadEnvelope) + (beacon node has blobs cached). + - Must submit early enough for PTC attestation by [PAYLOAD_ATTESTATION_DUE_BPS](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/validator.md#time-parameters) of slot duration Monitor chain block reorganization events (TBD) as they could change block proposers. If reorg is detected, ask for new proposer duties and proceed from 1. @@ -81,6 +94,11 @@ Building: 2. Cache fields required to form an [ExecutionPayloadEnvelope](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/beacon-chain.md#executionpayloadenvelope) 2. Sign `ExecutionPayloadBid` to create `SignedExecutionPayloadBid` 3. [Submit SignedExecutionPayloadBid](#/Beacon/publishExecutionPayloadBid) to network for proposer consideration -4. TODO: Envelope fetching and publishing flow (stateless vs. stateful) to be detailed in separate PR +4. If bid is selected by proposer in their block: + - [Fetch ExecutionPayloadEnvelope](#/Validator/getExecutionPayloadEnvelope) from beacon node + - Sign envelope and submit to network via [publishExecutionPayloadEnvelope](#/Beacon/publishExecutionPayloadEnvelope): + - Stateless (multi-BN): submit `SignedExecutionPayloadEnvelopeContents` (envelope + blobs + KZG proofs) + - Stateful (single BN): submit `SignedExecutionPayloadEnvelope` (beacon node has blobs cached) + - Must submit early enough for PTC attestation by [PAYLOAD_ATTESTATION_DUE_BPS](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/validator.md#time-parameters) of slot duration Monitor for block proposals containing your bid to trigger envelope release.