mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
Finish Modifications to get_attesting_indices()
This commit is contained in:
@@ -56,11 +56,13 @@ pub mod attesting_indices_electra {
|
||||
pub fn get_indexed_attestation<E: EthSpec>(
|
||||
committees: &[BeaconCommittee],
|
||||
attestation: &AttestationElectra<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<IndexedAttestation<E>, BlockOperationError<Invalid>> {
|
||||
let attesting_indices = get_attesting_indices::<E>(
|
||||
committees,
|
||||
&attestation.aggregation_bits,
|
||||
&attestation.committee_bits,
|
||||
spec,
|
||||
)?;
|
||||
|
||||
Ok(IndexedAttestation::Electra(IndexedAttestationElectra {
|
||||
@@ -73,18 +75,45 @@ pub mod attesting_indices_electra {
|
||||
pub fn get_indexed_attestation_from_state<E: EthSpec>(
|
||||
beacon_state: &BeaconState<E>,
|
||||
attestation: &AttestationElectra<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<IndexedAttestation<E>, BlockOperationError<Invalid>> {
|
||||
let committees = beacon_state.get_beacon_committees_at_slot(attestation.data.slot)?;
|
||||
get_indexed_attestation(&committees, attestation)
|
||||
get_indexed_attestation(&committees, attestation, spec)
|
||||
}
|
||||
|
||||
/// Shortcut for getting the attesting indices while fetching the committee from the state's cache.
|
||||
pub fn get_attesting_indices_from_state<E: EthSpec>(
|
||||
state: &BeaconState<E>,
|
||||
att: &AttestationElectra<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<u64>, BeaconStateError> {
|
||||
let committees = state.get_beacon_committees_at_slot(att.data.slot)?;
|
||||
get_attesting_indices::<E>(&committees, &att.aggregation_bits, &att.committee_bits)
|
||||
get_attesting_indices::<E>(
|
||||
&committees,
|
||||
&att.aggregation_bits,
|
||||
&att.committee_bits,
|
||||
spec,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a set of the PTC if the attestation slot is post EIP-7732, otherwise returns an empty set.
|
||||
pub fn get_ptc_set<E: EthSpec>(
|
||||
committees: &[BeaconCommittee],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<HashSet<u64>, BeaconStateError> {
|
||||
let attestation_slot = committees
|
||||
.get(0)
|
||||
.map(|committee| committee.slot)
|
||||
.ok_or(Error::NoCommitteeFound(0))?;
|
||||
if spec
|
||||
.fork_name_at_slot::<E>(attestation_slot)
|
||||
.eip7732_enabled()
|
||||
{
|
||||
PTC::<E>::from_committees(committees)
|
||||
.map(|ptc| ptc.into_iter().map(|i| i as u64).collect())
|
||||
} else {
|
||||
Ok(HashSet::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns validator indices which participated in the attestation, sorted by increasing index.
|
||||
@@ -94,9 +123,11 @@ pub mod attesting_indices_electra {
|
||||
committees: &[BeaconCommittee],
|
||||
aggregation_bits: &BitList<E::MaxValidatorsPerSlot>,
|
||||
committee_bits: &BitVector<E::MaxCommitteesPerSlot>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<u64>, BeaconStateError> {
|
||||
let mut attesting_indices = vec![];
|
||||
|
||||
let ptc_set = get_ptc_set::<E>(committees, spec)?;
|
||||
let committee_indices = get_committee_indices::<E>(committee_bits);
|
||||
|
||||
let mut committee_offset = 0;
|
||||
@@ -125,6 +156,8 @@ pub mod attesting_indices_electra {
|
||||
}
|
||||
None
|
||||
})
|
||||
// EIP-7732: filter out the PTC
|
||||
.filter(|index| !ptc_set.contains(index))
|
||||
.collect::<HashSet<u64>>();
|
||||
|
||||
attesting_indices.extend(committee_attesters);
|
||||
@@ -156,6 +189,7 @@ pub mod attesting_indices_electra {
|
||||
pub fn get_attesting_indices_from_state<E: EthSpec>(
|
||||
state: &BeaconState<E>,
|
||||
att: AttestationRef<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<u64>, BeaconStateError> {
|
||||
match att {
|
||||
AttestationRef::Base(att) => {
|
||||
@@ -166,7 +200,7 @@ pub fn get_attesting_indices_from_state<E: EthSpec>(
|
||||
)
|
||||
}
|
||||
AttestationRef::Electra(att) => {
|
||||
attesting_indices_electra::get_attesting_indices_from_state::<E>(state, att)
|
||||
attesting_indices_electra::get_attesting_indices_from_state::<E>(state, att, spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,14 @@ pub fn get_payload_attesting_indices<E: EthSpec>(
|
||||
) -> Result<Vec<u64>, BeaconStateError> {
|
||||
let ptc = state.get_ptc(slot)?;
|
||||
let bitlist = &payload_attestation.aggregation_bits;
|
||||
if bitlist.len() != ptc.len() {
|
||||
if bitlist.len() != E::PTCSize::to_usize() {
|
||||
return Err(BeaconStateError::InvalidBitfield);
|
||||
}
|
||||
|
||||
let mut attesting_indices = Vec::<u64>::new();
|
||||
for (i, index) in ptc.into_iter().enumerate() {
|
||||
if let Ok(true) = bitlist.get(i) {
|
||||
attesting_indices.push(*index as u64);
|
||||
attesting_indices.push(index as u64);
|
||||
}
|
||||
}
|
||||
attesting_indices.sort_unstable();
|
||||
|
||||
@@ -161,6 +161,7 @@ impl<E: EthSpec> ConsensusContext<E> {
|
||||
&'a mut self,
|
||||
state: &BeaconState<E>,
|
||||
attestation: AttestationRef<'a, E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<IndexedAttestationRef<E>, BlockOperationError<AttestationInvalid>> {
|
||||
let key = attestation.tree_hash_root();
|
||||
match attestation {
|
||||
@@ -177,7 +178,9 @@ impl<E: EthSpec> ConsensusContext<E> {
|
||||
Entry::Occupied(occupied) => Ok(occupied.into_mut()),
|
||||
Entry::Vacant(vacant) => {
|
||||
let indexed_attestation =
|
||||
attesting_indices_electra::get_indexed_attestation_from_state(state, attn)?;
|
||||
attesting_indices_electra::get_indexed_attestation_from_state(
|
||||
state, attn, spec,
|
||||
)?;
|
||||
Ok(vacant.insert(indexed_attestation))
|
||||
}
|
||||
},
|
||||
|
||||
@@ -282,7 +282,8 @@ where
|
||||
.body()
|
||||
.attestations()
|
||||
.try_for_each(|attestation| {
|
||||
let indexed_attestation = ctxt.get_indexed_attestation(self.state, attestation)?;
|
||||
let indexed_attestation =
|
||||
ctxt.get_indexed_attestation(self.state, attestation, self.spec)?;
|
||||
|
||||
self.sets.push(indexed_attestation_signature_set(
|
||||
self.state,
|
||||
|
||||
@@ -87,7 +87,7 @@ pub fn verify_attestation_for_state<'ctxt, E: EthSpec>(
|
||||
verify_casper_ffg_vote(attestation, state)?;
|
||||
|
||||
// Check signature and bitfields
|
||||
let indexed_attestation = ctxt.get_indexed_attestation(state, attestation)?;
|
||||
let indexed_attestation = ctxt.get_indexed_attestation(state, attestation, spec)?;
|
||||
is_valid_indexed_attestation(state, indexed_attestation, verify_signatures, spec)?;
|
||||
|
||||
Ok(indexed_attestation)
|
||||
|
||||
@@ -1843,40 +1843,12 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
|
||||
/// Get the PTC
|
||||
/// Requires the committee cache to be initialized.
|
||||
/// TODO(EIP-7732): is it easier to return u64 or usize?
|
||||
/// TODO(EIP-7732): definitely gonna have to cache this..
|
||||
pub fn get_ptc(&self, slot: Slot) -> Result<FixedVector<usize, E::PTCSize>, Error> {
|
||||
// this function is only used here and
|
||||
// I have no idea where else to put it
|
||||
fn bit_floor(n: u64) -> u64 {
|
||||
if n == 0 {
|
||||
0
|
||||
} else {
|
||||
1 << (n.leading_zeros() as u64 ^ 63)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ptc(&self, slot: Slot) -> Result<PTC<E>, Error> {
|
||||
let committee_cache = self.committee_cache_at_slot(slot)?;
|
||||
let committee_count_per_slot = committee_cache.committees_per_slot();
|
||||
|
||||
let committees_per_slot = bit_floor(std::cmp::min(
|
||||
committee_count_per_slot as u64,
|
||||
E::PTCSize::to_u64(),
|
||||
));
|
||||
let members_per_committee =
|
||||
committee_count_per_slot.safe_div(committees_per_slot)? as usize;
|
||||
|
||||
let committees = committee_cache.get_beacon_committees_at_slot(slot)?;
|
||||
let mut validator_indices = Vec::with_capacity(committees_per_slot as usize);
|
||||
for idx in 0..committees_per_slot {
|
||||
let beacon_committee = committees
|
||||
.get(idx as usize)
|
||||
.ok_or_else(|| Error::InvalidCommitteeIndex(idx))?;
|
||||
validator_indices
|
||||
.extend_from_slice(&beacon_committee.committee[..members_per_committee]);
|
||||
}
|
||||
|
||||
Ok(FixedVector::new(validator_indices)?)
|
||||
PTC::from_committees(&committees)
|
||||
}
|
||||
|
||||
/// Build all caches (except the tree hash cache), if they need to be built.
|
||||
|
||||
@@ -67,6 +67,7 @@ pub mod pending_consolidation;
|
||||
pub mod pending_partial_withdrawal;
|
||||
pub mod proposer_preparation_data;
|
||||
pub mod proposer_slashing;
|
||||
pub mod ptc;
|
||||
pub mod relative_epoch;
|
||||
pub mod selection_proof;
|
||||
pub mod shuffling_id;
|
||||
@@ -236,6 +237,7 @@ pub use crate::preset::{
|
||||
};
|
||||
pub use crate::proposer_preparation_data::ProposerPreparationData;
|
||||
pub use crate::proposer_slashing::ProposerSlashing;
|
||||
pub use crate::ptc::PTC;
|
||||
pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch};
|
||||
pub use crate::runtime_var_list::RuntimeVariableList;
|
||||
pub use crate::selection_proof::SelectionProof;
|
||||
|
||||
55
consensus/types/src/ptc.rs
Normal file
55
consensus/types/src/ptc.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use crate::*;
|
||||
use safe_arith::SafeArith;
|
||||
|
||||
/// TODO(EIP-7732): is it easier to return u64 or usize?
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct PTC<E: EthSpec>(FixedVector<usize, E::PTCSize>);
|
||||
|
||||
impl<E: EthSpec> PTC<E> {
|
||||
pub fn from_committees(committees: &[BeaconCommittee]) -> Result<Self, BeaconStateError> {
|
||||
// this function is only used here and
|
||||
// I have no idea where else to put it
|
||||
fn bit_floor(n: u64) -> u64 {
|
||||
if n == 0 {
|
||||
0
|
||||
} else {
|
||||
1 << (n.leading_zeros() as u64 ^ 63)
|
||||
}
|
||||
}
|
||||
|
||||
let committee_count_per_slot = committees.len() as u64;
|
||||
let committees_per_slot = bit_floor(std::cmp::min(
|
||||
committee_count_per_slot,
|
||||
E::PTCSize::to_u64(),
|
||||
)) as usize;
|
||||
let members_per_committee = E::PTCSize::to_usize().safe_div(committees_per_slot)?;
|
||||
|
||||
let mut ptc = Vec::with_capacity(E::PTCSize::to_usize());
|
||||
for idx in 0..committees_per_slot {
|
||||
let beacon_committee = committees
|
||||
.get(idx as usize)
|
||||
.ok_or_else(|| Error::InvalidCommitteeIndex(idx as u64))?;
|
||||
ptc.extend_from_slice(&beacon_committee.committee[..members_per_committee]);
|
||||
}
|
||||
|
||||
Ok(Self(FixedVector::from(ptc)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> IntoIterator for &'a PTC<E> {
|
||||
type Item = &'a usize;
|
||||
type IntoIter = std::slice::Iter<'a, usize>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> IntoIterator for PTC<E> {
|
||||
type Item = usize;
|
||||
type IntoIter = std::vec::IntoIter<usize>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user