diff --git a/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs b/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs index 088f7b8192..22238a2c4d 100644 --- a/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs +++ b/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs @@ -25,6 +25,7 @@ use types::{ #[derive(Debug, PartialEq)] pub enum Error { InvalidFlagIndex(usize), + NoUnslashedParticipatingIndices, MissingEffectiveBalance(usize), } @@ -66,7 +67,7 @@ struct SingleEpochParticipationCache { /// It would be ideal to maintain a reference to the `BeaconState` here rather than copying the /// `ParticipationFlags`, however that would cause us to run into mutable reference limitations /// upstream. - unslashed_participating_indices: HashMap, + unslashed_participating_indices: Option>, /// Stores the sum of the balances for all validators in `self.unslashed_participating_indices` /// for all flags in `NUM_FLAG_INDICES`. /// @@ -78,14 +79,12 @@ struct SingleEpochParticipationCache { } impl SingleEpochParticipationCache { - fn new(hashmap_len: usize, spec: &ChainSpec) -> Self { + fn new(hashmap_len: Option, spec: &ChainSpec) -> Self { let zero_balance = Balance::zero(spec.effective_balance_increment); Self { - unslashed_participating_indices: HashMap::with_capacity_and_hasher( - hashmap_len, - Default::default(), - ), + unslashed_participating_indices: hashmap_len + .map(|len| HashMap::with_capacity_and_hasher(len, Default::default())), total_flag_balances: [zero_balance; NUM_FLAG_INDICES], total_active_balance: zero_balance, } @@ -105,7 +104,7 @@ impl SingleEpochParticipationCache { /// /// May return an error if `flag_index` is out-of-bounds. fn has_flag(&self, val_index: usize, flag_index: usize) -> Result { - if let Some(participation_flags) = self.unslashed_participating_indices.get(&val_index) { + if let Some(participation_flags) = self.unslashed_participating_indices()?.get(&val_index) { participation_flags .has_flag(flag_index) .map_err(|_| Error::InvalidFlagIndex(flag_index)) @@ -114,6 +113,14 @@ impl SingleEpochParticipationCache { } } + fn unslashed_participating_indices( + &self, + ) -> Result<&HashMap, Error> { + self.unslashed_participating_indices + .as_ref() + .ok_or(Error::NoUnslashedParticipatingIndices) + } + /// Process an **active** validator, reading from the `state` with respect to the /// `relative_epoch`. /// @@ -145,9 +152,11 @@ impl SingleEpochParticipationCache { return Ok(()); } - // Add their `ParticipationFlags` to the map. - self.unslashed_participating_indices - .insert(val_index, *epoch_participation); + // Add their `ParticipationFlags` to the map *if* we need them (for the previous epoch). + if let Some(ref mut unslashed_participating_indices) = self.unslashed_participating_indices + { + unslashed_participating_indices.insert(val_index, *epoch_participation); + } // Iterate through all the flags and increment the total flag balances for whichever flags // are set for `val_index`. @@ -192,19 +201,15 @@ impl ParticipationCache { let num_previous_epoch_active_vals = state .get_cached_active_validator_indices(RelativeEpoch::Previous)? .len(); - let num_current_epoch_active_vals = state - .get_cached_active_validator_indices(RelativeEpoch::Current)? - .len(); // Both the current/previous epoch participations are set to a capacity that is slightly // larger than required. The difference will be due slashed-but-active validators. - let mut current_epoch_participation = - SingleEpochParticipationCache::new(num_current_epoch_active_vals, spec); + let mut current_epoch_participation = SingleEpochParticipationCache::new(None, spec); let mut previous_epoch_participation = - SingleEpochParticipationCache::new(num_previous_epoch_active_vals, spec); + SingleEpochParticipationCache::new(Some(num_previous_epoch_active_vals), spec); let mut effective_balances = - HashMap::with_capacity_and_hasher(num_current_epoch_active_vals, Default::default()); + HashMap::with_capacity_and_hasher(num_previous_epoch_active_vals, Default::default()); // Contains the set of validators which are either: // @@ -330,14 +335,13 @@ impl ParticipationCache { pub fn is_active_unslashed_in_previous_epoch(&self, val_index: usize) -> bool { self.previous_epoch_participation - .unslashed_participating_indices - .contains_key(&val_index) + .unslashed_participating_indices() + .map_or(false, |indices| indices.contains_key(&val_index)) } - pub fn is_active_unslashed_in_current_epoch(&self, val_index: usize) -> bool { - self.current_epoch_participation - .unslashed_participating_indices - .contains_key(&val_index) + pub fn is_active_unslashed_in_current_epoch(&self, _val_index: usize) -> bool { + // FIXME(sproul): work out how to serve this for the validator API + false } pub fn get_effective_balance(&self, val_index: usize) -> Result { diff --git a/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs b/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs index 059bc0f84b..d06baa72f9 100644 --- a/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs +++ b/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs @@ -9,9 +9,7 @@ pub fn process_participation_flag_updates( ) -> Result<(), EpochProcessingError> { *state.previous_epoch_participation_mut()? = std::mem::take(state.current_epoch_participation_mut()?); - *state.current_epoch_participation_mut()? = VList::new(vec![ - ParticipationFlags::default(); - state.validators().len() - ])?; + *state.current_epoch_participation_mut()? = + VList::repeat(ParticipationFlags::default(), state.validators().len())?; Ok(()) } diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index ffed75e98b..5a4fe3c043 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -486,10 +486,8 @@ impl BeaconState { /// If the current epoch is the genesis epoch, the genesis_epoch is returned. pub fn previous_epoch(&self) -> Epoch { let current_epoch = self.current_epoch(); - if current_epoch > T::genesis_epoch() { - current_epoch - .safe_sub(1) - .expect("current epoch greater than genesis implies greater than 0") + if let Ok(prev_epoch) = current_epoch.safe_sub(1) { + prev_epoch } else { current_epoch }