From d7cc47ccc3582e4f5605269067f3e5b62292ceac Mon Sep 17 00:00:00 2001 From: realbigsean Date: Sun, 12 May 2024 04:53:12 -0400 Subject: [PATCH] fix genesis from eth1 for electra --- consensus/state_processing/src/genesis.rs | 5 +- .../state_processing/src/upgrade/electra.rs | 97 +++++++++++-------- 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index c73417077a..049599ea94 100644 --- a/consensus/state_processing/src/genesis.rs +++ b/consensus/state_processing/src/genesis.rs @@ -2,9 +2,9 @@ use super::per_block_processing::{ errors::BlockProcessingError, process_operations::apply_deposit, }; use crate::common::DepositDataTree; +use crate::upgrade::electra::upgrade_state_to_electra; use crate::upgrade::{ upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_deneb, - upgrade_to_electra, }; use safe_arith::{ArithError, SafeArith}; use tree_hash::TreeHash; @@ -116,7 +116,8 @@ pub fn initialize_beacon_state_from_eth1( .electra_fork_epoch .map_or(false, |fork_epoch| fork_epoch == E::genesis_epoch()) { - upgrade_to_electra(&mut state, spec)?; + let post = upgrade_state_to_electra(&mut state, Epoch::new(0), Epoch::new(0), spec)?; + state = post; // Remove intermediate Deneb fork from `state.fork`. state.fork_mut().previous_version = spec.electra_fork_version; diff --git a/consensus/state_processing/src/upgrade/electra.rs b/consensus/state_processing/src/upgrade/electra.rs index 1e60bf488d..8d83e73828 100644 --- a/consensus/state_processing/src/upgrade/electra.rs +++ b/consensus/state_processing/src/upgrade/electra.rs @@ -1,8 +1,8 @@ use safe_arith::SafeArith; use std::mem; use types::{ - BeaconState, BeaconStateElectra, BeaconStateError as Error, ChainSpec, EpochCache, EthSpec, - Fork, + BeaconState, BeaconStateElectra, BeaconStateError as Error, ChainSpec, Epoch, EpochCache, + EthSpec, Fork, }; /// Transform a `Deneb` state into an `Electra` state. @@ -26,13 +26,66 @@ pub fn upgrade_to_electra( pre_state.build_total_active_balance_cache(spec)?; let earliest_consolidation_epoch = spec.compute_activation_exit_epoch(epoch)?; + let mut post = upgrade_state_to_electra( + pre_state, + earliest_exit_epoch, + earliest_consolidation_epoch, + spec, + )?; + + *post.exit_balance_to_consume_mut()? = post.get_activation_exit_churn_limit(spec)?; + *post.consolidation_balance_to_consume_mut()? = post.get_consolidation_churn_limit(spec)?; + + // Add validators that are not yet active to pending balance deposits + let validators = post.validators().clone(); + let mut pre_activation = validators + .iter() + .enumerate() + .filter(|(_, validator)| validator.activation_epoch == spec.far_future_epoch) + .collect::>(); + + // Sort the indices by activation_eligibility_epoch and then by index + pre_activation.sort_by(|(index_a, val_a), (index_b, val_b)| { + if val_a.activation_eligibility_epoch == val_b.activation_eligibility_epoch { + index_a.cmp(index_b) + } else { + val_a + .activation_eligibility_epoch + .cmp(&val_b.activation_eligibility_epoch) + } + }); + + // Process validators to queue entire balance and reset them + for (index, _) in pre_activation { + post.queue_entire_balance_and_reset_validator(index, spec)?; + } + + // Ensure early adopters of compounding credentials go through the activation churn + for (index, validator) in validators.iter().enumerate() { + if validator.has_compounding_withdrawal_credential(spec) { + post.queue_excess_active_balance(index, spec)?; + } + } + + *pre_state = post; + + Ok(()) +} + +pub fn upgrade_state_to_electra( + pre_state: &mut BeaconState, + earliest_exit_epoch: Epoch, + earliest_consolidation_epoch: Epoch, + spec: &ChainSpec, +) -> Result, Error> { + let epoch = pre_state.current_epoch(); let pre = pre_state.as_deneb_mut()?; // Where possible, use something like `mem::take` to move fields from behind the &mut // reference. For other fields that don't have a good default value, use `clone`. // // Fixed size vectors get cloned because replacing them would require the same size // allocation as cloning. - let mut post = BeaconState::Electra(BeaconStateElectra { + let post = BeaconState::Electra(BeaconStateElectra { // Versioning genesis_time: pre.genesis_time, genesis_validators_root: pre.genesis_validators_root, @@ -96,41 +149,5 @@ pub fn upgrade_to_electra( slashings_cache: mem::take(&mut pre.slashings_cache), epoch_cache: EpochCache::default(), }); - *post.exit_balance_to_consume_mut()? = post.get_activation_exit_churn_limit(spec)?; - *post.consolidation_balance_to_consume_mut()? = post.get_consolidation_churn_limit(spec)?; - - // Add validators that are not yet active to pending balance deposits - let validators = post.validators().clone(); - let mut pre_activation = validators - .iter() - .enumerate() - .filter(|(_, validator)| validator.activation_epoch == spec.far_future_epoch) - .collect::>(); - - // Sort the indices by activation_eligibility_epoch and then by index - pre_activation.sort_by(|(index_a, val_a), (index_b, val_b)| { - if val_a.activation_eligibility_epoch == val_b.activation_eligibility_epoch { - index_a.cmp(index_b) - } else { - val_a - .activation_eligibility_epoch - .cmp(&val_b.activation_eligibility_epoch) - } - }); - - // Process validators to queue entire balance and reset them - for (index, _) in pre_activation { - post.queue_entire_balance_and_reset_validator(index, spec)?; - } - - // Ensure early adopters of compounding credentials go through the activation churn - for (index, validator) in validators.iter().enumerate() { - if validator.has_compounding_withdrawal_credential(spec) { - post.queue_excess_active_balance(index, spec)?; - } - } - - *pre_state = post; - - Ok(()) + Ok(post) }