diff --git a/eth2/state_processing/src/per_epoch_processing.rs b/eth2/state_processing/src/per_epoch_processing.rs index f66ce4ea28..bcac1dc27c 100644 --- a/eth2/state_processing/src/per_epoch_processing.rs +++ b/eth2/state_processing/src/per_epoch_processing.rs @@ -48,15 +48,10 @@ pub fn per_epoch_processing( process_justification_and_finalization(state, &validator_statuses.total_balances)?; // Crosslinks. - let winning_root_for_shards = process_crosslinks(state, spec)?; + process_crosslinks(state, spec)?; // Rewards and Penalties. - process_rewards_and_penalties( - state, - &mut validator_statuses, - &winning_root_for_shards, - spec, - )?; + process_rewards_and_penalties(state, &mut validator_statuses, spec)?; // Registry Updates. process_registry_updates(state, spec)?; @@ -160,9 +155,7 @@ pub fn process_justification_and_finalization( pub fn process_crosslinks( state: &mut BeaconState, spec: &ChainSpec, -) -> Result { - let mut winning_root_for_shards: WinningRootHashSet = HashMap::new(); - +) -> Result<(), Error> { state.previous_crosslinks = state.current_crosslinks.clone(); for &relative_epoch in &[RelativeEpoch::Previous, RelativeEpoch::Current] { @@ -182,12 +175,11 @@ pub fn process_crosslinks( if 3 * winning_root.total_attesting_balance >= 2 * total_committee_balance { state.current_crosslinks[shard as usize] = winning_root.crosslink.clone(); } - winning_root_for_shards.insert(shard, winning_root); } } } - Ok(winning_root_for_shards) + Ok(()) } /// Finish up an epoch update. diff --git a/eth2/state_processing/src/per_epoch_processing/apply_rewards.rs b/eth2/state_processing/src/per_epoch_processing/apply_rewards.rs index 9bd53077a4..6de9ed872a 100644 --- a/eth2/state_processing/src/per_epoch_processing/apply_rewards.rs +++ b/eth2/state_processing/src/per_epoch_processing/apply_rewards.rs @@ -1,5 +1,5 @@ use super::validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses}; -use super::{Error, WinningRootHashSet}; +use super::Error; use integer_sqrt::IntegerSquareRoot; use types::*; @@ -36,7 +36,6 @@ impl std::ops::AddAssign for Delta { pub fn process_rewards_and_penalties( state: &mut BeaconState, validator_statuses: &mut ValidatorStatuses, - winning_root_for_shards: &WinningRootHashSet, spec: &ChainSpec, ) -> Result<(), Error> { if state.current_epoch() == T::genesis_epoch() { @@ -53,15 +52,13 @@ pub fn process_rewards_and_penalties( let mut deltas = vec![Delta::default(); state.balances.len()]; get_attestation_deltas(&mut deltas, state, &validator_statuses, spec)?; + + // Update statuses with the information from winning roots. + validator_statuses.process_winning_roots(state, spec)?; + get_crosslink_deltas(&mut deltas, state, &validator_statuses, spec)?; - get_proposer_deltas( - &mut deltas, - state, - validator_statuses, - winning_root_for_shards, - spec, - )?; + get_proposer_deltas(&mut deltas, state, validator_statuses, spec)?; // Apply the deltas, over-flowing but not under-flowing (saturating at 0 instead). for (i, delta) in deltas.iter().enumerate() { @@ -79,12 +76,8 @@ fn get_proposer_deltas( deltas: &mut Vec, state: &BeaconState, validator_statuses: &mut ValidatorStatuses, - winning_root_for_shards: &WinningRootHashSet, spec: &ChainSpec, ) -> Result<(), Error> { - // Update statuses with the information from winning roots. - validator_statuses.process_winning_roots(state, winning_root_for_shards, spec)?; - for (index, validator) in validator_statuses.statuses.iter().enumerate() { if validator.is_previous_epoch_attester { let inclusion = validator diff --git a/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs b/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs index 8a7d07d571..3280b981f2 100644 --- a/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs +++ b/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs @@ -1,4 +1,4 @@ -use super::WinningRootHashSet; +use super::{winning_root::winning_root, WinningRootHashSet}; use crate::common::get_attesting_indices; use types::*; @@ -292,9 +292,29 @@ impl ValidatorStatuses { pub fn process_winning_roots( &mut self, state: &BeaconState, - winning_roots: &WinningRootHashSet, spec: &ChainSpec, ) -> Result<(), BeaconStateError> { + // We must re-calculate the winning roots here because it is possible that they have + // changed since the first time they were calculated. + // + // This is because we altered the state during the first time we calculated the winning + // roots. + let winning_root_for_shards = { + let mut winning_root_for_shards = WinningRootHashSet::new(); + let relative_epoch = RelativeEpoch::Previous; + + let epoch = relative_epoch.into_epoch(state.current_epoch()); + for offset in 0..state.get_committee_count(relative_epoch)? { + let shard = (state.get_epoch_start_shard(relative_epoch)? + offset) + % T::ShardCount::to_u64(); + if let Some(winning_root) = winning_root(state, shard, epoch, spec)? { + winning_root_for_shards.insert(shard, winning_root); + } + } + + winning_root_for_shards + }; + // Loop through each slot in the previous epoch. for slot in state.previous_epoch().slot_iter(T::slots_per_epoch()) { let crosslink_committees_at_slot = state.get_crosslink_committees_at_slot(slot)?; @@ -302,7 +322,7 @@ impl ValidatorStatuses { // Loop through each committee in the slot. for c in crosslink_committees_at_slot { // If there was some winning crosslink root for the committee's shard. - if let Some(winning_root) = winning_roots.get(&c.shard) { + if let Some(winning_root) = winning_root_for_shards.get(&c.shard) { let total_committee_balance = state.get_total_balance(&c.committee, spec)?; for &validator_index in &winning_root.attesting_validator_indices { // Take note of the balance information for the winning root, it will be diff --git a/eth2/state_processing/src/per_epoch_processing/winning_root.rs b/eth2/state_processing/src/per_epoch_processing/winning_root.rs index 874e11d6c7..82a6b0ff1f 100644 --- a/eth2/state_processing/src/per_epoch_processing/winning_root.rs +++ b/eth2/state_processing/src/per_epoch_processing/winning_root.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use tree_hash::TreeHash; use types::*; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct WinningRoot { pub crosslink: Crosslink, pub attesting_validator_indices: Vec,