diff --git a/CHANGES.md b/CHANGES.md index b18d861f..b1ab4654 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,8 @@ 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) / [#624](https://github.com/ethereum/beacon-APIs/pull/624) `GET /eth/v4/validator/blocks/{slot}` added | | | | | | +| [#580](https://github.com/ethereum/beacon-APIs/pull/580) / [#624](https://github.com/ethereum/beacon-APIs/pull/624) / [#630](https://github.com/ethereum/beacon-APIs/pull/630) `POST /eth/v4/validator/blocks/{slot}` added | | | | | | +| [#630](https://github.com/ethereum/beacon-APIs/pull/630) `POST /eth/v1/validator/builder_preferences` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v1/validator/execution_payload_bids/{slot}/{builder_index}` added | | | | | | | [#580](https://github.com/ethereum/beacon-APIs/pull/580) / [#624](https://github.com/ethereum/beacon-APIs/pull/624) `GET /eth/v1/validator/execution_payload_envelopes/{slot}/{beacon_block_root}` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v1/validator/payload_attestation_data/{slot}` added | | | | | | @@ -20,7 +21,7 @@ There are likely to be descriptions etc outside of the list below, but new query | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `POST /eth/v1/beacon/pool/payload_attestations` added | | | | | | | [#614](https://github.com/ethereum/beacon-APIs/pull/614) `POST /eth/v1/beacon/states/{state_id}/builders` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `GET /eth/v2/beacon/blocks/{block_id}` updated | | | | | | -| [#552](https://github.com/ethereum/beacon-APIs/pull/552) `POST /eth/v2/beacon/blocks` updated | | | | | | +| [#552](https://github.com/ethereum/beacon-APIs/pull/552) / [#630](https://github.com/ethereum/beacon-APIs/pull/630) `POST /eth/v2/beacon/blocks` updated | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `execution_payload_available EVENT` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `execution_payload_bid EVENT` added | | | | | | | [#552](https://github.com/ethereum/beacon-APIs/pull/552) `payload_attestation_message EVENT` added | | | | | | diff --git a/apis/beacon/blocks/blocks.v2.yaml b/apis/beacon/blocks/blocks.v2.yaml index b93e6db9..f561b3d5 100644 --- a/apis/beacon/blocks/blocks.v2.yaml +++ b/apis/beacon/blocks/blocks.v2.yaml @@ -43,6 +43,20 @@ post: required: true name: Eth-Consensus-Version description: "The active consensus version to which the block being submitted belongs." + - name: Eth-Builder-Url + in: header + required: false + description: | + The `url` of the winning builder, as returned by `POST /eth/v4/validator/blocks/{slot}`. + When that endpoint returns this header the validator client MUST echo it here, so the beacon + node can forward the signed block to the same builder and the builder can release the + payload without waiting for gossip. The echo is what lets a beacon node that did not serve + the block-production request still forward it. Omitted for a self-built block or a block won + by a p2p bid. + schema: + type: string + format: uri + example: "https://builder.example.com" requestBody: description: "The `SignedBeaconBlock` object composed of `BeaconBlock` object (produced by beacon node) and validator signature." required: true diff --git a/apis/validator/block.v4.yaml b/apis/validator/block.v4.yaml index 901f7491..b23ee031 100644 --- a/apis/validator/block.v4.yaml +++ b/apis/validator/block.v4.yaml @@ -1,25 +1,37 @@ -get: +post: 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. + Requests a beacon node to produce a valid block, which the validator then signs. - 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. + The beacon node always builds a local payload and MAY consider a p2p bid, so a block is returned + even when no builder bid is available. The validator client supplies a `BuilderConfig` in the + request body: a list of `BuilderEntry` objects in its `builders` field, one per bid request, + plus a top-level `min_bid` and `builder_boost_factor` that apply to p2p bids. Each entry + requests a bid from its `url`, and the entry applies to the bid that request returns; an empty + `builder_pubkeys` list accepts any builder, and a bid MUST NOT be accepted unless signed by + one of a non-empty list. - When self-building (local execution payload), the response includes the full block contents - (beacon block, execution payload envelope, blobs, and KZG proofs) if `include_payload` is - set to `true`, otherwise only the `BeaconBlock` is returned. - 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. + A builder bid, over the builder API or p2p, is rejected if its total payment falls below the + `min_bid` that applies to it. Every surviving bid is then boosted by the + `builder_boost_factor` that applies to it, and the + highest boosted bid competes with the local build in Gwei. The local build wins a tie. - The `Eth-Execution-Payload-Included` header and `execution_payload_included` response field - indicate which response type was returned. + The response carries the full block contents only when the beacon node self-built the block and + `include_payload` is `true`; in every other case, including any builder bid win, it carries + only the `BeaconBlock`. + + Every block is published via `POST /eth/v2/beacon/blocks`. A self-built block carries + `BUILDER_INDEX_SELF_BUILD` as its `builder_index`, and the validator client publishes its + execution payload envelope via `POST /eth/v1/beacon/execution_payload_envelopes`. When a + builder bid won, the winning builder releases the envelope instead, and the validator client + echoes `Eth-Builder-Url` if one was returned. + + This endpoint is specific to the post-Gloas forks and is not backwards compatible with previous + forks. parameters: - name: slot in: path @@ -58,46 +70,37 @@ get: 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). + This parameter affects the self-built case only. When a builder bid wins, the beacon node + does not hold that payload, so it returns only the beacon block regardless of this + parameter. schema: type: boolean - - name: builder_boost_factor - in: query - required: false - description: | - Percentage multiplier to apply to the builder's bid value when choosing between a - builder bid and payload from the paired execution node. This parameter is only relevant - if the beacon node has at least one viable builder `ExecutionPayloadBid` available and - receives a valid response from the paired execution node. When these preconditions are - met, the server MUST act as follows: - - * if `exec_node_payload_value >= builder_boost_factor * (builder_bid_value // 100)` - for the highest builder bid known to the beacon node, then return a block committing - to the local execution node payload (with the payload itself included if - `include_payload` is set to true). - * otherwise, return a block committing to the builder bid (without execution payload, - as it is not yet available). - - 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 of the local - execution node payload and the builder bid pays more. - * `builder_boost_factor=2**64 - 1`: prefer the builder bid 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 no builder bid is available, the beacon node MUST respond with a block - committing to the local execution node payload, 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. + - in: header schema: - $ref: "../../beacon-node-oapi.yaml#/components/schemas/Uint64" + $ref: "../../beacon-node-oapi.yaml#/components/schemas/ConsensusVersion" + required: true + name: Eth-Consensus-Version + description: "The active consensus version to which the request belongs." + requestBody: + required: true + description: | + A `BuilderConfig` for this request: the builder entries to solicit bids from, plus the + top-level `min_bid` and `builder_boost_factor` that apply to p2p bids. + Each entry's `auth.message.slot` is the `slot` this request is for; + the builder rejects a mismatch, so an entry naming a different slot is one the beacon node + does not use for a bid request. A missing body, or one that cannot be decoded, is invalid and + MUST fail with a 400. Every other failure is per entry: an entry the beacon node rejects, or + whose builder does not answer, yields no bid and MUST NOT fail the request, so one bad entry + never costs the proposer its slot. A local-preferred build is requested with an empty + `builders` list and a `builder_boost_factor` of `0`, which prefers the local payload unless + an error makes it unviable. + content: + application/json: + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Gloas.BuilderConfig" + application/octet-stream: + schema: + description: "SSZ serialized `BuilderConfig` bytes (see the `BuilderConfig` type description for the container and constants). Use Content-Type header to indicate that SSZ data is contained in the request body." responses: "200": description: Success response @@ -110,6 +113,18 @@ get: $ref: '../../beacon-node-oapi.yaml#/components/headers/Eth-Execution-Payload-Value' Eth-Execution-Payload-Included: $ref: '../../beacon-node-oapi.yaml#/components/headers/Eth-Execution-Payload-Included' + Eth-Builder-Url: + description: | + When the winning bid came through the builder-API channel, the `url` of that builder. + The validator echoes this value in the `Eth-Builder-Url` request header when publishing + the signed block, so the beacon node can forward the block to the same builder via the + builder-API `submitSignedBeaconBlock`. Absent when the block was self-built or the + winning bid came from the p2p network. + required: false + schema: + type: string + format: uri + example: "https://builder.example.com" content: application/json: schema: @@ -130,7 +145,7 @@ get: example: "12345" description: | Execution payload value in Wei. The value of the local execution payload when - self-building, or the total value of the bid when committing to a builder bid. + self-building, or the total value of the builder bid when committing to one. execution_payload_included: type: boolean description: | @@ -159,6 +174,8 @@ get: message: "Invalid request to produce a block" "406": $ref: "../../beacon-node-oapi.yaml#/components/responses/NotAcceptable" + "415": + $ref: "../../beacon-node-oapi.yaml#/components/responses/UnsupportedMediaType" "500": $ref: '../../beacon-node-oapi.yaml#/components/responses/InternalError' "503": diff --git a/apis/validator/builder_preferences.yaml b/apis/validator/builder_preferences.yaml new file mode 100644 index 00000000..715a74c9 --- /dev/null +++ b/apis/validator/builder_preferences.yaml @@ -0,0 +1,56 @@ +post: + operationId: "submitBuilderPreferences" + summary: Submit builder preferences + description: | + Submits per-builder preferences for one or more proposers. The request body is a flat list of + `BuilderPreferencesEntry` objects, each naming the proposer in `proposer_pubkey`; the beacon + node submits each to the builder-API `submitBuilderPreferences` endpoint at the entry's `url`. + Applicable from the Gloas fork onwards. + + Notes: + - Each entry targets one builder `url`, to which the beacon node makes one submission. + - Entries are identified by `proposer_pubkey`, so several proposers MAY submit to the same `url`. + - The beacon node routes each entry by its `url` and submits to that builder's + `submitBuilderPreferences` for the entry's `proposer_pubkey`, forwarding the `auth` and + `max_execution_payment`. + - Validators MAY submit in the epoch prior to proposing (from `state.proposer_lookahead`), so + builders hold the preferences before the bid request arrives. + 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 submitted builder preferences belong." + tags: + - Validator + requestBody: + required: true + description: "Array of `BuilderPreferencesEntry` objects to submit, one per builder per proposer." + content: + application/json: + schema: + type: array + maxItems: 4096 # MAX_BUILDER_ENTRIES * (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH + items: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/Gloas.BuilderPreferencesEntry" + application/octet-stream: + schema: + description: "SSZ serialized `List[BuilderPreferencesEntry, MAX_BUILDER_ENTRIES * (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]` bytes. Use Content-Type header to indicate that SSZ data is contained in the request body." + responses: + "200": + description: "Every entry was submitted and its builder accepted it" + "400": + description: | + One or more entries failed; the others were still submitted. Each failure is reported by the + entry's index via `IndexedErrorMessage`, proxying the builder's error for that entry. + content: + application/json: + schema: + $ref: "../../beacon-node-oapi.yaml#/components/schemas/IndexedErrorMessage" + "415": + $ref: "../../beacon-node-oapi.yaml#/components/responses/UnsupportedMediaType" + "500": + $ref: "../../beacon-node-oapi.yaml#/components/responses/InternalError" + "503": + $ref: "../../beacon-node-oapi.yaml#/components/responses/CurrentlySyncing" diff --git a/beacon-node-oapi.yaml b/beacon-node-oapi.yaml index 369a8f18..d24e44b4 100644 --- a/beacon-node-oapi.yaml +++ b/beacon-node-oapi.yaml @@ -224,6 +224,8 @@ paths: $ref: "./apis/validator/register_validator.yaml" /eth/v1/validator/proposer_preferences: $ref: "./apis/validator/proposer_preferences.yaml" + /eth/v1/validator/builder_preferences: + $ref: "./apis/validator/builder_preferences.yaml" /eth/v1/validator/liveness/{epoch}: $ref: "./apis/validator/liveness.yaml" /eth/v1/validator/execution_payload_bids/{slot}/{builder_index}: @@ -493,6 +495,16 @@ components: $ref: "./types/fulu/data_column_sidecar.yaml#/Fulu/DataColumnSidecars" Gloas.DataColumnSidecars: $ref: "./types/gloas/data_column_sidecar.yaml#/Gloas/DataColumnSidecars" + Gloas.RequestAuth: + $ref: "./types/gloas/request_auth.yaml#/Gloas/RequestAuth" + Gloas.SignedRequestAuth: + $ref: "./types/gloas/request_auth.yaml#/Gloas/SignedRequestAuth" + Gloas.BuilderEntry: + $ref: "./types/gloas/builder_entry.yaml#/Gloas/BuilderEntry" + Gloas.BuilderConfig: + $ref: "./types/gloas/builder_entry.yaml#/Gloas/BuilderConfig" + Gloas.BuilderPreferencesEntry: + $ref: "./types/gloas/builder_preferences_entry.yaml#/Gloas/BuilderPreferencesEntry" Node: $ref: './types/fork_choice.yaml#/Node' ExtraData: diff --git a/types/gloas/builder_entry.yaml b/types/gloas/builder_entry.yaml new file mode 100644 index 00000000..16a5254a --- /dev/null +++ b/types/gloas/builder_entry.yaml @@ -0,0 +1,115 @@ +Gloas: + BuilderEntry: + type: object + description: | + A per-builder input the validator client supplies on a block-production request. + + Each entry is a bid request sent to its `url`, authenticated by its `auth`, which the + builder requires on every request. No two entries may share both their `url` and their + `auth`'s `data`, and one request is made per entry, so several MAY share a `url` with + different `data`. + + `auth` is the [`SignedRequestAuthV1`](https://github.com/ethereum/builder-specs/blob/78a5546d9d8253beabf7db8baf988a58abdec87f/specs/gloas/validator.md#signedrequestauthv1) object from the Builder API Gloas spec. + + A `BuilderEntry` never reaches a builder, so it has no Builder API definition. Its SSZ + container and constants are: + + MAX_BUILDER_ENTRIES = 64 + MAX_BUILDER_URL_SIZE = 2048 + MAX_BUILDER_PUBKEYS = 64 + + class BuilderEntry(Container): + url: ByteList[MAX_BUILDER_URL_SIZE] # UTF-8 bytes of `url`, exactly as in JSON + auth: SignedRequestAuth + builder_pubkeys: List[BLSPubkey, MAX_BUILDER_PUBKEYS] + max_execution_payment: Gwei + min_bid: Gwei + builder_boost_factor: uint64 + + In either encoding, a zero-length `url` is invalid. + required: [url, auth, builder_pubkeys, max_execution_payment, min_bid, builder_boost_factor] + properties: + url: + type: string + format: uri + maxLength: 2048 # MAX_BUILDER_URL_SIZE + description: "Where this entry's bid request is sent." + example: "https://builder.example.com" + auth: + allOf: + - $ref: "./request_auth.yaml#/Gloas/SignedRequestAuth" + - description: "Authenticates this entry's bid request to the builder. The beacon node MUST forward `message` and `signature` byte-for-byte unchanged." + builder_pubkeys: + type: array + maxItems: 64 # MAX_BUILDER_PUBKEYS + description: "The builder BLS public keys this entry accepts bids from. Empty accepts any builder; otherwise a bid not signed by one of them MUST NOT be accepted." + items: + allOf: + - $ref: "../primitive.yaml#/Pubkey" + - description: "A builder's BLS public key." + max_execution_payment: + allOf: + - $ref: "../primitive.yaml#/Gwei" + - description: "Maximum execution-layer payment, in Gwei, the proposer will accept from this builder. Its effect on bid selection is specified in the builder-specs." + example: "1000000000" + min_bid: + allOf: + - $ref: "../primitive.yaml#/Gwei" + - description: "Minimum total payment, in Gwei, accepted from this builder. A bid whose `value` plus `execution_payment` is below this MUST be rejected." + example: "10000000" + builder_boost_factor: + allOf: + - $ref: "../primitive.yaml#/Uint64" + - description: | + Percentage multiplier applied to this builder's bid once it has passed the + `min_bid` check, giving + `builder_boost_factor * (builder_bid_value // 100)`, where + `builder_bid_value` is the bid's `value` plus its `execution_payment`. The + highest boosted bid competes with the local payload in Gwei, so a factor below `100` + favors the local payload and one above `100` favors this builder. + + Servers must support the following values, which encode common preferences: + + * `builder_boost_factor=0`: prefer the local payload unless an error makes it unviable. + * `builder_boost_factor=100`: profit maximization mode; choose whichever pays more. + * `builder_boost_factor=2**64 - 1`: prefer this builder unless an error or health check + makes it unviable. + + Servers should use saturating arithmetic so that large values do not overflow. + example: "100" + BuilderConfig: + type: object + description: | + The resolved per-key builder config the validator client sends on a block-production request. + Entries arrive fully resolved, so a requested bid is governed by its own `BuilderEntry`; the + top-level `min_bid` and `builder_boost_factor` apply to bids received over p2p. + + Its SSZ container is: + + class BuilderConfig(Container): + min_bid: Gwei + builder_boost_factor: uint64 + builders: List[BuilderEntry, MAX_BUILDER_ENTRIES] + required: [min_bid, builder_boost_factor, builders] + properties: + min_bid: + allOf: + - $ref: "../primitive.yaml#/Gwei" + - description: "Minimum total payment, in Gwei, accepted from a p2p bid. A bid whose `value` plus `execution_payment` is below this MUST be rejected." + example: "10000000" + builder_boost_factor: + allOf: + - $ref: "../primitive.yaml#/Uint64" + - description: | + Percentage multiplier applied to a p2p bid, exactly as a `BuilderEntry`'s + `builder_boost_factor` is applied to a bid from that entry: `0` prefers the local + payload, `100` is profit maximization, and `2**64 - 1` prefers the bid, each unless + an error or health check makes the preferred payload unviable. Servers should use + saturating arithmetic so that large values do not overflow. + example: "100" + builders: + type: array + maxItems: 64 # MAX_BUILDER_ENTRIES + description: "The builders to request bids from, one `BuilderEntry` each. Empty means request none, so only p2p bids are considered." + items: + $ref: "#/Gloas/BuilderEntry" diff --git a/types/gloas/builder_preferences_entry.yaml b/types/gloas/builder_preferences_entry.yaml new file mode 100644 index 00000000..c55cc27f --- /dev/null +++ b/types/gloas/builder_preferences_entry.yaml @@ -0,0 +1,42 @@ +Gloas: + BuilderPreferencesEntry: + type: object + description: | + A per-builder preference the validator client asks the beacon node to submit ahead of the bid + request, one entry per builder per proposer. A single submission batches these across the + validator client's proposers, so each entry names the proposer it belongs to in + `proposer_pubkey`. It is a dedicated type, distinct from the block-production `BuilderEntry`. + + The entry pairs the beacon node's routing with the payload the builder receives, so like + `BuilderEntry` it has no Builder API definition. Its SSZ container uses that type's constants + and the + [`SignedRequestAuthV1`](https://github.com/ethereum/builder-specs/blob/78a5546d9d8253beabf7db8baf988a58abdec87f/specs/gloas/validator.md#signedrequestauthv1) object from the Builder API Gloas spec: + + class BuilderPreferencesEntry(Container): + proposer_pubkey: BLSPubkey # the proposer these preferences belong to + url: ByteList[MAX_BUILDER_URL_SIZE] # UTF-8 bytes of `url`, exactly as in JSON + auth: SignedRequestAuth + max_execution_payment: Gwei + + In either encoding, a zero-length `url` is invalid. + required: [proposer_pubkey, url, auth, max_execution_payment] + properties: + proposer_pubkey: + description: "The BLS public key of the proposer these preferences apply to." + allOf: + - $ref: "../primitive.yaml#/Pubkey" + url: + type: string + format: uri + maxLength: 2048 # MAX_BUILDER_URL_SIZE + description: "The URL this entry's preferences are submitted to. Multiple entries MAY share a `url`; the beacon node makes one submission per entry." + example: "https://builder.example.com" + auth: + description: "Authenticates this submission to the builder. The beacon node MUST forward `message` and `signature` byte-for-byte unchanged." + allOf: + - $ref: "./request_auth.yaml#/Gloas/SignedRequestAuth" + max_execution_payment: + allOf: + - $ref: "../primitive.yaml#/Gwei" + - description: "Maximum execution-layer payment, in Gwei, submitted to this builder so it can shape its bid." + example: "1000000000" diff --git a/types/gloas/request_auth.yaml b/types/gloas/request_auth.yaml new file mode 100644 index 00000000..4561e588 --- /dev/null +++ b/types/gloas/request_auth.yaml @@ -0,0 +1,32 @@ +Gloas: + RequestAuth: + type: object + description: "The [`RequestAuthV1`](https://github.com/ethereum/builder-specs/blob/78a5546d9d8253beabf7db8baf988a58abdec87f/specs/gloas/validator.md#requestauthv1) object from the Builder API Gloas spec." + required: [data, slot] + properties: + data: + type: string + format: hex + description: | + Opaque authentication data unique to the builder, agreed upon out of band. The meaning of + the up to `MAX_DATA_SIZE` (4096) bytes is left to the two parties; the builder checks the + exact bytes when it verifies. When no value has been agreed out of band, implementations + SHOULD default to the UTF-8 bytes of the builder's own advertised URL, exactly as + advertised, so proposers with no prior relationship can construct an identical `data` + deterministically. A zero-length `data` is invalid. + example: "0x1234567890abcdef" + pattern: "^0x(?:[a-fA-F0-9]{2}){1,4096}$" + slot: + allOf: + - $ref: "../primitive.yaml#/Uint64" + - description: "The proposal slot this request is authorized for." + + SignedRequestAuth: + type: object + description: "The [`SignedRequestAuthV1`](https://github.com/ethereum/builder-specs/blob/78a5546d9d8253beabf7db8baf988a58abdec87f/specs/gloas/validator.md#signedrequestauthv1) object from the Builder API Gloas spec." + required: [message, signature] + properties: + message: + $ref: "#/Gloas/RequestAuth" + signature: + $ref: "../primitive.yaml#/Signature" diff --git a/validator-flow.md b/validator-flow.md index 79dc94e1..15ebc406 100644 --- a/validator-flow.md +++ b/validator-flow.md @@ -14,18 +14,27 @@ Detail explanation how validator should utilize this API to perform his regular On start of every epoch, validator should [fetch proposer duties](#/Validator/getProposerDuties). Result is array of objects, each containing proposer pubkey and slot at which he is suppose to propose. +Post-Gloas, in the epoch prior to a proposal the validator MAY +[submit builder preferences](#/Validator/submitBuilderPreferences) so builders hold them before the +bid request arrives. + If proposing block, then at immediate start of slot: 1. Ask Beacon Node for BeaconBlock object: - Pre-Gloas forks: [produceBlockV3](#/Validator/produceBlockV3) - Post-Gloas fork: [produceBlockV4](#/Validator/produceBlockV4) + - Supply a `BuilderConfig` in the required request body, with the `Eth-Consensus-Version` + header: the builder entries to solicit builder-API bids, plus the top-level `min_bid` and + `builder_boost_factor` that apply to p2p bids. - `include_payload=true`: returns `BlockContents` (beacon block, execution payload envelope, blobs, and KZG proofs). Enables stateless operation (multi-BN setups, distributed validators, 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`. + - When a bid wins, only the `BeaconBlock` is returned regardless of `include_payload`, and + `Eth-Builder-Url` names the builder if the bid came through the builder-API channel. 2. Sign block -3. [Submit SignedBeaconBlock](#/ValidatorRequiredApi/publishBlock) (BeaconBlock + signature) -4. Post-Gloas, if self-building (proposer's own bid included in block): +3. [Submit SignedBeaconBlock](#/ValidatorRequiredApi/publishBlock) (BeaconBlock + signature), + echoing the `Eth-Builder-Url` header if one was returned +4. Post-Gloas, if self-building (the block's `builder_index` is [BUILDER_INDEX_SELF_BUILD](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/gloas/beacon-chain.md#misc)): - Stateless (`include_payload=true`): envelope and blobs are already available from step 1. Sign envelope and [submit `SignedExecutionPayloadEnvelopeContents`](#/Beacon/publishExecutionPayloadEnvelope) (envelope + blobs + KZG proofs). @@ -34,6 +43,9 @@ If proposing block, then at immediate start of slot: (beacon node attaches blobs and KZG proofs from its cache). - Must submit before [PAYLOAD_DUE_BPS](https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/gloas/validator.md#time-parameters) of slot duration for the PTC to attest the payload as present +5. Post-Gloas, if a bid won (any other `builder_index`): nothing further. The winning builder + releases the execution payload envelope. + 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. diff --git a/wordlist.txt b/wordlist.txt index b03ee999..6336057f 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -47,3 +47,11 @@ produceBlockV stateful CGC RLP +auth +RequestAuth +RequestAuthV +SignedRequestAuth +SignedRequestAuthV +UTF +uri +publishBlockV