diff --git a/specs/gloas/builder.md b/specs/gloas/builder.md index df8f27f361..5385f043e5 100644 --- a/specs/gloas/builder.md +++ b/specs/gloas/builder.md @@ -107,11 +107,11 @@ to include. They produce a `SignedExecutionPayloadBid` as follows. 05. Set `bid.prev_randao` to be the previous RANDAO of the constructed payload, that is `payload.prev_randao`. 06. Set `bid.fee_recipient` to be an execution address to receive the payment. - This address can be obtained from the proposer directly via a request or can - be set from the withdrawal credentials of the proposer. The burn address can - be used as a fallback. -07. Set `bid.gas_limit` to be the gas limit of the constructed payload, that is - `payload.gas_limit`. + The proposer's preferred fee recipient can be obtained from their + `SignedProposerPreferences` for `compute_epoch_at_slot(bid.slot)`. +07. Set `bid.gas_limit` to be the gas limit of the constructed payload. The + proposer's preferred gas limit can be obtained from their + `SignedProposerPreferences` for `compute_epoch_at_slot(bid.slot)`. 08. Set `bid.builder_index` to be the validator index of the builder performing these actions. 09. Set `bid.slot` to be the slot for which this bid is aimed. This slot diff --git a/specs/gloas/p2p-interface.md b/specs/gloas/p2p-interface.md index 31d2cdb390..e218753df0 100644 --- a/specs/gloas/p2p-interface.md +++ b/specs/gloas/p2p-interface.md @@ -11,6 +11,8 @@ - [Configuration](#configuration) - [Containers](#containers) - [Modified `DataColumnSidecar`](#modified-datacolumnsidecar) + - [New `ProposerPreferences`](#new-proposerpreferences) + - [New `SignedProposerPreferences`](#new-signedproposerpreferences) - [Helpers](#helpers) - [Modified `verify_data_column_sidecar`](#modified-verify_data_column_sidecar) - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) @@ -21,6 +23,7 @@ - [`execution_payload`](#execution_payload) - [`payload_attestation_message`](#payload_attestation_message) - [`execution_payload_bid`](#execution_payload_bid) + - [`proposer_preferences`](#proposer_preferences) - [Blob subnets](#blob-subnets) - [`data_column_sidecar_{subnet_id}`](#data_column_sidecar_subnet_id) - [Attestation subnets](#attestation-subnets) @@ -103,6 +106,28 @@ class DataColumnSidecar(Container): beacon_block_root: Root ``` +#### New `ProposerPreferences` + +*[New in Gloas:EIP7732]* + +```python +class ProposerPreferences(Container): + proposal_epoch: Epoch + validator_index: ValidatorIndex + fee_recipient: ExecutionAddress + gas_limit: uint64 +``` + +#### New `SignedProposerPreferences` + +*[New in Gloas:EIP7732]* + +```python +class SignedProposerPreferences(Container): + message: ProposerPreferences + signature: BLSSignature +``` + ### Helpers ##### Modified `verify_data_column_sidecar` @@ -157,6 +182,7 @@ are given in this table: | `execution_payload_bid` | `SignedExecutionPayloadBid` | | `execution_payload` | `SignedExecutionPayloadEnvelope` | | `payload_attestation_message` | `PayloadAttestationMessage` | +| `proposer_preferences` | `SignedProposerPreferences` | ##### Global topics @@ -282,6 +308,10 @@ The following validations MUST pass before forwarding the `is_builder_withdrawal_credential(state.validators[bid.builder_index].withdrawal_credentials)` returns `True`. - _[REJECT]_ `bid.execution_payment` is zero. +- _[REJECT]_ `bid.fee_recipient` matches the `fee_recipient` from the proposer's + `SignedProposerPreferences` for `compute_epoch_at_slot(bid.slot)`. +- _[REJECT]_ `bid.gas_limit` matches the `gas_limit` from the proposer's + `SignedProposerPreferences` for `compute_epoch_at_slot(bid.slot)`. - _[IGNORE]_ this is the first signed bid seen with a valid signature from the given builder for this slot. - _[IGNORE]_ this bid is the highest value bid seen for the corresponding slot @@ -297,6 +327,29 @@ The following validations MUST pass before forwarding the - _[REJECT]_ `signed_execution_payload_bid.signature` is valid with respect to the `bid.builder_index`. +###### `proposer_preferences` + +*[New in Gloas:EIP7732]* + +This topic is used to propagate signed proposer preferences as +`SignedProposerPreferences`. These messages allow validators to communicate +their preferred `fee_recipient` and `gas_limit` to builders. + +The following validations MUST pass before forwarding the +`signed_proposer_preferences` on the network, assuming the alias +`preferences = signed_proposer_preferences.message`: + +- _[IGNORE]_ `preferences.proposal_epoch` is the next epoch (with a + `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. + `preferences.proposal_epoch == get_current_epoch(state) + 1`. +- _[REJECT]_ `preferences.validator_index` is present in the next epoch's + portion of `state.proposer_lookahead` -- i.e. + `is_next_epoch_proposer(state, preferences.validator_index)` returns `True`. +- _[IGNORE]_ The `signed_proposer_preferences` is the first valid message + received from the validator with index `preferences.validator_index`. +- _[REJECT]_ `signed_proposer_preferences.signature` is valid with respect to + the validator's public key. + ##### Blob subnets ###### `data_column_sidecar_{subnet_id}` diff --git a/specs/gloas/validator.md b/specs/gloas/validator.md index 093501e35a..5f404c2a8c 100644 --- a/specs/gloas/validator.md +++ b/specs/gloas/validator.md @@ -14,6 +14,7 @@ - [Attestation](#attestation) - [Sync Committee participations](#sync-committee-participations) - [Block proposal](#block-proposal) + - [Broadcasting `SignedProposerPreferences`](#broadcasting-signedproposerpreferences) - [Constructing `signed_execution_payload_bid`](#constructing-signed_execution_payload_bid) - [Constructing `payload_attestations`](#constructing-payload_attestations) - [Blob sidecars](#blob-sidecars) @@ -119,6 +120,33 @@ any slot during which `is_proposer(state, validator_index)` returns `True`. The mechanism to prepare this beacon block and related sidecars differs from previous forks as follows +#### Broadcasting `SignedProposerPreferences` + +At the beginning of each epoch, a validator MAY broadcast a +`SignedProposerPreferences` message to the `proposer_preferences` gossip topic +if `is_next_epoch_proposer(state, validator_index)` returns `True`. This allows +builders to construct execution payloads with the validator's preferred +`fee_recipient` and `gas_limit`. + +```python +def is_next_epoch_proposer(state: BeaconState, validator_index: ValidatorIndex) -> bool: + """ + Check if ``validator_index`` is scheduled to propose in the next epoch. + """ + next_epoch_proposers = state.proposer_lookahead[SLOTS_PER_EPOCH:] + return validator_index in next_epoch_proposers +``` + +To construct the `SignedProposerPreferences`: + +1. Set `preferences.proposal_epoch` to `get_current_epoch(state) + 1`. +2. Set `preferences.validator_index` to the validator's index. +3. Set `preferences.fee_recipient` to the execution address where the validator + wishes to receive builder payments. +4. Set `preferences.gas_limit` to the validator's preferred gas limit for + execution payloads. +5. Sign the `ProposerPreferences` with the validator's signing key. + #### Constructing `signed_execution_payload_bid` To obtain `signed_execution_payload_bid`, a block proposer building a block on