diff --git a/eth2/state_processing/src/per_epoch_processing.rs b/eth2/state_processing/src/per_epoch_processing.rs index b917510f2..fcdc668f4 100644 --- a/eth2/state_processing/src/per_epoch_processing.rs +++ b/eth2/state_processing/src/per_epoch_processing.rs @@ -32,7 +32,7 @@ pub type WinningRootHashSet = HashMap; /// Mutates the given `BeaconState`, returning early if an error is encountered. If an error is /// returned, a state might be "half-processed" and therefore in an invalid state. /// -/// Spec v0.4.0 +/// Spec v0.5.0 pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> { // Ensure the previous and next epoch caches are built. state.build_epoch_cache(RelativeEpoch::Previous, spec)?; @@ -41,27 +41,38 @@ pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result // Load the struct we use to assign validators into sets based on their participation. // // E.g., attestation in the previous epoch, attested to the head, etc. - let mut statuses = ValidatorStatuses::new(state, spec)?; - statuses.process_attestations(&state, spec)?; + let mut validator_statuses = ValidatorStatuses::new(state, spec)?; + validator_statuses.process_attestations(&state, spec)?; - process_eth1_data(state, spec); - - update_justification_and_finalization(state, &statuses.total_balances, spec)?; + // Justification. + update_justification_and_finalization(state, &validator_statuses.total_balances, spec)?; // Crosslinks. let winning_root_for_shards = process_crosslinks(state, spec)?; + // Eth1 data. + maybe_reset_eth1_period(state, spec); + // Rewards and Penalities. - apply_rewards(state, &mut statuses, &winning_root_for_shards, spec)?; + apply_rewards( + state, + &mut validator_statuses, + &winning_root_for_shards, + spec, + )?; // Ejections. process_ejections(state, spec)?; // Validator Registry. - update_registry_and_shuffling_data(state, statuses.total_balances.current_epoch, spec)?; + update_registry_and_shuffling_data( + state, + validator_statuses.total_balances.current_epoch, + spec, + )?; // Slashings and exit queue. - process_slashings(state, spec)?; + process_slashings(state, validator_statuses.total_balances.current_epoch, spec)?; process_exit_queue(state, spec); // Final updates. @@ -76,7 +87,7 @@ pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result /// Maybe resets the eth1 period. /// /// Spec v0.5.0 -pub fn process_eth1_data(state: &mut BeaconState, spec: &ChainSpec) { +pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) { let next_epoch = state.next_epoch(spec); let voting_period = spec.epochs_per_eth1_voting_period; diff --git a/eth2/state_processing/src/per_epoch_processing/process_exit_queue.rs b/eth2/state_processing/src/per_epoch_processing/process_exit_queue.rs index f672c97be..074db1d08 100644 --- a/eth2/state_processing/src/per_epoch_processing/process_exit_queue.rs +++ b/eth2/state_processing/src/per_epoch_processing/process_exit_queue.rs @@ -21,8 +21,8 @@ pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) { .collect(); eligable_indices.sort_by_key(|i| state.validator_registry[*i].exit_epoch); - for (withdrawn_so_far, index) in eligable_indices.iter().enumerate() { - if withdrawn_so_far as u64 >= spec.max_exit_dequeues_per_epoch { + for (dequeues, index) in eligable_indices.iter().enumerate() { + if dequeues as u64 >= spec.max_exit_dequeues_per_epoch { break; } prepare_validator_for_withdrawal(state, *index, spec); diff --git a/eth2/state_processing/src/per_epoch_processing/process_slashings.rs b/eth2/state_processing/src/per_epoch_processing/process_slashings.rs index 19c1e519b..88777472c 100644 --- a/eth2/state_processing/src/per_epoch_processing/process_slashings.rs +++ b/eth2/state_processing/src/per_epoch_processing/process_slashings.rs @@ -2,34 +2,32 @@ use types::{BeaconStateError as Error, *}; /// Process slashings. /// -/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized. -/// -/// Spec v0.4.0 -pub fn process_slashings(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> { +/// Spec v0.5.0 +pub fn process_slashings( + state: &mut BeaconState, + current_total_balance: u64, + spec: &ChainSpec, +) -> Result<(), Error> { let current_epoch = state.current_epoch(spec); - let active_validator_indices = - state.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?; - let total_balance = state.get_total_balance(&active_validator_indices[..], spec)?; + + let total_at_start = state.get_slashed_balance(current_epoch + 1, spec)?; + let total_at_end = state.get_slashed_balance(current_epoch, spec)?; + let total_penalities = total_at_end - total_at_start; for (index, validator) in state.validator_registry.iter().enumerate() { - if validator.slashed - && (current_epoch - == validator.withdrawable_epoch - Epoch::from(spec.latest_slashed_exit_length / 2)) - { - // TODO: check the following two lines are correct. - let total_at_start = state.get_slashed_balance(current_epoch + 1, spec)?; - let total_at_end = state.get_slashed_balance(current_epoch, spec)?; - - let total_penalities = total_at_end.saturating_sub(total_at_start); + let should_penalize = current_epoch.as_usize() + == validator.withdrawable_epoch.as_usize() - spec.latest_slashed_exit_length / 2; + if validator.slashed && should_penalize { let effective_balance = state.get_effective_balance(index, spec)?; + let penalty = std::cmp::max( - effective_balance * std::cmp::min(total_penalities * 3, total_balance) - / total_balance, + effective_balance * std::cmp::min(total_penalities * 3, current_total_balance) + / current_total_balance, effective_balance / spec.min_penalty_quotient, ); - safe_sub_assign!(state.validator_balances[index], penalty); + state.validator_balances[index] -= penalty; } }