-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add specs for proposer preferences #4777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
a358402
e3fc9c6
7d30044
a293f98
61b3c49
779d003
0af56c6
079686c
3978a2a
5f11b7c
a42c256
a37c921
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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_slot: Slot | ||
| 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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just want to point out that these rules are not enforceable at all. eg. Proposer can still accept bid that has different fee recipient from
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the purpose of this is just to protect the proposer itself so the beacon node doesn't select a bid that violates the preference
jtraglia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| `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,37 @@ 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_slot` is in the next epoch -- i.e. | ||
| `compute_epoch_at_slot(preferences.proposal_slot) == get_current_epoch(state) + 1`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldn't it be better if we also allow to broadcast preferences for the current epoch, eg. if a node was offline for whatever reason it still gets a chance to submit the preference, in practice it really just needs to reach the builder 1-2 slots before the proposal change this to something like (there are few other functions we would have to update to support this) |
||
| - _[REJECT]_ `preferences.validator_index` is present at the correct slot in the | ||
| next epoch's portion of `state.proposer_lookahead` -- i.e. | ||
| `is_valid_proposal_slot(state, preferences)` 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. | ||
|
|
||
| ```python | ||
| def is_valid_proposal_slot(state: BeaconState, preferences: ProposerPreferences) -> bool: | ||
| """ | ||
| Check if the validator is the proposer for the given slot in the next epoch. | ||
| """ | ||
| index = SLOTS_PER_EPOCH + preferences.proposal_slot % SLOTS_PER_EPOCH | ||
| return state.proposer_lookahead[index] == preferences.validator_index | ||
| ``` | ||
|
|
||
| ##### Blob subnets | ||
|
|
||
| ###### `data_column_sidecar_{subnet_id}` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,38 @@ 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` messages to the `proposer_preferences` gossip topic | ||
| for each slot returned by `get_upcoming_proposal_slots(state, validator_index)`. | ||
| This allows builders to construct execution payloads with the validator's | ||
| preferred `fee_recipient` and `gas_limit`. | ||
|
|
||
| ```python | ||
| def get_upcoming_proposal_slots( | ||
| state: BeaconState, validator_index: ValidatorIndex | ||
| ) -> Sequence[Slot]: | ||
| """ | ||
| Get the slots in the next epoch for which ``validator_index`` is proposing. | ||
| """ | ||
| return [ | ||
| Slot(compute_start_slot_at_epoch(get_current_epoch(state) + Epoch(1)) + offset) | ||
| for offset, proposer_index in enumerate(state.proposer_lookahead[SLOTS_PER_EPOCH:]) | ||
| if validator_index == proposer_index | ||
| ] | ||
| ``` | ||
|
|
||
| To construct each `SignedProposerPreferences`: | ||
|
|
||
| 1. Set `preferences.proposal_slot` to `upcoming_proposal_slots[i]`. | ||
| 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. | ||
jtraglia marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #### Constructing `signed_execution_payload_bid` | ||
|
|
||
| To obtain `signed_execution_payload_bid`, a block proposer building a block on | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we switched to
proposal_slotnow, this should probably no longer usecompute_epoch_at_slot, there are several other places like this, it's very unlikely but if a proposer has 2 slots in the epoch there could be 2 different preferences for the same epoch