Gloas bid and preference verification (#9036)

Gossip verify and cache bids and proposer preferences. This PR also ensures we subscribe to new fork topics one epoch early instead of two slots early. This is required for proposer preferences.


  


Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>
This commit is contained in:
Eitan Seri-Levi
2026-04-15 01:39:59 +09:00
committed by GitHub
parent 8c8facd0cd
commit b40a178111
19 changed files with 2267 additions and 79 deletions

View File

@@ -12,9 +12,9 @@ use types::{
BuilderIndex, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, InconsistentFork,
IndexedAttestation, IndexedAttestationRef, IndexedPayloadAttestation, ProposerSlashing,
SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
SignedBlsToExecutionChange, SignedContributionAndProof, SignedExecutionPayloadBid, SignedRoot,
SignedVoluntaryExit, SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData,
consts::gloas::BUILDER_INDEX_SELF_BUILD,
SignedBlsToExecutionChange, SignedContributionAndProof, SignedExecutionPayloadBid,
SignedProposerPreferences, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate,
SyncAggregatorSelectionData, consts::gloas::BUILDER_INDEX_SELF_BUILD,
};
pub type Result<T> = std::result::Result<T, Error>;
@@ -389,6 +389,37 @@ where
Ok(SignatureSet::multiple_pubkeys(signature, pubkeys, message))
}
pub fn proposer_preferences_signature_set<'a, E, F>(
state: &'a BeaconState<E>,
get_pubkey: F,
signed_proposer_preferences: &'a SignedProposerPreferences,
spec: &'a ChainSpec,
) -> Result<SignatureSet<'a>>
where
E: EthSpec,
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
{
let preferences = &signed_proposer_preferences.message;
let validator_index = preferences.validator_index as usize;
let proposal_epoch = preferences.proposal_slot.epoch(E::slots_per_epoch());
let proposal_fork = spec.fork_at_epoch(proposal_epoch);
let domain = spec.get_domain(
proposal_epoch,
Domain::ProposerPreferences,
&proposal_fork,
state.genesis_validators_root(),
);
let message = preferences.signing_root(domain);
Ok(SignatureSet::single_pubkey(
&signed_proposer_preferences.signature,
get_pubkey(validator_index).ok_or(Error::ValidatorUnknown(validator_index as u64))?,
message,
))
}
pub fn execution_payload_bid_signature_set<'a, E, F>(
state: &'a BeaconState<E>,
get_builder_pubkey: F,
@@ -407,10 +438,16 @@ where
// See `process_execution_payload_bid`.
return Ok(None);
}
let bid_epoch = signed_execution_payload_bid
.message
.slot
.epoch(E::slots_per_epoch());
let bid_fork = spec.fork_at_epoch(bid_epoch);
let domain = spec.get_domain(
state.current_epoch(),
bid_epoch,
Domain::BeaconBuilder,
&state.fork(),
&bid_fork,
state.genesis_validators_root(),
);