diff --git a/apis/builder/beacon_block.yaml b/apis/builder/beacon_block.yaml new file mode 100644 index 0000000..1a86500 --- /dev/null +++ b/apis/builder/beacon_block.yaml @@ -0,0 +1,50 @@ +post: + operationId: "submitSignedBeaconBlock" + summary: Submit a signed beacon block with the execution payload bid. + description: | + Submits a `SignedBeaconBlock` to the builder, binding the proposer to the block. + + A success response (200) indicates that the signed beacon block was + valid. If the signed beacon block was invalid, then the builder + must return an error response (400) with a description of the validation + failure. + tags: + - Builder + parameters: + - in: header + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/ConsensusVersion" + required: false + name: Eth-Consensus-Version + description: "The active consensus version to which the block being submitted belongs. Required if request is SSZ encoded." + requestBody: + description: A `SignedBeaconBlock`. + required: true + content: + application/json: + schema: + type: object + required: [data] + properties: + data: + $ref: "../../beacon-apis/types/gloas/block.yaml#/Gloas/SignedBeaconBlock" + description: "The signed beacon block." + application/octet-stream: + schema: + description: "SSZ serialized `SignedBeaconBlock` bytes. Use content type header to indicate that SSZ data is contained in the request body." + responses: + "202": + description: Success response. + "400": + description: Error response. + content: + application/json: + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Invalid signed beacon block: missing signature" + "415": + $ref: "../../builder-oapi.yaml#/components/responses/UnsupportedMediaType" + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/apis/builder/execution_payload_bid.yaml b/apis/builder/execution_payload_bid.yaml new file mode 100644 index 0000000..15dd90e --- /dev/null +++ b/apis/builder/execution_payload_bid.yaml @@ -0,0 +1,126 @@ +post: + operationId: "getExecutionPayloadBid" + summary: Get an execution payload bid. + description: | + Requests a builder node to produce a valid execution payload bid, which + can be integrated into a blinded beacon block and signed. + + The proposer sends a POST request to the builder with the following information: + - The slot for which the block should be proposed. + - The hash of the execution layer block the proposer will build on. + - The root of the beacon block the proposer will build on. + - The index of the proposer. + - A signed bid request auth using a builder-specific salt to authenticate the request. Proposers are required + to set the salt to the URL provided by the whitelisted builder. + + The builder responds with a 200 response containing an execution payload bid if it can provide one. + + If the builder is unable to produce a valid execution payload bid, then + the builder MUST return a 204 response. If the request is invalid, then the + builder MUST return an error response (400) with a description of the + validation failure. If the SignedBidRequestAuth is invalid, the builder MUST return a 400 response. + + This API is applicable from Glamsterdam fork onwards. + tags: + - Builder + parameters: + - name: slot + in: path + required: true + description: The slot for which the block should be proposed. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Uint64" + - name: parent_hash + in: path + required: true + description: Hash of execution layer block the proposer will build on. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Root" + - name: parent_root + in: path + required: true + description: Root of the beacon block the proposer will build on. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Root" + - name: proposer_index + in: path + required: true + description: Index of the proposer. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Uint64" + - name: Date-Milliseconds + in: header + required: false + description: | + Optional header containing a Unix timestamp in milliseconds representing + the point-in-time the request was sent. This header can be used to measure + latency. + schema: + type: integer + format: int64 + example: 1710338135000 + - name: X-Timeout-Ms + in: header + required: false + description: | + Optional header containing the proposer's timeout for the request in milliseconds. + Builders should use this header to adjust the amount of time by which they delay the + requests to maximise block rewards. Otherwise, requests will timeout and the proposer + will not receive the header in time. + schema: + type: integer + format: int64 + example: 10000 + requestBody: + required: true + content: + application/json: + schema: + $ref: "../../types/gloas/bid_request_auth.yaml#/Gloas/SignedBidRequestAuth" + application/octet-stream: + schema: + description: "SSZ serialized `SignedBidRequestAuth` bytes." + responses: + "200": + description: Success response. + headers: + Eth-Consensus-Version: + $ref: "../../builder-oapi.yaml#/components/headers/Eth-Consensus-Version" + required: false + content: + application/json: + schema: + title: GetExecutionPayloadBidResponse + type: object + required: [version, data] + properties: + version: + type: string + enum: [ gloas ] + example: "gloas" + data: + $ref: "../../beacon-apis/types/gloas/execution_payload_bid.yaml#/Gloas/SignedExecutionPayloadBid" + application/octet-stream: + schema: + description: "SSZ serialized `SignedExecutionPayloadBid` bytes. Use Accept header to choose this response type" + "204": + description: No bid is available. + "400": + description: Error response. + content: + application/json: + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/ErrorMessage" + examples: + InvalidHash: + value: + code: 400 + message: "Unknown hash: missing parent hash" + InvalidAuth: + value: + code: 400 + message: "Invalid SignedBidRequestAuth: signature verification failed" + "406": + $ref: "../../builder-oapi.yaml#/components/responses/NotAcceptable" + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/apis/builder/validators_v2.yaml b/apis/builder/validators_v2.yaml new file mode 100644 index 0000000..813ae98 --- /dev/null +++ b/apis/builder/validators_v2.yaml @@ -0,0 +1,45 @@ +post: + operationId: "registerValidatorV2" + summary: Register or update a validator's block building preferences for Gloas. + description: | + Registers a validator's preferred fee recipient, gas limit and preferences. + + A success response (200) indicates that the registration was valid. If the + registration passes validation, then the builder MUST integrate the + registration into its state, such that future blocks built for the + validator conform to the preferences expressed in the registration. If the + registration is invalid, then the builder MUST return an error response + (400) with a description of the validation failure. + tags: + - Builder + requestBody: + description: | + A signed declaration of a validator's block building preferences. + required: true + content: + application/json: + schema: + type: array + items: + $ref: "../../builder-oapi.yaml#/components/schemas/Gloas.SignedValidatorRegistrationV2" + example: + $ref: "../../builder-oapi.yaml#/components/examples/SignedValidatorRegistrations/value" + application/octet-stream: + schema: + description: "SSZ serialized `List[SignedValidatorRegistrationV2, VALIDATOR_REGISTRY_LIMIT]` bytes. Use content type header to indicate that SSZ data is contained in the request body." + responses: + "200": + description: Success response. + "400": + description: Error response. + content: + application/json: + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "unknown validator" + "415": + $ref: "../../builder-oapi.yaml#/components/responses/UnsupportedMediaType" + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/beacon-apis b/beacon-apis index 339eea9..fe36269 160000 --- a/beacon-apis +++ b/beacon-apis @@ -1 +1 @@ -Subproject commit 339eea96b41c787dad47765fc781303fb40aa886 +Subproject commit fe362694bd70685fe7d24cc40ada99178a354d7d diff --git a/builder-oapi.yaml b/builder-oapi.yaml index a9c05f0..99e7545 100644 --- a/builder-oapi.yaml +++ b/builder-oapi.yaml @@ -51,8 +51,14 @@ tags: paths: /eth/v1/builder/validators: $ref: "./apis/builder/validators.yaml" + /eth/v2/builder/validators: + $ref: "./apis/builder/validators_v2.yaml" /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}: $ref: "./apis/builder/header.yaml" + /eth/v1/builder/execution_payload_bid/{slot}/{parent_hash}/{parent_root}/{proposer_index}: + $ref: "./apis/builder/execution_payload_bid.yaml" + /eth/v1/builder/beacon_block: + $ref: "./apis/builder/beacon_block.yaml" /eth/v1/builder/blinded_blocks: $ref: "./apis/builder/blinded_blocks.yaml" /eth/v2/builder/blinded_blocks: @@ -72,7 +78,7 @@ components: $ref: "./beacon-apis/types/http.yaml#/ErrorMessage" ConsensusVersion: $ref: "./beacon-apis/beacon-node-oapi.yaml#/components/schemas/ConsensusVersion" - enum: [bellatrix, capella, deneb, electra, fulu] + enum: [bellatrix, capella, deneb, electra, fulu, gloas] example: "bellatrix" Bellatrix.ExecutionPayload: $ref: "./beacon-apis/types/bellatrix/execution_payload.yaml#/Bellatrix/ExecutionPayload" @@ -102,7 +108,17 @@ components: $ref: "./types/fulu/blobs_bundle.yaml#/Fulu/BlobsBundle" Fulu.ExecutionPayloadAndBlobsBundle: $ref: "./types/fulu/execution_payload_and_blobs_bundle.yaml#/Fulu/ExecutionPayloadAndBlobsBundle" - + Gloas.BidRequestAuth: + $ref: "./types/gloas/bid_request_auth.yaml#/Gloas/BidRequestAuth" + Gloas.SignedBidRequestAuth: + $ref: "./types/gloas/bid_request_auth.yaml#/Gloas/SignedBidRequestAuth" + Gloas.BuilderPreferences: + $ref: "./types/gloas/registration.yaml#/Gloas/BuilderPreferences" + Gloas.ValidatorRegistrationV2: + $ref: "./types/gloas/registration.yaml#/Gloas/ValidatorRegistrationV2" + Gloas.SignedValidatorRegistrationV2: + $ref: "./types/gloas/registration.yaml#/Gloas/SignedValidatorRegistrationV2" + responses: InternalError: $ref: "./types/http.yaml#/InternalError" diff --git a/specs/gloas/builder.md b/specs/gloas/builder.md new file mode 100644 index 0000000..da013da --- /dev/null +++ b/specs/gloas/builder.md @@ -0,0 +1,211 @@ + + + +- [Gloas - Builder Specification](#gloas---builder-specification) + - [Introduction](#introduction) + - [Constants](#constants) + - [Containers](#containers) + - [New Containers](#new-containers) + - [`BuilderPreferences`](#builderpreferences) + - [`ValidatorRegistrationV2`](#validatorregistrationv2) + - [`SignedValidatorRegistrationV2`](#signedvalidatorregistrationv2) + - [`verify_registration_v2_signature`](#verify_registration_v2_signature) + - [Bidding](#bidding) + - [Builder Preferences](#builder-preferences) + - [Validator Registration V2](#validator-registration-v2) + - [`process_registration_v2`](#process_registration_v2) + - [Constructing a `SignedExecutionPayloadBid`](#constructing-a-signedexecutionpayloadbid) + - [Constructing a `SignedExecutionPayloadEnvelope`](#constructing-a-signedexecutionpayloadenvelope) + + + +# Gloas - Builder Specification + +## Introduction + +This document documents the builder behaviour with the Builder-API post ePBS. It +describes how builders interact with validators through +[`ValidatorRegistrationV2`][validator-registration-v2] and construct +[`SignedExecutionPayloadBid`][signed-execution-payload-bid] and +[`SignedExecutionPayloadEnvelope`][signed-execution-payload-envelope] objects. + +## Constants + +| Name | Value | +| ----------------------------------------- | ------------------ | +| `MAX_TRUSTED_BID` | `2**64 - 1` | + +## Containers + +### New Containers + +#### `BuilderPreferences` + +```python +class BuilderPreferences(Container): + max_trusted_bid: uint64 +``` + +#### `ValidatorRegistrationV2` + +```python +class ValidatorRegistrationV2(Container): + validator_index: ValidatorIndex + fee_recipient: ExecutionAddress + proposal_slot: Slot + gas_limit: uint64 + builder_preferences: BuilderPreferences +``` + +#### `SignedValidatorRegistrationV2` + +```python +class SignedValidatorRegistrationV2(Container): + message: ValidatorRegistrationV2 + signature: BLSSignature +``` + +### `verify_registration_v2_signature` + +*Note*: `compute_domain` and `compute_signing_root` are defined in the +[Gloas consensus specs][gloas-consensus-specs]. + +```python +def verify_registration_v2_signature( + state: BeaconState, signed_registration: SignedValidatorRegistrationV2 +) -> bool: + validator = state.validators[signed_registration.message.validator_index] + pubkey = validator.pubkey + domain = compute_domain(DOMAIN_APPLICATION_BUILDER) + signing_root = compute_signing_root(signed_registration.message, domain) + return bls.Verify(pubkey, signing_root, signed_registration.signature) +``` + +## Bidding + +In Gloas, Execution payloads are built for a specific `slot`, `parent_hash`, +`validator_index` along with the `parent_root` tuple corresponding to a unique +beacon block serving as the parent. + +This is because in Gloas with [EIP-7732], the execution payload and beacon +blocks are decoupled. The `parent_hash` could refer to a beacon block which is +an ancestor of the parent beacon block corresponding to the current beacon block +for which we are building the execution payload. + +We update `is_eligible_for_bid` below. *Note*: `hash_tree_root` is defined in +the [Gloas consensus specs][gloas-consensus-specs]. + +```python +def is_eligible_for_bid( + state: BeaconState, + registrations: Dict[ValidatorIndex, ValidatorRegistrationV2], + slot: Slot, + parent_hash: Hash32, + # [New in Gloas] + parent_root: Root, + # [New in Gloas] + validator_index: ValidatorIndex, +): + # Verify slot + assert slot == state.slot + + assert validator_index in state.validators.keys() + + assert validator_index in registrations.keys() + + # Verify parent hash + # [Modified in Gloas:EIP7732] + assert parent_hash == state.latest_block_hash + + # Verify parent root + # [Modified in Gloas:EIP7732] + assert parent_root == hash_tree_root(state.latest_block_header) +``` + +## Builder Preferences + +Using validator registrations, a proposer can express the preferences it has for +a builder. Currently, the only preference that is supported is: + +- `max_trusted_bid`: Specifies the maximum value (in Gwei) that a proposer is + willing to accept as a trusted execution layer payment from the builder. A + value of `0` indicates that the proposer does not accept any trusted payments + from the builder, requiring all payments to be cryptographically verifiable + on-chain. A value of `MAX_TRUSTED_BID` indicates that the proposer will accept + any trusted payment amount from the builder. Proposers may adjust this + parameter based on their level of trust in the builder's reliability and + reputation. + +## Validator Registration V2 + +The second version of ValidatorRegistrations adds the following new fields: + +- `validator_index`: The index of the validator selected to propose a block at + slot `proposal_slot` +- `builder_preferences`: This is a struct which contains the per builder + preferences the proposer has. +- `proposal_slot`: The slot at which this validator is proposing. + +The following fields are removed: + +- `pubkey`: This is the pubkey of the validator which has now been replaced with + `validator_index`. +- `timestamp`: A new validator registration will be sent by the validator to the + builder in the epoch prior to one where they will be proposing. + +### `process_registration_v2` + +A `validator_registration_v2` is considered valid if the following function +completes without raising any assertions. + +```python +def process_registration_v2( + state: BeaconState, + signed_registration: SignedValidatorRegistrationV2, + registrations: Dict[ValidatorIndex, ValidatorRegistrationV2], +): + signature = signed_registration.signature + registration = signed_registration.message + validator_index = registration.validator_index + proposal_slot = registration.proposal_slot + + validator = state.validators[validator_index] + + # Verify validator registration eligibility + assert is_eligible_for_registration(state, validator) + + # Verify that the old registration's proposal slot is earlier than the new registration's proposal slot + if validator_index in registrations.keys(): + prev_registration = registrations[validator_index] + assert registration.proposal_slot >= prev_registration.proposal_slot + + # Verify registration signature + assert verify_registration_v2_signature(state, signed_registration) +``` + +## Constructing a `SignedExecutionPayloadBid` + +The specification for a block builder to construct a +[`SignedExecutionPayloadBid`][signed-execution-payload-bid] is documented in the +[Gloas consensus specs][gloas-builder-specs]. + +## Constructing a `SignedExecutionPayloadEnvelope` + +If the builder's [`SignedExecutionPayloadBid`][signed-execution-payload-bid] has +been accepted by the proposer and it has been included in its +`SignedBeaconBlock`, then the builder has to construct a +[`SignedExecutionPayloadEnvelope`][signed-execution-payload-envelope] +corresponding to the [`SignedExecutionPayloadBid`][signed-execution-payload-bid] +and it has to broadcast it to the PTC committee via the +`execution_payload_envelope` gossip topic. + +The specification for a block builder to construct a +[`SignedExecutionPayloadEnvelope`][signed-execution-payload-envelope] is +documented in the [Gloas consensus specs][gloas-builder-specs]. + +[eip-7732]: https://eips.ethereum.org/EIPS/eip-7732 +[gloas-builder-specs]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/builder.md +[gloas-consensus-specs]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas +[signed-execution-payload-bid]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadbid +[signed-execution-payload-envelope]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadenvelope +[validator-registration-v2]: #validatorregistrationv2 diff --git a/specs/gloas/validator.md b/specs/gloas/validator.md new file mode 100644 index 0000000..57e0ee0 --- /dev/null +++ b/specs/gloas/validator.md @@ -0,0 +1,245 @@ + + + + +- [Gloas - Honest Validator](#gloas---honest-validator) + - [Introduction](#introduction) + - [Constants](#constants) + - [Containers](#containers) + - [New Containers](#new-containers) + - [`BidRequestAuth`](#bidrequestauth) + - [`SignedBidRequestAuth`](#signedbidrequestauth) + - [Helper](#helper) + - [`get_proposer_slots_in_upcoming_epoch`](#get_proposer_slots_in_upcoming_epoch) + - [Bid Authentication](#bid-authentication) + - [Constructing the `BidRequestAuth`](#constructing-the-bidrequestauth) + - [Validator Registrations](#validator-registrations) + - [Constructing the `ValidatorRegistrationV2`](#constructing-the-validatorregistrationv2) + - [Validator Registration dissemination](#validator-registration-dissemination) + - [Validating a `SignedExecutionPayloadBid`](#validating-a-signedexecutionpayloadbid) + - [Block proposal](#block-proposal) + - [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody) + - [Receiving ExecutionPayloadBid](#receiving-executionpayloadbid) + + + +# Gloas - Honest Validator + +## Introduction + +This document explains how a beacon-chain validator can participate in the +external block building market with the Builder-API post ePBS. + +Validators request a [`SignedExecutionPayloadBid`][signed-execution-payload-bid] +from the external builder network to put it in their `SignedBeaconBlock`. The +external builder network broadcasts the +[`SignedExecutionPayloadEnvelope`][signed-execution-payload-envelope] +corresponding to the bid to the PTC committee. + +## Constants + +| Name | Value | +| ----------------------------------------- | ------------------ | +| `MAX_SALT_BYTES` | `4096` | + +## Containers + +### New Containers + +#### `BidRequestAuth` + +`BidRequestAuth` is used to authenticate requests to get the bid from a builder. +This is useful so that other builders do not DDOS the builder to get their +latest bid. + +```python +class BidRequestAuth(Container): + salt: ByteList[MAX_SALT_BYTES] +``` + +#### `SignedBidRequestAuth` + +```python +class SignedBidRequestAuth(Container): + message: BidRequestAuth + signature: BLSSignature +``` + +## Helper + +### `get_proposer_slots_in_upcoming_epoch` + +*Note*: `compute_start_slot_at_epoch` and `get_current_epoch` are defined in the +[Gloas consensus specs][gloas-consensus-specs]. + +```python +def get_proposer_slots_in_upcoming_epoch( + state: BeaconState, validator_index: ValidatorIndex +) -> List[Slot]: + """ + Return all slots where validator_index is the proposer within the lookahead window in the next epoch. + """ + proposer_slots = [] + current_epoch_start_slot = compute_start_slot_at_epoch(get_current_epoch(state)) + next_epoch_proposer_lookahead = state.proposer_lookahead[SLOTS_PER_EPOCH:] + + for offset, proposer_index in enumerate(next_epoch_proposer_lookahead): + if proposer_index == validator_index: + slot = current_epoch_start_slot + SLOTS_PER_EPOCH + offset + proposer_slots.append(slot) + + return proposer_slots +``` + +## Bid Authentication + +### Constructing the `BidRequestAuth` + +To construct the `BidRequestAuth`, we need to fill the following information: + +- `salt`: This is a 4kB salt which has to be specific to each whitelisted + builder. The spec requires the proposer to set it to the URL provided by the + whitelisted builder. + +The validator constructs the `SignedBidRequestAuth` by signing the +`BidRequestAuth`. It sends the `SignedBidRequestAuth` in the request body along +with the request to get the bid in the +[`getExecutionPayloadBid`][get-execution-payload-bid-api] API call. + +## Validator Registrations + +### Constructing the `ValidatorRegistrationV2` + +To do this, the validator client assembles a +[`ValidatorRegistrationV2`][validator-registration-v2] with the following +information: + +- `fee_recipient`: An execution layer address where fees for the validator + should go. +- `gas_limit`: The value a validator prefers for the execution block gas limit. +- `validator_index`: The validator's index. Used to identify the beacon chain + validator and verify the wrapping signature. +- `max_trusted_bid`: The amount(in Gwei) the proposer is willing to accept as a + trusted execution layer payment from the builder. +- `proposal_slot`: This is set to the slot in which the validator will be + proposing. This can be looked up in `state.proposer_lookahead`. + +### Validator Registration dissemination + +This specification suggests validators re-submit registrations only if they will +be proposing in the upcoming epoch(E+1). This is such that we do not send too +many validator registrations all at once to builders. Validators run +`create_validator_registrations` at every epoch boundary to create validator +registrations for all the slots they will be proposing in the upcoming epoch. + +```python +def create_validator_registrations( + state: BeaconState, + validator_index: ValidatorIndex, + gas_limit: uint64, + builder_preferences: BuilderPreferences, + fee_recipient: ExecutionAddress, +) -> List[ValidatorRegistrationV2]: + slots = get_proposer_slots_in_upcoming_epoch(state, validator_index) + registrations: List[ValidatorRegistrationV2] = [] + + for slot in slots: + registrations.append( + ValidatorRegistrationV2( + fee_recipient=fee_recipient, + gas_limit=gas_limit, + validator_index=validator_index, + builder_preferences=builder_preferences, + proposal_slot=slot, + ) + ) + + return registrations +``` + +## Validating a `SignedExecutionPayloadBid` + +When the proposer receives a +[`SignedExecutionPayloadBid`][signed-execution-payload-bid] from a builder, it +can validate the bid using `validate_bid`. It can discard the bid if the +conditions are not satisfied. + +*Note*: `hash_tree_root`, `get_randao_mix`, and `get_current_epoch` are defined +in the [Gloas consensus specs][gloas-consensus-specs]. The predicates +[`is_active_builder`][is-active-builder], +[`can_builder_cover_bid`][can-builder-cover-bid], and +[`verify_execution_payload_bid_signature`][verify-execution-payload-bid-signature] +are also defined in the consensus specs. + +```python +def validate_bid( + state: BeaconState, + reg: SignedValidatorRegistrationV2, + signed_bid: SignedExecutionPayloadBid, + fee_recipient: ExecutionAddress, +) -> bool: + bid = signed_bid.message + + assert is_active_builder(state, bid.builder_index) + assert bid.slot == state.slot + assert bid.fee_recipient == fee_recipient + assert bid.parent_block_hash == state.latest_block_hash + assert bid.parent_block_root == hash_tree_root(state.latest_block_header) + assert bid.prev_randao == get_randao_mix(state, get_current_epoch(state)) + assert bid.gas_limit <= reg.message.gas_limit + + assert bid.execution_payment <= reg.message.builder_preferences.max_trusted_bid + + if bid.value > 0: + assert can_builder_cover_bid(state, bid.builder_index, bid.value) + + return verify_execution_payload_bid_signature(state, signed_bid) +``` + +Note that, the fee recipient specified in `bid.fee_recipient` does not +necessarily correspond to the fee recipient of the execution payload. Even if a +builder pays the validator via execution layer payments, we require that the +bid's fee recipient matches the validators expected fee recipient and not the +builder's fee recipient. + +To express per-builder preferences we need validators to remember which +registration they have sent to the builder, so that they can validate whether +the bid conforms to the preferences expressed by the validators. + +## Block proposal + +### Constructing the `BeaconBlockBody` + +#### Receiving ExecutionPayloadBid + +To obtain execution payloads for a given `slot`, a block proposer building a +block on top of a beacon `state` must take the following actions: + +1. Call upstream builder software to get a + [`SignedExecutionPayloadBid`][signed-execution-payload-bid] using the + [`getExecutionPayloadBid`][get-execution-payload-bid-api] API call. The + validator is required to send the `SignedBidRequestAuth` in the request body + in order to authenticate the request to the builder. +2. Assemble a `SignedBeaconBlock` according to the process outlined in the + [Gloas validator specs][gloas-validator-specs] but with the best + [`SignedExecutionPayloadBid`][signed-execution-payload-bid] from the prior + step. +3. The proposer returns the `SignedBeaconBlock` back to the upstream block + building software via [`submitSignedBeaconBlock`][submit-signed-beacon-block] + API call. +4. The upstream block building software constructs the + [`SignedExecutionPayloadEnvelope`][signed-execution-payload-envelope] + corresponding to the + [`SignedExecutionPayloadBid`][signed-execution-payload-bid] and broadcasts it + to the PTC committee. + +[can-builder-cover-bid]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#can_builder_cover_bid +[get-execution-payload-bid-api]: ./../../apis/builder/execution_payload_bid.yaml +[gloas-consensus-specs]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas +[gloas-validator-specs]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/validator.md#block-proposal +[is-active-builder]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#is_active_builder +[signed-execution-payload-bid]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadbid +[signed-execution-payload-envelope]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadenvelope +[submit-signed-beacon-block]: ./../../apis/builder/beacon_block.yaml +[validator-registration-v2]: ./builder.md#validatorregistrationv2 +[verify-execution-payload-bid-signature]: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#verify_execution_payload_bid_signature diff --git a/types/gloas/bid_request_auth.yaml b/types/gloas/bid_request_auth.yaml new file mode 100644 index 0000000..0393bcd --- /dev/null +++ b/types/gloas/bid_request_auth.yaml @@ -0,0 +1,17 @@ +Gloas: + BidRequestAuth: + type: object + required: [salt] + properties: + salt: + type: string + maxLength: 4096 + description: "A builder-specific salt (max 4096 bytes) used to authenticate bid requests. Must be set to the URL provided by the whitelisted builder." + SignedBidRequestAuth: + type: object + required: [message, signature] + properties: + message: + $ref: "#/Gloas/BidRequestAuth" + signature: + $ref: "../../beacon-apis/types/primitive.yaml#/Signature" \ No newline at end of file diff --git a/types/gloas/registration.yaml b/types/gloas/registration.yaml new file mode 100644 index 0000000..b0d46f4 --- /dev/null +++ b/types/gloas/registration.yaml @@ -0,0 +1,38 @@ +Gloas: + BuilderPreferences: + type: object + description: "Per-builder preferences that a validator can express." + required: [max_trusted_bid] + properties: + max_trusted_bid: + $ref: "../../beacon-apis/types/primitive.yaml#/Uint64" + description: "Indicates the maximum amount that a proposer is willing to accept as a trusted payment amount from the builder." + ValidatorRegistrationV2: + type: object + description: "The `ValidatorRegistrationV2` object for Gloas fork, replacing pubkey and timestamp with validator_index, proposal_slot, and builder_preferences." + required: [validator_index, fee_recipient, proposal_slot, gas_limit, builder_preferences] + properties: + validator_index: + $ref: "../../beacon-apis/types/primitive.yaml#/Uint64" + description: "Validator index. Used to identify the beacon chain validator and verify the signature." + fee_recipient: + $ref: "../../beacon-apis/types/primitive.yaml#/ExecutionAddress" + description: "Address to receive fees from the block." + proposal_slot: + $ref: "../../beacon-apis/types/primitive.yaml#/Uint64" + description: "The slot at which this validator is proposing." + gas_limit: + $ref: "../../beacon-apis/types/primitive.yaml#/Uint64" + description: "Preferred gas limit of validator." + builder_preferences: + $ref: "#/Gloas/BuilderPreferences" + description: "Per-builder preferences." + SignedValidatorRegistrationV2: + type: object + description: "The `SignedValidatorRegistrationV2` object for Gloas fork." + required: [message, signature] + properties: + message: + $ref: "#/Gloas/ValidatorRegistrationV2" + signature: + $ref: "../../beacon-apis/types/primitive.yaml#/Signature" \ No newline at end of file diff --git a/wordlist.txt b/wordlist.txt index 970e86c..353ab83 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -28,6 +28,12 @@ validator's vc wei EIP +ePBS Fulu fulu -submitBlindedBlockV \ No newline at end of file +Gloas +gloas +Gwei +PTC +submitBlindedBlockV +ValidatorRegistrationsV \ No newline at end of file