11use crate :: { BeaconChain , BeaconChainError , BeaconChainTypes } ;
22use eth2:: lighthouse:: attestation_rewards:: { IdealAttestationRewards , TotalAttestationRewards } ;
33use eth2:: lighthouse:: StandardAttestationRewards ;
4- use participation_cache :: ParticipationCache ;
4+ use eth2 :: types :: ValidatorId ;
55use safe_arith:: SafeArith ;
66use serde_utils:: quoted_u64:: Quoted ;
77use slog:: debug;
8+ use state_processing:: common:: base:: { self , SqrtTotalActiveBalance } ;
89use state_processing:: per_epoch_processing:: altair:: {
9- process_inactivity_updates, process_justification_and_finalization,
10- } ;
11- use state_processing:: {
12- common:: altair:: BaseRewardPerIncrement ,
13- per_epoch_processing:: altair:: { participation_cache, rewards_and_penalties:: get_flag_weight} ,
14- } ;
15- use std:: collections:: HashMap ;
16- use store:: consts:: altair:: {
17- PARTICIPATION_FLAG_WEIGHTS , TIMELY_HEAD_FLAG_INDEX , TIMELY_SOURCE_FLAG_INDEX ,
18- TIMELY_TARGET_FLAG_INDEX ,
10+ process_inactivity_updates_slow, process_justification_and_finalization,
1911} ;
20- use types:: consts:: altair:: WEIGHT_DENOMINATOR ;
21-
22- use types:: { BeaconState , Epoch , EthSpec } ;
23-
24- use eth2:: types:: ValidatorId ;
25- use state_processing:: common:: base:: get_base_reward_from_effective_balance;
2612use state_processing:: per_epoch_processing:: base:: rewards_and_penalties:: {
2713 get_attestation_component_delta, get_attestation_deltas_all, get_attestation_deltas_subset,
2814 get_inactivity_penalty_delta, get_inclusion_delay_delta,
@@ -32,6 +18,19 @@ use state_processing::per_epoch_processing::base::{
3218 process_justification_and_finalization as process_justification_and_finalization_base,
3319 TotalBalances , ValidatorStatus , ValidatorStatuses ,
3420} ;
21+ use state_processing:: {
22+ common:: altair:: BaseRewardPerIncrement ,
23+ common:: update_progressive_balances_cache:: initialize_progressive_balances_cache,
24+ epoch_cache:: initialize_epoch_cache,
25+ per_epoch_processing:: altair:: rewards_and_penalties:: get_flag_weight,
26+ } ;
27+ use std:: collections:: HashMap ;
28+ use store:: consts:: altair:: {
29+ PARTICIPATION_FLAG_WEIGHTS , TIMELY_HEAD_FLAG_INDEX , TIMELY_SOURCE_FLAG_INDEX ,
30+ TIMELY_TARGET_FLAG_INDEX ,
31+ } ;
32+ use types:: consts:: altair:: WEIGHT_DENOMINATOR ;
33+ use types:: { BeaconState , Epoch , EthSpec , RelativeEpoch } ;
3534
3635impl < T : BeaconChainTypes > BeaconChain < T > {
3736 pub fn compute_attestation_rewards (
@@ -134,11 +133,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
134133 ) -> Result < StandardAttestationRewards , BeaconChainError > {
135134 let spec = & self . spec ;
136135
136+ // Build required caches.
137+ initialize_epoch_cache ( & mut state, spec) ?;
138+ initialize_progressive_balances_cache ( & mut state, spec) ?;
139+ state. build_exit_cache ( spec) ?;
140+ state. build_committee_cache ( RelativeEpoch :: Previous , spec) ?;
141+ state. build_committee_cache ( RelativeEpoch :: Current , spec) ?;
142+
137143 // Calculate ideal_rewards
138- let participation_cache = ParticipationCache :: new ( & state, spec) ?;
139- process_justification_and_finalization ( & state, & participation_cache) ?
140- . apply_changes_to_state ( & mut state) ;
141- process_inactivity_updates ( & mut state, & participation_cache, spec) ?;
144+ process_justification_and_finalization ( & state) ?. apply_changes_to_state ( & mut state) ;
145+ process_inactivity_updates_slow ( & mut state, spec) ?;
142146
143147 let previous_epoch = state. previous_epoch ( ) ;
144148
@@ -148,18 +152,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
148152 let weight = get_flag_weight ( flag_index)
149153 . map_err ( |_| BeaconChainError :: AttestationRewardsError ) ?;
150154
151- let unslashed_participating_indices = participation_cache
152- . get_unslashed_participating_indices ( flag_index, previous_epoch) ?;
153-
154- let unslashed_participating_balance =
155- unslashed_participating_indices
156- . total_balance ( )
157- . map_err ( |_| BeaconChainError :: AttestationRewardsError ) ?;
155+ let unslashed_participating_balance = state
156+ . progressive_balances_cache ( )
157+ . previous_epoch_flag_attesting_balance ( flag_index) ?;
158158
159159 let unslashed_participating_increments =
160160 unslashed_participating_balance. safe_div ( spec. effective_balance_increment ) ?;
161161
162- let total_active_balance = participation_cache . current_epoch_total_active_balance ( ) ;
162+ let total_active_balance = state . get_total_active_balance ( ) ? ;
163163
164164 let active_increments =
165165 total_active_balance. safe_div ( spec. effective_balance_increment ) ?;
@@ -195,30 +195,49 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
195195 let mut total_rewards: Vec < TotalAttestationRewards > = Vec :: new ( ) ;
196196
197197 let validators = if validators. is_empty ( ) {
198- participation_cache . eligible_validator_indices ( ) . to_vec ( )
198+ Self :: all_eligible_validator_indices ( & state , previous_epoch ) ?
199199 } else {
200200 Self :: validators_ids_to_indices ( & mut state, validators) ?
201201 } ;
202202
203- for validator_index in & validators {
204- let eligible = state. is_eligible_validator ( previous_epoch, * validator_index) ?;
203+ for & validator_index in & validators {
204+ // Return 0s for unknown/inactive validator indices.
205+ let Ok ( validator) = state. get_validator ( validator_index) else {
206+ debug ! (
207+ self . log,
208+ "No rewards for inactive/unknown validator" ;
209+ "index" => validator_index,
210+ "epoch" => previous_epoch
211+ ) ;
212+ total_rewards. push ( TotalAttestationRewards {
213+ validator_index : validator_index as u64 ,
214+ head : 0 ,
215+ target : 0 ,
216+ source : 0 ,
217+ inclusion_delay : None ,
218+ inactivity : 0 ,
219+ } ) ;
220+ continue ;
221+ } ;
222+ let previous_epoch_participation_flags = state
223+ . previous_epoch_participation ( ) ?
224+ . get ( validator_index)
225+ . ok_or ( BeaconChainError :: AttestationRewardsError ) ?;
226+ let eligible = state. is_eligible_validator ( previous_epoch, validator) ?;
205227 let mut head_reward = 0i64 ;
206228 let mut target_reward = 0i64 ;
207229 let mut source_reward = 0i64 ;
208230 let mut inactivity_penalty = 0i64 ;
209231
210232 if eligible {
211- let effective_balance = state . get_effective_balance ( * validator_index ) ? ;
233+ let effective_balance = validator . effective_balance ;
212234
213235 for flag_index in 0 ..PARTICIPATION_FLAG_WEIGHTS . len ( ) {
214236 let ( ideal_reward, penalty) = ideal_rewards_hashmap
215237 . get ( & ( flag_index, effective_balance) )
216238 . ok_or ( BeaconChainError :: AttestationRewardsError ) ?;
217- let voted_correctly = participation_cache
218- . get_unslashed_participating_indices ( flag_index, previous_epoch)
219- . map_err ( |_| BeaconChainError :: AttestationRewardsError ) ?
220- . contains ( * validator_index)
221- . map_err ( |_| BeaconChainError :: AttestationRewardsError ) ?;
239+ let voted_correctly = !validator. slashed
240+ && previous_epoch_participation_flags. has_flag ( flag_index) ?;
222241 if voted_correctly {
223242 if flag_index == TIMELY_HEAD_FLAG_INDEX {
224243 head_reward += * ideal_reward as i64 ;
@@ -233,10 +252,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
233252 target_reward = * penalty;
234253
235254 let penalty_numerator = effective_balance
236- . safe_mul ( state. get_inactivity_score ( * validator_index) ?) ?;
237- let penalty_denominator = spec
238- . inactivity_score_bias
239- . safe_mul ( spec . inactivity_penalty_quotient_for_state ( & state ) ) ?;
255+ . safe_mul ( state. get_inactivity_score ( validator_index) ?) ?;
256+ let penalty_denominator = spec. inactivity_score_bias . safe_mul (
257+ spec . inactivity_penalty_quotient_for_fork ( state . fork_name_unchecked ( ) ) ,
258+ ) ?;
240259 inactivity_penalty =
241260 -( penalty_numerator. safe_div ( penalty_denominator) ? as i64 ) ;
242261 } else if flag_index == TIMELY_SOURCE_FLAG_INDEX {
@@ -245,7 +264,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
245264 }
246265 }
247266 total_rewards. push ( TotalAttestationRewards {
248- validator_index : * validator_index as u64 ,
267+ validator_index : validator_index as u64 ,
249268 head : head_reward,
250269 target : target_reward,
251270 source : source_reward,
@@ -302,6 +321,24 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
302321 Ok ( max_steps)
303322 }
304323
324+ fn all_eligible_validator_indices (
325+ state : & BeaconState < T :: EthSpec > ,
326+ previous_epoch : Epoch ,
327+ ) -> Result < Vec < usize > , BeaconChainError > {
328+ state
329+ . validators ( )
330+ . iter ( )
331+ . enumerate ( )
332+ . filter_map ( |( i, validator) | {
333+ state
334+ . is_eligible_validator ( previous_epoch, validator)
335+ . map ( |eligible| eligible. then_some ( i) )
336+ . map_err ( BeaconChainError :: BeaconStateError )
337+ . transpose ( )
338+ } )
339+ . collect ( )
340+ }
341+
305342 fn validators_ids_to_indices (
306343 state : & mut BeaconState < T :: EthSpec > ,
307344 validators : Vec < ValidatorId > ,
@@ -340,15 +377,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
340377 } ;
341378
342379 let mut ideal_attestation_rewards_list = Vec :: new ( ) ;
343-
380+ let sqrt_total_active_balance = SqrtTotalActiveBalance :: new ( total_balances . current_epoch ( ) ) ;
344381 for effective_balance_step in 1 ..=self . max_effective_balance_increment_steps ( ) ? {
345382 let effective_balance =
346383 effective_balance_step. safe_mul ( spec. effective_balance_increment ) ?;
347- let base_reward = get_base_reward_from_effective_balance :: < T :: EthSpec > (
348- effective_balance,
349- total_balances. current_epoch ( ) ,
350- spec,
351- ) ?;
384+ let base_reward =
385+ base:: get_base_reward ( effective_balance, sqrt_total_active_balance, spec) ?;
352386
353387 // compute ideal head rewards
354388 let head = get_attestation_component_delta (
0 commit comments