mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-05 05:44:30 +00:00
Gloas fix proposer preferences gossip verification (#9337)
Ensure we are using the correct state when validating proposer preferences over gossip. Previously we were only using the head state. At epoch boundaries the head state could be at `current_epoch - 1`. Peers submitting proposer preferences for `current_epoch + 1` would be penalized because our head states lookahead did not have proposer duties for `current_epoch + 1` Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::{Address, ForkName, Hash256, SignedRoot, Slot};
|
||||
use bls::Signature;
|
||||
use crate::{Address, ChainSpec, Domain, EthSpec, Fork, ForkName, Hash256, SignedRoot, Slot};
|
||||
use bls::{PublicKey, Signature};
|
||||
use context_deserialize::context_deserialize;
|
||||
use educe::Educe;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -40,6 +40,25 @@ impl SignedProposerPreferences {
|
||||
signature: Signature::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify `self.signature` against the given `pubkey`.
|
||||
pub fn verify_signature<E: EthSpec>(
|
||||
&self,
|
||||
pubkey: &PublicKey,
|
||||
fork: &Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> bool {
|
||||
let proposal_epoch = self.message.proposal_slot.epoch(E::slots_per_epoch());
|
||||
let domain = spec.get_domain(
|
||||
proposal_epoch,
|
||||
Domain::ProposerPreferences,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = self.message.signing_root(domain);
|
||||
self.signature.verify(pubkey, message)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -23,7 +23,7 @@ use tree_hash_derive::TreeHash;
|
||||
use typenum::Unsigned;
|
||||
|
||||
use crate::{
|
||||
Address, ExecutionBlockHash, ExecutionPayloadBid, ProposerPreferences, Withdrawal,
|
||||
Address, ExecutionBlockHash, ExecutionPayloadBid, Withdrawal,
|
||||
attestation::{
|
||||
AttestationData, AttestationDuty, BeaconCommittee, Checkpoint, CommitteeIndex, PTC,
|
||||
ParticipationFlags, PendingAttestation,
|
||||
@@ -1341,43 +1341,6 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the validator is the proposer for the given slot in the current or next epoch.
|
||||
pub fn is_valid_proposal_slot(
|
||||
&self,
|
||||
preferences: &ProposerPreferences,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<bool, BeaconStateError> {
|
||||
let current_epoch = self.current_epoch();
|
||||
let proposal_epoch = preferences.proposal_slot.epoch(E::slots_per_epoch());
|
||||
|
||||
if proposal_epoch < current_epoch {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if proposal_epoch > current_epoch.saturating_add(spec.min_seed_lookahead) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let epoch_offset = proposal_epoch.as_u64().safe_sub(current_epoch.as_u64())?;
|
||||
|
||||
let slot_in_epoch = preferences
|
||||
.proposal_slot
|
||||
.as_u64()
|
||||
.safe_rem(E::slots_per_epoch())?;
|
||||
|
||||
let index = epoch_offset
|
||||
.safe_mul(E::slots_per_epoch())
|
||||
.and_then(|v| v.safe_add(slot_in_epoch))?;
|
||||
|
||||
let proposer_lookahead = self.proposer_lookahead()?;
|
||||
|
||||
let proposer = proposer_lookahead
|
||||
.get(index as usize)
|
||||
.ok_or(BeaconStateError::ProposerLookaheadOutOfBounds { i: index as usize })?;
|
||||
|
||||
Ok(*proposer == preferences.validator_index)
|
||||
}
|
||||
|
||||
/// Returns the beacon proposer index for each `slot` in `epoch`.
|
||||
///
|
||||
/// The returned `Vec` contains one proposer index for each slot in the epoch.
|
||||
|
||||
Reference in New Issue
Block a user