@@ -23,7 +23,7 @@ use types::{
2323
2424/// A balance which will never be below the specified `minimum`.
2525///
26- /// This is an attempt to ensure the `EFFECTIVE_BALANCE_INCREMENT` minimum is always respected.
26+ /// This is an effort to ensure the `EFFECTIVE_BALANCE_INCREMENT` minimum is always respected.
2727#[ derive( PartialEq , Debug , Clone , Copy ) ]
2828struct Balance {
2929 raw : u64 ,
@@ -52,7 +52,7 @@ impl Balance {
5252struct SingleEpochParticipationCache {
5353 /// Maps an active validator index to their participation flags.
5454 ///
55- /// To reiterate, only active validator indices are stored in this map.
55+ /// To reiterate, only active and unslashed validator indices are stored in this map.
5656 ///
5757 /// ## Note
5858 ///
@@ -71,7 +71,7 @@ struct SingleEpochParticipationCache {
7171}
7272
7373impl SingleEpochParticipationCache {
74- pub fn new ( hashmap_len : usize , spec : & ChainSpec ) -> Self {
74+ fn new ( hashmap_len : usize , spec : & ChainSpec ) -> Self {
7575 let zero_balance = Balance :: zero ( spec. effective_balance_increment ) ;
7676
7777 Self {
@@ -81,54 +81,64 @@ impl SingleEpochParticipationCache {
8181 }
8282 }
8383
84- /// Process an **active** validator.
84+ /// Shrink any allocations to the smallest necessary size.
85+ fn shrink_to_fit ( & mut self ) {
86+ self . unslashed_participating_indices . shrink_to_fit ( )
87+ }
88+
89+ /// Returns the total balance of attesters who have `flag_index` set.
90+ fn total_flag_balance ( & self , flag_index : usize ) -> Result < u64 , ArithError > {
91+ self . total_flag_balances
92+ . get ( flag_index)
93+ . map ( Balance :: get)
94+ . ok_or ( ArithError :: Overflow )
95+ }
96+
97+ /// Process an **active** validator, reading from the `state` with respect to the
98+ /// `relative_epoch`.
8599 ///
86100 /// ## Errors
87101 ///
88- /// - The provided `state` **must** be Altair, otherwise an error will be returned.
102+ /// - The provided `state` **must** be Altair. An error will be returned otherwise .
89103 ///
90104 /// ## Warning
91105 ///
92106 /// - It is a logic error to provide an inactive validator to this function.
93- pub fn process_active_validator < T : EthSpec > (
107+ fn process_active_validator < T : EthSpec > (
94108 & mut self ,
95109 val_index : usize ,
96110 state : & BeaconState < T > ,
97- epoch_participation : & [ ParticipationFlags ] ,
111+ relative_epoch : RelativeEpoch ,
98112 ) -> Result < ( ) , BeaconStateError > {
99113 let val_balance = state. get_effective_balance ( val_index) ?;
100114
101- // All active validator increase the total active balance.
115+ let epoch_participation = match relative_epoch {
116+ RelativeEpoch :: Current => state. current_epoch_participation ( ) ,
117+ RelativeEpoch :: Previous => state. previous_epoch_participation ( ) ,
118+ _ => Err ( BeaconStateError :: EpochOutOfBounds ) ,
119+ } ?
120+ . get ( val_index)
121+ . ok_or ( BeaconStateError :: ParticipationOutOfBounds ( val_index) ) ?;
122+
123+ // All active validators increase the total active balance.
102124 self . total_active_balance . safe_add_assign ( val_balance) ?;
103125
126+ // Only unslashed validators may proceed.
104127 if state. get_validator ( val_index) ?. slashed {
105128 return Ok ( ( ) ) ;
106129 }
107130
131+ // Add their `ParticipationFlags` to the map.
132+ self . unslashed_participating_indices
133+ . insert ( val_index, * epoch_participation) ;
134+
108135 // Iterate through all the flags and increment the total flag balances for whichever flags
109136 // are set for `val_index`.
110- self . total_flag_balances
111- . iter_mut ( )
112- . enumerate ( )
113- . try_for_each ( |( flag, balance) | {
114- if epoch_participation
115- . get ( val_index)
116- . ok_or ( BeaconStateError :: ParticipationOutOfBounds ( val_index) ) ?
117- . has_flag ( flag) ?
118- {
119- balance. safe_add_assign ( val_balance) ?;
120- }
121-
122- Ok :: < _ , BeaconStateError > ( ( ) )
123- } ) ?;
124-
125- // The validator is active an unslashed, add their `ParticipationFlags` to the map.
126- self . unslashed_participating_indices . insert (
127- val_index,
128- * epoch_participation
129- . get ( val_index)
130- . ok_or ( BeaconStateError :: ParticipationOutOfBounds ( val_index) ) ?,
131- ) ;
137+ for ( flag, balance) in self . total_flag_balances . iter_mut ( ) . enumerate ( ) {
138+ if epoch_participation. has_flag ( flag) ? {
139+ balance. safe_add_assign ( val_balance) ?;
140+ }
141+ }
132142
133143 Ok ( ( ) )
134144 }
@@ -152,7 +162,7 @@ impl ParticipationCache {
152162 ///
153163 /// ## Errors
154164 ///
155- /// - The provided `state` **must** be an Altair state, otherwise an error will be returned.
165+ /// - The provided `state` **must** be an Altair state. An error will be returned otherwise .
156166 pub fn new < T : EthSpec > (
157167 state : & BeaconState < T > ,
158168 spec : & ChainSpec ,
@@ -173,7 +183,7 @@ impl ParticipationCache {
173183 SingleEpochParticipationCache :: new ( num_current_epoch_active_vals, spec) ;
174184 let mut previous_epoch_participation =
175185 SingleEpochParticipationCache :: new ( num_previous_epoch_active_vals, spec) ;
176- // Contains the set of validators which are:
186+ // Contains the set of validators which are either :
177187 //
178188 // - Active in the previous epoch.
179189 // - Slashed, but not yet withdrawable.
@@ -182,35 +192,40 @@ impl ParticipationCache {
182192 // reallocations.
183193 let mut eligible_indices = Vec :: with_capacity ( state. validators ( ) . len ( ) ) ;
184194
195+ // Iterate through all validators, updating:
196+ //
197+ // 1. Validator participation for current and previous epochs.
198+ // 2. The "eligible indices".
199+ //
200+ // Care is taken to ensure that the ordering of `eligible_indices` is the same as the
201+ // `get_eligible_validator_indices` function in the spec.
185202 for ( val_index, val) in state. validators ( ) . iter ( ) . enumerate ( ) {
186203 if val. is_active_at ( current_epoch) {
187204 current_epoch_participation. process_active_validator (
188205 val_index,
189206 state,
190- state . current_epoch_participation ( ) ? ,
207+ RelativeEpoch :: Current ,
191208 ) ?;
192209 }
193210
194211 if val. is_active_at ( previous_epoch) {
195212 previous_epoch_participation. process_active_validator (
196213 val_index,
197214 state,
198- state . previous_epoch_participation ( ) ? ,
215+ RelativeEpoch :: Previous ,
199216 ) ?;
200217 }
201218
219+ // Note: a validator might still be "eligible" whilst returning `false` to
220+ // `Validator::is_active_at`.
202221 if state. is_eligible_validator ( val_index) ? {
203222 eligible_indices. push ( val_index)
204223 }
205224 }
206225
207226 eligible_indices. shrink_to_fit ( ) ;
208- current_epoch_participation
209- . unslashed_participating_indices
210- . shrink_to_fit ( ) ;
211- previous_epoch_participation
212- . unslashed_participating_indices
213- . shrink_to_fit ( ) ;
227+ current_epoch_participation. shrink_to_fit ( ) ;
228+ previous_epoch_participation. shrink_to_fit ( ) ;
214229
215230 Ok ( Self {
216231 current_epoch,
@@ -230,36 +245,23 @@ impl ParticipationCache {
230245 self . current_epoch_participation . total_active_balance . get ( )
231246 }
232247
233- fn current_epoch_flag_attesting_balance ( & self , flag_index : usize ) -> Result < u64 , ArithError > {
234- self . current_epoch_participation
235- . total_flag_balances
236- . get ( flag_index)
237- . map ( Balance :: get)
238- . ok_or ( ArithError :: Overflow )
239- }
240-
241248 pub fn current_epoch_target_attesting_balance ( & self ) -> Result < u64 , ArithError > {
242- self . current_epoch_flag_attesting_balance ( TIMELY_TARGET_FLAG_INDEX )
249+ self . current_epoch_participation
250+ . total_flag_balance ( TIMELY_TARGET_FLAG_INDEX )
243251 }
244252
245253 pub fn previous_epoch_total_active_balance ( & self ) -> u64 {
246254 self . previous_epoch_participation . total_active_balance . get ( )
247255 }
248256
249- fn previous_epoch_flag_attesting_balance ( & self , flag_index : usize ) -> Result < u64 , ArithError > {
250- self . previous_epoch_participation
251- . total_flag_balances
252- . get ( flag_index)
253- . map ( Balance :: get)
254- . ok_or ( ArithError :: Overflow )
255- }
256-
257257 pub fn previous_epoch_target_attesting_balance ( & self ) -> Result < u64 , ArithError > {
258- self . previous_epoch_flag_attesting_balance ( TIMELY_TARGET_FLAG_INDEX )
258+ self . previous_epoch_participation
259+ . total_flag_balance ( TIMELY_TARGET_FLAG_INDEX )
259260 }
260261
261262 pub fn previous_epoch_head_attesting_balance ( & self ) -> Result < u64 , ArithError > {
262- self . previous_epoch_flag_attesting_balance ( TIMELY_HEAD_FLAG_INDEX )
263+ self . previous_epoch_participation
264+ . total_flag_balance ( TIMELY_HEAD_FLAG_INDEX )
263265 }
264266
265267 /// Equivalent to the `get_unslashed_participating_indices` function in the specification.
@@ -282,13 +284,13 @@ impl ParticipationCache {
282284 } )
283285 }
284286
285- pub fn is_active_in_previous_epoch ( & self , val_index : usize ) -> bool {
287+ pub fn is_active_unslashed_in_previous_epoch ( & self , val_index : usize ) -> bool {
286288 self . previous_epoch_participation
287289 . unslashed_participating_indices
288290 . contains_key ( & val_index)
289291 }
290292
291- pub fn is_active_in_current_epoch ( & self , val_index : usize ) -> bool {
293+ pub fn is_active_unslashed_in_current_epoch ( & self , val_index : usize ) -> bool {
292294 self . current_epoch_participation
293295 . unslashed_participating_indices
294296 . contains_key ( & val_index)
0 commit comments