From 238ac98d7c229f330a182823984a8e2e1acda080 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Thu, 25 Nov 2021 17:32:18 +1100 Subject: [PATCH] Update state_processing --- consensus/state_processing/Cargo.toml | 1 + .../src/common/initiate_validator_exit.rs | 9 ++++-- .../src/common/slash_validator.rs | 5 ++- consensus/state_processing/src/genesis.rs | 5 +-- .../src/per_block_processing/errors.rs | 9 ++++++ .../per_block_processing/signature_sets.rs | 3 ++ .../altair/participation_cache.rs | 3 ++ .../altair/participation_flag_updates.rs | 3 ++ .../altair/rewards_and_penalties.rs | 3 ++ .../base/rewards_and_penalties.rs | 3 ++ .../base/validator_statuses.rs | 3 ++ .../effective_balance_updates.rs | 7 ++-- .../per_epoch_processing/registry_updates.rs | 9 ++++-- .../src/per_epoch_processing/slashings.rs | 5 +-- .../state_processing/src/upgrade/altair.rs | 4 +++ consensus/types/src/beacon_state.rs | 32 +++++++++++++++---- consensus/types/src/lib.rs | 5 +++ consensus/types/src/mixin.rs | 18 +++++++++++ 18 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 consensus/types/src/mixin.rs diff --git a/consensus/state_processing/Cargo.toml b/consensus/state_processing/Cargo.toml index 216a497685..755de44fac 100644 --- a/consensus/state_processing/Cargo.toml +++ b/consensus/state_processing/Cargo.toml @@ -31,6 +31,7 @@ default = ["legacy-arith", "metrics"] fake_crypto = ["bls/fake_crypto"] legacy-arith = ["types/legacy-arith"] metrics = ["lighthouse_metrics", "lazy_static"] +milhouse = ["types/milhouse"] arbitrary-fuzz = [ "arbitrary", "types/arbitrary-fuzz", diff --git a/consensus/state_processing/src/common/initiate_validator_exit.rs b/consensus/state_processing/src/common/initiate_validator_exit.rs index 85e5e1df1d..fbf4d037ab 100644 --- a/consensus/state_processing/src/common/initiate_validator_exit.rs +++ b/consensus/state_processing/src/common/initiate_validator_exit.rs @@ -31,9 +31,14 @@ pub fn initiate_validator_exit( state .exit_cache_mut() .record_validator_exit(exit_queue_epoch)?; - state.get_validator_mut(index)?.exit_epoch = exit_queue_epoch; - state.get_validator_mut(index)?.withdrawable_epoch = + + let mut validators = state.validators_mut(); + let validator = validators.get_validator_mut(index)?; + + validator.exit_epoch = exit_queue_epoch; + validator.withdrawable_epoch = exit_queue_epoch.safe_add(spec.min_validator_withdrawability_delay)?; + drop(validators); Ok(()) } diff --git a/consensus/state_processing/src/common/slash_validator.rs b/consensus/state_processing/src/common/slash_validator.rs index 7643043bab..4867706730 100644 --- a/consensus/state_processing/src/common/slash_validator.rs +++ b/consensus/state_processing/src/common/slash_validator.rs @@ -17,13 +17,16 @@ pub fn slash_validator( initiate_validator_exit(state, slashed_index, spec)?; - let validator = state.get_validator_mut(slashed_index)?; + let mut validators = state.validators_mut(); + let validator = validators.get_validator_mut(slashed_index)?; validator.slashed = true; validator.withdrawable_epoch = cmp::max( validator.withdrawable_epoch, epoch.safe_add(T::EpochsPerSlashingsVector::to_u64())?, ); let validator_effective_balance = validator.effective_balance; + drop(validators); + state.set_slashings( epoch, state diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index 7834c6daf3..0b72bd5bb2 100644 --- a/consensus/state_processing/src/genesis.rs +++ b/consensus/state_processing/src/genesis.rs @@ -76,8 +76,9 @@ pub fn process_activations( state: &mut BeaconState, spec: &ChainSpec, ) -> Result<(), Error> { - let (validators, balances) = state.validators_and_balances_mut(); - for (index, validator) in validators.iter_mut().enumerate() { + let (mut validators, balances) = state.validators_and_balances_mut(); + for index in 0..validators.len() { + let validator = validators.get_validator_mut(index)?; let balance = balances .get(index) .copied() diff --git a/consensus/state_processing/src/per_block_processing/errors.rs b/consensus/state_processing/src/per_block_processing/errors.rs index 2ba9ea78c1..c4bdaf3c7b 100644 --- a/consensus/state_processing/src/per_block_processing/errors.rs +++ b/consensus/state_processing/src/per_block_processing/errors.rs @@ -57,6 +57,8 @@ pub enum BlockProcessingError { ArithError(ArithError), InconsistentBlockFork(InconsistentFork), InconsistentStateFork(InconsistentFork), + #[cfg(feature = "milhouse")] + MilhouseError(milhouse::Error), } impl From for BlockProcessingError { @@ -89,6 +91,13 @@ impl From for BlockProcessingError { } } +#[cfg(feature = "milhouse")] +impl From for BlockProcessingError { + fn from(e: milhouse::Error) -> Self { + Self::MilhouseError(e) + } +} + impl From> for BlockProcessingError { fn from(e: BlockOperationError) -> BlockProcessingError { match e { diff --git a/consensus/state_processing/src/per_block_processing/signature_sets.rs b/consensus/state_processing/src/per_block_processing/signature_sets.rs index a3b8dcaf21..d2e9286b49 100644 --- a/consensus/state_processing/src/per_block_processing/signature_sets.rs +++ b/consensus/state_processing/src/per_block_processing/signature_sets.rs @@ -14,6 +14,9 @@ use types::{ SignedVoluntaryExit, SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned, }; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + pub type Result = std::result::Result; #[derive(Debug, PartialEq, Clone)] diff --git a/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs b/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs index 503dadfc70..46d0d928e8 100644 --- a/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs +++ b/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs @@ -21,6 +21,9 @@ use types::{ BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, ParticipationFlags, RelativeEpoch, }; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + #[derive(Debug, PartialEq)] pub enum Error { InvalidFlagIndex(usize), diff --git a/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs b/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs index 7162fa7f4a..db1c030a18 100644 --- a/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs +++ b/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs @@ -6,6 +6,9 @@ use types::eth_spec::EthSpec; use types::participation_flags::ParticipationFlags; use types::VariableList; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + pub fn process_participation_flag_updates( state: &mut BeaconState, ) -> Result<(), EpochProcessingError> { diff --git a/consensus/state_processing/src/per_epoch_processing/altair/rewards_and_penalties.rs b/consensus/state_processing/src/per_epoch_processing/altair/rewards_and_penalties.rs index 5906e0f8d2..7f8fd63341 100644 --- a/consensus/state_processing/src/per_epoch_processing/altair/rewards_and_penalties.rs +++ b/consensus/state_processing/src/per_epoch_processing/altair/rewards_and_penalties.rs @@ -6,6 +6,9 @@ use types::consts::altair::{ }; use types::{BeaconState, ChainSpec, EthSpec}; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + use crate::common::{altair::get_base_reward, decrease_balance, increase_balance}; use crate::per_epoch_processing::{Delta, Error}; diff --git a/consensus/state_processing/src/per_epoch_processing/base/rewards_and_penalties.rs b/consensus/state_processing/src/per_epoch_processing/base/rewards_and_penalties.rs index 2c1ef6178e..1c2db2cbbb 100644 --- a/consensus/state_processing/src/per_epoch_processing/base/rewards_and_penalties.rs +++ b/consensus/state_processing/src/per_epoch_processing/base/rewards_and_penalties.rs @@ -7,6 +7,9 @@ use safe_arith::SafeArith; use std::array::IntoIter as ArrayIter; use types::{BeaconState, ChainSpec, EthSpec}; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + /// Combination of several deltas for different components of an attestation reward. /// /// Exists only for compatibility with EF rewards tests. diff --git a/consensus/state_processing/src/per_epoch_processing/base/validator_statuses.rs b/consensus/state_processing/src/per_epoch_processing/base/validator_statuses.rs index b40f91ce5a..bd7bd73256 100644 --- a/consensus/state_processing/src/per_epoch_processing/base/validator_statuses.rs +++ b/consensus/state_processing/src/per_epoch_processing/base/validator_statuses.rs @@ -2,6 +2,9 @@ use crate::common::get_attesting_indices; use safe_arith::SafeArith; use types::{BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, PendingAttestation}; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + #[cfg(feature = "arbitrary-fuzz")] use arbitrary::Arbitrary; diff --git a/consensus/state_processing/src/per_epoch_processing/effective_balance_updates.rs b/consensus/state_processing/src/per_epoch_processing/effective_balance_updates.rs index c166667b5a..5378bf47fb 100644 --- a/consensus/state_processing/src/per_epoch_processing/effective_balance_updates.rs +++ b/consensus/state_processing/src/per_epoch_processing/effective_balance_updates.rs @@ -2,7 +2,7 @@ use super::errors::EpochProcessingError; use safe_arith::SafeArith; use types::beacon_state::BeaconState; use types::chain_spec::ChainSpec; -use types::{BeaconStateError, EthSpec}; +use types::{BeaconStateError, EthSpec, GetValidatorMut}; pub fn process_effective_balance_updates( state: &mut BeaconState, @@ -13,8 +13,9 @@ pub fn process_effective_balance_updates( .safe_div(spec.hysteresis_quotient)?; let downward_threshold = hysteresis_increment.safe_mul(spec.hysteresis_downward_multiplier)?; let upward_threshold = hysteresis_increment.safe_mul(spec.hysteresis_upward_multiplier)?; - let (validators, balances) = state.validators_and_balances_mut(); - for (index, validator) in validators.iter_mut().enumerate() { + let (mut validators, balances) = state.validators_and_balances_mut(); + for index in 0..validators.len() { + let validator = validators.get_validator_mut(index)?; let balance = balances .get(index) .copied() diff --git a/consensus/state_processing/src/per_epoch_processing/registry_updates.rs b/consensus/state_processing/src/per_epoch_processing/registry_updates.rs index 4fd2d68586..93daa7def2 100644 --- a/consensus/state_processing/src/per_epoch_processing/registry_updates.rs +++ b/consensus/state_processing/src/per_epoch_processing/registry_updates.rs @@ -1,7 +1,7 @@ use crate::{common::initiate_validator_exit, per_epoch_processing::Error}; use itertools::Itertools; use safe_arith::SafeArith; -use types::{BeaconState, ChainSpec, EthSpec, Validator}; +use types::{BeaconState, ChainSpec, EthSpec, GetValidatorMut, Validator}; /// Performs a validator registry update, if required. /// @@ -30,11 +30,13 @@ pub fn process_registry_updates( .collect(); for index in indices_to_update { - let validator = state.get_validator_mut(index)?; + let mut validators = state.validators_mut(); + let validator = validators.get_validator_mut(index)?; if validator.is_eligible_for_activation_queue(spec) { validator.activation_eligibility_epoch = current_epoch.safe_add(1)?; } if is_ejectable(validator) { + drop(validators); initiate_validator_exit(state, index, spec)?; } } @@ -52,8 +54,9 @@ pub fn process_registry_updates( // Dequeue validators for activation up to churn limit let churn_limit = state.get_churn_limit(spec)? as usize; let delayed_activation_epoch = state.compute_activation_exit_epoch(current_epoch, spec)?; + let mut validators = state.validators_mut(); for index in activation_queue.into_iter().take(churn_limit) { - state.get_validator_mut(index)?.activation_epoch = delayed_activation_epoch; + validators.get_validator_mut(index)?.activation_epoch = delayed_activation_epoch; } Ok(()) diff --git a/consensus/state_processing/src/per_epoch_processing/slashings.rs b/consensus/state_processing/src/per_epoch_processing/slashings.rs index ed77018e2d..2721abbe7b 100644 --- a/consensus/state_processing/src/per_epoch_processing/slashings.rs +++ b/consensus/state_processing/src/per_epoch_processing/slashings.rs @@ -1,6 +1,6 @@ use crate::per_epoch_processing::Error; use safe_arith::{SafeArith, SafeArithIter}; -use types::{BeaconState, BeaconStateError, ChainSpec, EthSpec, Unsigned}; +use types::{BeaconState, BeaconStateError, ChainSpec, EthSpec, GetValidatorMut, Unsigned}; /// Process slashings. pub fn process_slashings( @@ -16,7 +16,8 @@ pub fn process_slashings( std::cmp::min(sum_slashings.safe_mul(slashing_multiplier)?, total_balance); let (validators, balances) = state.validators_and_balances_mut(); - for (index, validator) in validators.iter().enumerate() { + for index in 0..validators.len() { + let validator = validators.get_validator(index)?; if validator.slashed && epoch.safe_add(T::EpochsPerSlashingsVector::to_u64().safe_div(2)?)? == validator.withdrawable_epoch diff --git a/consensus/state_processing/src/upgrade/altair.rs b/consensus/state_processing/src/upgrade/altair.rs index 5e4fcbcf55..91ff41bf14 100644 --- a/consensus/state_processing/src/upgrade/altair.rs +++ b/consensus/state_processing/src/upgrade/altair.rs @@ -6,6 +6,9 @@ use types::{ ParticipationFlags, PendingAttestation, RelativeEpoch, SyncCommittee, VariableList, }; +#[cfg(feature = "milhouse")] +use types::milhouse::prelude::*; + /// Translate the participation information from the epoch prior to the fork into Altair's format. pub fn translate_participation( state: &mut BeaconState, @@ -104,6 +107,7 @@ pub fn upgrade_to_altair( committee_caches: mem::take(&mut pre.committee_caches), pubkey_cache: mem::take(&mut pre.pubkey_cache), exit_cache: mem::take(&mut pre.exit_cache), + #[cfg(not(feature = "milhouse"))] tree_hash_cache: mem::take(&mut pre.tree_hash_cache), }); diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index b8c7d9ac22..98cd4348ec 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -47,7 +47,11 @@ mod tree_hash_cache; #[cfg(feature = "milhouse")] pub type ListMut<'a, T, N> = Interface>; + +#[cfg(feature = "milhouse")] pub type ValidatorsMut<'a, N> = ListMut<'a, Validator, N>; +#[cfg(not(feature = "milhouse"))] +pub type ValidatorsMut<'a, N> = &'a mut VList; pub const CACHED_EPOCHS: usize = 3; const MAX_RANDOM_BYTE: u64 = (1 << 8) - 1; @@ -240,6 +244,7 @@ where pub eth1_deposit_index: u64, // Registry + #[superstruct(getter(rename = "validators_raw"))] #[test_random(default)] pub validators: VList, #[compare_fields(as_slice)] @@ -1096,19 +1101,32 @@ impl BeaconState { Ok(()) } + pub fn validators(&self) -> &VList { + self.validators_raw() + } + + pub fn validators_mut(&mut self) -> ValidatorsMut { + #[cfg(not(feature = "milhouse"))] + { + self.validators_raw_mut() + } + #[cfg(feature = "milhouse")] + { + self.validators_raw_mut().as_mut() + } + } + /// Convenience accessor for validators and balances simultaneously. - #[cfg(not(feature = "milhouse"))] - pub fn validators_and_balances_mut(&mut self) -> (&mut [Validator], &mut [u64]) { + pub fn validators_and_balances_mut( + &mut self, + ) -> (ValidatorsMut, &mut [u64]) { + #[cfg(not(feature = "milhouse"))] match self { BeaconState::Base(state) => (&mut state.validators, &mut state.balances), BeaconState::Altair(state) => (&mut state.validators, &mut state.balances), } - } - #[cfg(feature = "milhouse")] - pub fn validators_and_balances_mut( - &mut self, - ) -> (ValidatorsMut, &mut [u64]) { + #[cfg(feature = "milhouse")] match self { BeaconState::Base(state) => (state.validators.as_mut(), &mut state.balances), BeaconState::Altair(state) => (state.validators.as_mut(), &mut state.balances), diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 4e78ffd7bb..044791b116 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -64,6 +64,7 @@ pub mod voluntary_exit; pub mod slot_epoch_macros; pub mod config_and_preset; pub mod fork_context; +pub mod mixin; pub mod participation_flags; pub mod participation_list; pub mod preset; @@ -117,6 +118,7 @@ pub use crate::free_attestation::FreeAttestation; pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN}; pub use crate::historical_batch::HistoricalBatch; pub use crate::indexed_attestation::IndexedAttestation; +pub use crate::mixin::GetValidatorMut; pub use crate::participation_flags::ParticipationFlags; pub use crate::participation_list::ParticipationList; pub use crate::pending_attestation::PendingAttestation; @@ -159,3 +161,6 @@ pub use bls::{ }; pub use ssz_types::{typenum, typenum::Unsigned, BitList, BitVector, FixedVector, VariableList}; pub use superstruct::superstruct; + +#[cfg(feature = "milhouse")] +pub use milhouse::{self, prelude::*}; diff --git a/consensus/types/src/mixin.rs b/consensus/types/src/mixin.rs new file mode 100644 index 0000000000..2735cf35cb --- /dev/null +++ b/consensus/types/src/mixin.rs @@ -0,0 +1,18 @@ +use crate::beacon_state::{Error, ValidatorsMut}; +use crate::{Unsigned, Validator}; + +pub trait GetValidatorMut { + fn get_validator(&self, index: usize) -> Result<&Validator, Error>; + + fn get_validator_mut(&mut self, index: usize) -> Result<&mut Validator, Error>; +} + +impl<'a, N: Unsigned> GetValidatorMut for ValidatorsMut<'a, N> { + fn get_validator(&self, index: usize) -> Result<&Validator, Error> { + self.get(index).ok_or(Error::UnknownValidator(index)) + } + + fn get_validator_mut(&mut self, index: usize) -> Result<&mut Validator, Error> { + self.get_mut(index).ok_or(Error::UnknownValidator(index)) + } +}