@@ -7,17 +7,14 @@ use ssz::four_byte_option_impl;
77use ssz_derive:: { Decode , Encode } ;
88use state_processing:: {
99 per_epoch_processing:: {
10- altair:: { self , rewards_and_penalties :: get_flag_index_deltas , ParticipationCache } ,
10+ altair,
1111 base:: { self , rewards_and_penalties:: AttestationDelta , ValidatorStatuses } ,
1212 Delta ,
1313 } ,
1414 EpochProcessingError ,
1515} ;
1616use std:: path:: { Path , PathBuf } ;
17- use types:: {
18- consts:: altair:: { TIMELY_HEAD_FLAG_INDEX , TIMELY_SOURCE_FLAG_INDEX , TIMELY_TARGET_FLAG_INDEX } ,
19- BeaconState , EthSpec , ForkName ,
20- } ;
17+ use types:: { BeaconState , EthSpec , ForkName } ;
2118
2219#[ derive( Debug , Clone , PartialEq , Decode , Encode , CompareFields ) ]
2320pub struct Deltas {
@@ -41,6 +38,11 @@ pub struct AllDeltas {
4138 inactivity_penalty_deltas : Deltas ,
4239}
4340
41+ #[ derive( Debug , Clone , PartialEq , CompareFields ) ]
42+ pub struct TotalDeltas {
43+ deltas : Vec < i64 > ,
44+ }
45+
4446#[ derive( Debug , Clone , Default , Deserialize ) ]
4547pub struct Metadata {
4648 pub description : Option < String > ,
@@ -110,11 +112,19 @@ impl<E: EthSpec> Case for RewardsTest<E> {
110112 let mut state = self . pre . clone ( ) ;
111113 let spec = & testing_spec :: < E > ( fork_name) ;
112114
113- let deltas: Result < AllDeltas , EpochProcessingError > = ( || {
114- // Processing requires the committee caches.
115- state. build_all_committee_caches ( spec) ?;
115+ // Single-pass epoch processing doesn't compute rewards in the genesis epoch because that's
116+ // what the spec for `process_rewards_and_penalties` says to do. We skip these tests for now.
117+ //
118+ // See: https://github.com/ethereum/consensus-specs/issues/3593
119+ if fork_name != ForkName :: Base && state. current_epoch ( ) == 0 {
120+ return Err ( Error :: SkippedKnownFailure ) ;
121+ }
122+
123+ if let BeaconState :: Base ( _) = state {
124+ let deltas: Result < AllDeltas , EpochProcessingError > = ( || {
125+ // Processing requires the committee caches.
126+ state. build_all_committee_caches ( spec) ?;
116127
117- if let BeaconState :: Base ( _) = state {
118128 let mut validator_statuses = ValidatorStatuses :: new ( & state, spec) ?;
119129 validator_statuses. process_attestations ( & state) ?;
120130
@@ -125,39 +135,19 @@ impl<E: EthSpec> Case for RewardsTest<E> {
125135 ) ?;
126136
127137 Ok ( convert_all_base_deltas ( & deltas) )
128- } else {
129- let total_active_balance = state. get_total_active_balance ( ) ?;
138+ } ) ( ) ;
139+ compare_result_detailed ( & deltas, & Some ( self . deltas . clone ( ) ) ) ?;
140+ } else {
141+ let deltas: Result < TotalDeltas , EpochProcessingError > = ( || {
142+ // Processing requires the committee caches.
143+ state. build_all_committee_caches ( spec) ?;
144+ compute_altair_deltas ( & mut state, spec)
145+ } ) ( ) ;
130146
131- let source_deltas = compute_altair_flag_deltas (
132- & state,
133- TIMELY_SOURCE_FLAG_INDEX ,
134- total_active_balance,
135- spec,
136- ) ?;
137- let target_deltas = compute_altair_flag_deltas (
138- & state,
139- TIMELY_TARGET_FLAG_INDEX ,
140- total_active_balance,
141- spec,
142- ) ?;
143- let head_deltas = compute_altair_flag_deltas (
144- & state,
145- TIMELY_HEAD_FLAG_INDEX ,
146- total_active_balance,
147- spec,
148- ) ?;
149- let inactivity_penalty_deltas = compute_altair_inactivity_deltas ( & state, spec) ?;
150- Ok ( AllDeltas {
151- source_deltas,
152- target_deltas,
153- head_deltas,
154- inclusion_delay_deltas : None ,
155- inactivity_penalty_deltas,
156- } )
157- }
158- } ) ( ) ;
159-
160- compare_result_detailed ( & deltas, & Some ( self . deltas . clone ( ) ) ) ?;
147+ let expected = all_deltas_to_total_deltas ( & self . deltas ) ;
148+
149+ compare_result_detailed ( & deltas, & Some ( expected) ) ?;
150+ } ;
161151
162152 Ok ( ( ) )
163153 }
@@ -182,39 +172,54 @@ fn convert_base_deltas(attestation_deltas: &[AttestationDelta], accessor: Access
182172 Deltas { rewards, penalties }
183173}
184174
185- fn compute_altair_flag_deltas < E : EthSpec > (
186- state : & BeaconState < E > ,
187- flag_index : usize ,
188- total_active_balance : u64 ,
189- spec : & ChainSpec ,
190- ) -> Result < Deltas , EpochProcessingError > {
191- let mut deltas = vec ! [ Delta :: default ( ) ; state. validators( ) . len( ) ] ;
192- get_flag_index_deltas (
193- & mut deltas,
194- state,
195- flag_index,
196- total_active_balance,
197- & ParticipationCache :: new ( state, spec) . unwrap ( ) ,
198- spec,
199- ) ?;
200- Ok ( convert_altair_deltas ( deltas) )
175+ fn deltas_to_total_deltas ( d : & Deltas ) -> impl Iterator < Item = i64 > + ' _ {
176+ d. rewards
177+ . iter ( )
178+ . zip ( & d. penalties )
179+ . map ( |( & reward, & penalty) | reward as i64 - penalty as i64 )
201180}
202181
203- fn compute_altair_inactivity_deltas < E : EthSpec > (
204- state : & BeaconState < E > ,
205- spec : & ChainSpec ,
206- ) -> Result < Deltas , EpochProcessingError > {
207- let mut deltas = vec ! [ Delta :: default ( ) ; state. validators( ) . len( ) ] ;
208- altair:: rewards_and_penalties:: get_inactivity_penalty_deltas (
209- & mut deltas,
210- state,
211- & ParticipationCache :: new ( state, spec) . unwrap ( ) ,
212- spec,
213- ) ?;
214- Ok ( convert_altair_deltas ( deltas) )
182+ fn optional_deltas_to_total_deltas ( d : & Option < Deltas > , len : usize ) -> TotalDeltas {
183+ let deltas = if let Some ( d) = d {
184+ deltas_to_total_deltas ( d) . collect ( )
185+ } else {
186+ vec ! [ 0i64 ; len]
187+ } ;
188+ TotalDeltas { deltas }
215189}
216190
217- fn convert_altair_deltas ( deltas : Vec < Delta > ) -> Deltas {
218- let ( rewards, penalties) = deltas. into_iter ( ) . map ( |d| ( d. rewards , d. penalties ) ) . unzip ( ) ;
219- Deltas { rewards, penalties }
191+ fn all_deltas_to_total_deltas ( d : & AllDeltas ) -> TotalDeltas {
192+ let len = d. source_deltas . rewards . len ( ) ;
193+ let deltas = deltas_to_total_deltas ( & d. source_deltas )
194+ . zip ( deltas_to_total_deltas ( & d. target_deltas ) )
195+ . zip ( deltas_to_total_deltas ( & d. head_deltas ) )
196+ . zip ( optional_deltas_to_total_deltas ( & d. inclusion_delay_deltas , len) . deltas )
197+ . zip ( deltas_to_total_deltas ( & d. inactivity_penalty_deltas ) )
198+ . map (
199+ |( ( ( ( source, target) , head) , inclusion_delay) , inactivity_penalty) | {
200+ source + target + head + inclusion_delay + inactivity_penalty
201+ } ,
202+ )
203+ . collect :: < Vec < i64 > > ( ) ;
204+ TotalDeltas { deltas }
205+ }
206+
207+ fn compute_altair_deltas < E : EthSpec > (
208+ state : & mut BeaconState < E > ,
209+ spec : & ChainSpec ,
210+ ) -> Result < TotalDeltas , EpochProcessingError > {
211+ // Initialise deltas to pre-state balances.
212+ let mut deltas = state
213+ . balances ( )
214+ . iter ( )
215+ . map ( |x| * x as i64 )
216+ . collect :: < Vec < _ > > ( ) ;
217+ altair:: process_rewards_and_penalties_slow ( state, spec) ?;
218+
219+ for ( delta, new_balance) in deltas. iter_mut ( ) . zip ( state. balances ( ) ) {
220+ let old_balance = * delta;
221+ * delta = * new_balance as i64 - old_balance;
222+ }
223+
224+ Ok ( TotalDeltas { deltas } )
220225}
0 commit comments