diff --git a/beacon_node/beacon_chain/src/eth1_chain.rs b/beacon_node/beacon_chain/src/eth1_chain.rs index 62aad558eeb..b4005f22fd1 100644 --- a/beacon_node/beacon_chain/src/eth1_chain.rs +++ b/beacon_node/beacon_chain/src/eth1_chain.rs @@ -548,8 +548,8 @@ impl Eth1ChainBackend for CachingEth1Backend { // [New in Electra:EIP6110] let deposit_index_limit = - if let Ok(deposit_receipts_start_index) = state.deposit_requests_start_index() { - std::cmp::min(deposit_count, deposit_receipts_start_index) + if let Ok(deposit_requests_start_index) = state.deposit_requests_start_index() { + std::cmp::min(deposit_count, deposit_requests_start_index) } else { deposit_count }; diff --git a/consensus/state_processing/src/common/initiate_validator_exit.rs b/consensus/state_processing/src/common/initiate_validator_exit.rs index 49e3a7390d4..d2d4374ab24 100644 --- a/consensus/state_processing/src/common/initiate_validator_exit.rs +++ b/consensus/state_processing/src/common/initiate_validator_exit.rs @@ -20,7 +20,7 @@ pub fn initiate_validator_exit( // Compute exit queue epoch let exit_queue_epoch = if state.fork_name_unchecked() >= ForkName::Electra { - let effective_balance = state.get_validator(index)?.effective_balance; + let effective_balance = state.get_effective_balance(index)?; state.compute_exit_epoch_and_update_churn(effective_balance, spec)? } else { let delayed_epoch = state.compute_activation_exit_epoch(state.current_epoch(), spec)?; diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index c73417077ae..049599ea945 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/per_epoch_processing/single_pass.rs b/consensus/state_processing/src/per_epoch_processing/single_pass.rs index a1fe9efbef6..514cf639360 100644 --- a/consensus/state_processing/src/per_epoch_processing/single_pass.rs +++ b/consensus/state_processing/src/per_epoch_processing/single_pass.rs @@ -359,6 +359,7 @@ pub fn process_epoch_single_pass( state, &mut next_epoch_cache, effective_balances_ctxt, + conf.effective_balance_updates, state_ctxt, spec, )?; @@ -859,6 +860,7 @@ fn process_pending_consolidations( state: &mut BeaconState, next_epoch_cache: &mut PreEpochCache, effective_balances_ctxt: &EffectiveBalancesContext, + perform_effective_balance_updates: bool, state_ctxt: &StateContext, spec: &ChainSpec, ) -> Result<(), Error> { @@ -910,6 +912,11 @@ fn process_pending_consolidations( )?; *state.pending_consolidations_mut()? = new_pending_consolidations; + // the spec tests require we don't perform effective balance updates when testing pending_consolidations + if !perform_effective_balance_updates { + return Ok(()); + } + // Re-process effective balance updates for validators affected by consolidations. let (validators, balances, _, current_epoch_participation, _, progressive_balances, _, _) = state.mutable_validator_fields()?; diff --git a/consensus/state_processing/src/upgrade/electra.rs b/consensus/state_processing/src/upgrade/electra.rs index 03cd96aebc5..1e532d9f107 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) } diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index 456aa98fad7..054e5dbe271 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -380,6 +380,7 @@ where pub eth1_deposit_index: u64, // Registry + #[compare_fields(as_iter)] #[test_random(default)] pub validators: List, #[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")] @@ -405,8 +406,10 @@ where pub current_epoch_attestations: List, E::MaxPendingAttestations>, // Participation (Altair and later) + #[compare_fields(as_iter)] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[test_random(default)] + #[compare_fields(as_iter)] pub previous_epoch_participation: List, #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[test_random(default)] @@ -483,7 +486,11 @@ where // Electra #[superstruct(only(Electra), partial_getter(copy))] #[metastruct(exclude_from(tree_lists))] - #[serde(with = "serde_utils::quoted_u64")] + #[serde( + with = "serde_utils::quoted_u64", + //TODO(electra) remove alias when ef tests are updated + alias = "deposit_receipts_start_index" + )] pub deposit_requests_start_index: u64, #[superstruct(only(Electra), partial_getter(copy))] #[metastruct(exclude_from(tree_lists))] @@ -503,13 +510,16 @@ where #[superstruct(only(Electra), partial_getter(copy))] #[metastruct(exclude_from(tree_lists))] pub earliest_consolidation_epoch: Epoch, + #[compare_fields(as_iter)] #[test_random(default)] #[superstruct(only(Electra))] pub pending_balance_deposits: List, + #[compare_fields(as_iter)] #[test_random(default)] #[superstruct(only(Electra))] pub pending_partial_withdrawals: List, + #[compare_fields(as_iter)] #[test_random(default)] #[superstruct(only(Electra))] pub pending_consolidations: List, diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index 0f61f74efe1..9cc864f9641 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -880,6 +880,14 @@ impl ChainSpec { electra_fork_epoch: None, max_pending_partials_per_withdrawals_sweep: u64::checked_pow(2, 0) .expect("pow does not overflow"), + min_per_epoch_churn_limit_electra: option_wrapper(|| { + u64::checked_pow(2, 6)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), + max_per_epoch_activation_exit_churn_limit: option_wrapper(|| { + u64::checked_pow(2, 7)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), // Other network_id: 2, // lighthouse testnet network id deposit_chain_id: 5, diff --git a/consensus/types/src/deposit_receipt.rs b/consensus/types/src/deposit_request.rs similarity index 100% rename from consensus/types/src/deposit_receipt.rs rename to consensus/types/src/deposit_request.rs diff --git a/consensus/types/src/execution_payload.rs b/consensus/types/src/execution_payload.rs index eca561f7353..02300cc1927 100644 --- a/consensus/types/src/execution_payload.rs +++ b/consensus/types/src/execution_payload.rs @@ -94,6 +94,8 @@ pub struct ExecutionPayload { #[serde(with = "serde_utils::quoted_u64")] pub excess_blob_gas: u64, #[superstruct(only(Electra))] + //TODO(electra) remove alias once EF tests are updates with correct name + #[serde(alias = "deposit_receipts")] pub deposit_requests: VariableList, #[superstruct(only(Electra))] pub withdrawal_requests: diff --git a/consensus/types/src/execution_payload_header.rs b/consensus/types/src/execution_payload_header.rs index 962e7a16fbc..149cc286ae9 100644 --- a/consensus/types/src/execution_payload_header.rs +++ b/consensus/types/src/execution_payload_header.rs @@ -86,7 +86,9 @@ pub struct ExecutionPayloadHeader { #[serde(with = "serde_utils::quoted_u64")] pub excess_blob_gas: u64, #[superstruct(only(Electra), partial_getter(copy))] - pub deposit_receipts_root: Hash256, + //TODO(electra) remove alias once EF tests are updates with correct name + #[serde(alias = "deposit_receipts_root")] + pub deposit_requests_root: Hash256, #[superstruct(only(Electra), partial_getter(copy))] pub withdrawal_requests_root: Hash256, } @@ -202,7 +204,7 @@ impl ExecutionPayloadHeaderDeneb { withdrawals_root: self.withdrawals_root, blob_gas_used: self.blob_gas_used, excess_blob_gas: self.excess_blob_gas, - deposit_receipts_root: Hash256::zero(), + deposit_requests_root: Hash256::zero(), withdrawal_requests_root: Hash256::zero(), } } @@ -295,7 +297,7 @@ impl<'a, E: EthSpec> From<&'a ExecutionPayloadElectra> for ExecutionPayloadHe withdrawals_root: payload.withdrawals.tree_hash_root(), blob_gas_used: payload.blob_gas_used, excess_blob_gas: payload.excess_blob_gas, - deposit_receipts_root: payload.deposit_requests.tree_hash_root(), + deposit_requests_root: payload.deposit_requests.tree_hash_root(), withdrawal_requests_root: payload.withdrawal_requests.tree_hash_root(), } } diff --git a/consensus/types/src/fork_name.rs b/consensus/types/src/fork_name.rs index 55a393e0188..51a5b3813ba 100644 --- a/consensus/types/src/fork_name.rs +++ b/consensus/types/src/fork_name.rs @@ -130,6 +130,18 @@ impl ForkName { } } + pub fn altair_enabled(self) -> bool { + self >= ForkName::Altair + } + + pub fn bellatrix_enabled(self) -> bool { + self >= ForkName::Bellatrix + } + + pub fn capella_enabled(self) -> bool { + self >= ForkName::Capella + } + pub fn deneb_enabled(self) -> bool { self >= ForkName::Deneb } diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index c8c37ad708e..b5c500f0b22 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -33,7 +33,7 @@ pub mod contribution_and_proof; pub mod deposit; pub mod deposit_data; pub mod deposit_message; -pub mod deposit_receipt; +pub mod deposit_request; pub mod deposit_tree_snapshot; pub mod enr_fork_id; pub mod eth1_data; @@ -150,7 +150,7 @@ pub use crate::contribution_and_proof::ContributionAndProof; pub use crate::deposit::{Deposit, DEPOSIT_TREE_DEPTH}; pub use crate::deposit_data::DepositData; pub use crate::deposit_message::DepositMessage; -pub use crate::deposit_receipt::DepositRequest; +pub use crate::deposit_request::DepositRequest; pub use crate::deposit_tree_snapshot::{DepositTreeSnapshot, FinalizedExecutionBlock}; pub use crate::enr_fork_id::EnrForkId; pub use crate::epoch_cache::{EpochCache, EpochCacheError, EpochCacheKey}; diff --git a/testing/ef_tests/Makefile b/testing/ef_tests/Makefile index 508c284275a..5dc3d2a0404 100644 --- a/testing/ef_tests/Makefile +++ b/testing/ef_tests/Makefile @@ -1,4 +1,4 @@ -TESTS_TAG := v1.4.0-beta.6 +TESTS_TAG := v1.5.0-alpha.2 TESTS = general minimal mainnet TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS)) diff --git a/testing/ef_tests/check_all_files_accessed.py b/testing/ef_tests/check_all_files_accessed.py index 5f425ab98b4..e1a308f7a40 100755 --- a/testing/ef_tests/check_all_files_accessed.py +++ b/testing/ef_tests/check_all_files_accessed.py @@ -43,8 +43,14 @@ "bls12-381-tests/hash_to_G2", "tests/.*/eip6110", "tests/.*/whisk", - # TODO(electra): re-enable in https://github.com/sigp/lighthouse/pull/5758 - "tests/.*/.*/ssz_static/IndexedAttestation" + "tests/.*/eip7594", + # TODO(electra) re-enable once https://github.com/sigp/lighthouse/issues/6002 is resolved + "tests/.*/electra/ssz_static/LightClientUpdate", + "tests/.*/electra/ssz_static/LightClientFinalityUpdate", + "tests/.*/electra/ssz_static/LightClientBootstrap", + # TODO(electra) re-enable as DepositRequest when EF tests are updated + "tests/.*/electra/operations/deposit_receipt", + "tests/.*/electra/ssz_static/DepositReceipt" ] diff --git a/testing/ef_tests/src/cases/epoch_processing.rs b/testing/ef_tests/src/cases/epoch_processing.rs index c4c592e4cf2..dfd782a22b3 100644 --- a/testing/ef_tests/src/cases/epoch_processing.rs +++ b/testing/ef_tests/src/cases/epoch_processing.rs @@ -10,6 +10,9 @@ use state_processing::per_epoch_processing::capella::process_historical_summarie use state_processing::per_epoch_processing::effective_balance_updates::{ process_effective_balance_updates, process_effective_balance_updates_slow, }; +use state_processing::per_epoch_processing::single_pass::{ + process_epoch_single_pass, SinglePassConfig, +}; use state_processing::per_epoch_processing::{ altair, base, historical_roots_update::process_historical_roots_update, @@ -53,6 +56,10 @@ pub struct Slashings; #[derive(Debug)] pub struct Eth1DataReset; #[derive(Debug)] +pub struct PendingBalanceDeposits; +#[derive(Debug)] +pub struct PendingConsolidations; +#[derive(Debug)] pub struct EffectiveBalanceUpdates; #[derive(Debug)] pub struct SlashingsReset; @@ -79,6 +86,8 @@ type_name!(RewardsAndPenalties, "rewards_and_penalties"); type_name!(RegistryUpdates, "registry_updates"); type_name!(Slashings, "slashings"); type_name!(Eth1DataReset, "eth1_data_reset"); +type_name!(PendingBalanceDeposits, "pending_balance_deposits"); +type_name!(PendingConsolidations, "pending_consolidations"); type_name!(EffectiveBalanceUpdates, "effective_balance_updates"); type_name!(SlashingsReset, "slashings_reset"); type_name!(RandaoMixesReset, "randao_mixes_reset"); @@ -178,6 +187,35 @@ impl EpochTransition for Eth1DataReset { } } +impl EpochTransition for PendingBalanceDeposits { + fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { + process_epoch_single_pass( + state, + spec, + SinglePassConfig { + pending_balance_deposits: true, + ..SinglePassConfig::disable_all() + }, + ) + .map(|_| ()) + } +} + +impl EpochTransition for PendingConsolidations { + fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { + initialize_epoch_cache(state, spec)?; + process_epoch_single_pass( + state, + spec, + SinglePassConfig { + pending_consolidations: true, + ..SinglePassConfig::disable_all() + }, + ) + .map(|_| ()) + } +} + impl EpochTransition for EffectiveBalanceUpdates { fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { if let BeaconState::Base(_) = state { @@ -304,24 +342,32 @@ impl> Case for EpochProcessing { } fn is_enabled_for_fork(fork_name: ForkName) -> bool { - match fork_name { - // No Altair tests for genesis fork. - ForkName::Base => { - T::name() != "sync_committee_updates" - && T::name() != "inactivity_updates" - && T::name() != "participation_flag_updates" - && T::name() != "historical_summaries_update" - } - // No phase0 tests for Altair and later. - ForkName::Altair | ForkName::Bellatrix => { - T::name() != "participation_record_updates" - && T::name() != "historical_summaries_update" - } - ForkName::Capella | ForkName::Deneb | ForkName::Electra => { - T::name() != "participation_record_updates" - && T::name() != "historical_roots_update" - } + if !fork_name.altair_enabled() + && (T::name() == "sync_committee_updates" + || T::name() == "inactivity_updates" + || T::name() == "participation_flag_updates") + { + return false; + } + + if fork_name.altair_enabled() && T::name() == "participation_record_updates" { + return false; + } + + if !fork_name.capella_enabled() && T::name() == "historical_summaries_update" { + return false; + } + + if fork_name.capella_enabled() && T::name() == "historical_roots_update" { + return false; + } + + if !fork_name.electra_enabled() + && (T::name() == "pending_consolidations" || T::name() == "pending_balance_deposits") + { + return false; } + true } fn result(&self, _case_index: usize, fork_name: ForkName) -> Result<(), Error> { diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index d87770a4df0..0af2c818271 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -6,6 +6,9 @@ use serde::Deserialize; use ssz::Decode; use state_processing::common::update_progressive_balances_cache::initialize_progressive_balances_cache; use state_processing::epoch_cache::initialize_epoch_cache; +use state_processing::per_block_processing::process_operations::{ + process_consolidations, process_deposit_requests, process_execution_layer_withdrawal_requests, +}; use state_processing::{ per_block_processing::{ errors::BlockProcessingError, @@ -21,8 +24,9 @@ use state_processing::{ use std::fmt::Debug; use types::{ Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix, - BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconState, BlindedPayload, Deposit, - ExecutionPayload, FullPayload, ProposerSlashing, SignedBlsToExecutionChange, + BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconState, + BlindedPayload, Deposit, DepositRequest, ExecutionLayerWithdrawalRequest, ExecutionPayload, + FullPayload, ProposerSlashing, SignedBlsToExecutionChange, SignedConsolidation, SignedVoluntaryExit, SyncAggregate, }; @@ -294,7 +298,7 @@ impl Operation for BeaconBlockBody> { } fn is_enabled_for_fork(fork_name: ForkName) -> bool { - fork_name != ForkName::Base && fork_name != ForkName::Altair + fork_name.bellatrix_enabled() } fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result { @@ -303,6 +307,7 @@ impl Operation for BeaconBlockBody> { ForkName::Bellatrix => BeaconBlockBody::Bellatrix(<_>::from_ssz_bytes(bytes)?), ForkName::Capella => BeaconBlockBody::Capella(<_>::from_ssz_bytes(bytes)?), ForkName::Deneb => BeaconBlockBody::Deneb(<_>::from_ssz_bytes(bytes)?), + ForkName::Electra => BeaconBlockBody::Electra(<_>::from_ssz_bytes(bytes)?), _ => panic!(), }) }) @@ -335,7 +340,7 @@ impl Operation for BeaconBlockBody> { } fn is_enabled_for_fork(fork_name: ForkName) -> bool { - fork_name != ForkName::Base && fork_name != ForkName::Altair + fork_name.bellatrix_enabled() } fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result { @@ -354,6 +359,10 @@ impl Operation for BeaconBlockBody> { let inner = >>::from_ssz_bytes(bytes)?; BeaconBlockBody::Deneb(inner.clone_as_blinded()) } + ForkName::Electra => { + let inner = >>::from_ssz_bytes(bytes)?; + BeaconBlockBody::Electra(inner.clone_as_blinded()) + } _ => panic!(), }) }) @@ -387,9 +396,7 @@ impl Operation for WithdrawalsPayload { } fn is_enabled_for_fork(fork_name: ForkName) -> bool { - fork_name != ForkName::Base - && fork_name != ForkName::Altair - && fork_name != ForkName::Bellatrix + fork_name.capella_enabled() } fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result { @@ -421,9 +428,7 @@ impl Operation for SignedBlsToExecutionChange { } fn is_enabled_for_fork(fork_name: ForkName) -> bool { - fork_name != ForkName::Base - && fork_name != ForkName::Altair - && fork_name != ForkName::Bellatrix + fork_name.capella_enabled() } fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result { @@ -440,6 +445,75 @@ impl Operation for SignedBlsToExecutionChange { } } +impl Operation for ExecutionLayerWithdrawalRequest { + fn handler_name() -> String { + "execution_layer_withdrawal_request".into() + } + + fn is_enabled_for_fork(fork_name: ForkName) -> bool { + fork_name.electra_enabled() + } + + fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result { + ssz_decode_file(path) + } + + fn apply_to( + &self, + state: &mut BeaconState, + spec: &ChainSpec, + _extra: &Operations, + ) -> Result<(), BlockProcessingError> { + process_execution_layer_withdrawal_requests(state, &[self.clone()], spec) + } +} + +impl Operation for DepositRequest { + fn handler_name() -> String { + "deposit_request".into() + } + + fn is_enabled_for_fork(fork_name: ForkName) -> bool { + fork_name.electra_enabled() + } + + fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result { + ssz_decode_file(path) + } + + fn apply_to( + &self, + state: &mut BeaconState, + spec: &ChainSpec, + _extra: &Operations, + ) -> Result<(), BlockProcessingError> { + process_deposit_requests(state, &[self.clone()], spec) + } +} + +impl Operation for SignedConsolidation { + fn handler_name() -> String { + "consolidation".into() + } + + fn is_enabled_for_fork(fork_name: ForkName) -> bool { + fork_name.electra_enabled() + } + + fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result { + ssz_decode_file(path) + } + + fn apply_to( + &self, + state: &mut BeaconState, + spec: &ChainSpec, + _extra: &Operations, + ) -> Result<(), BlockProcessingError> { + process_consolidations(state, &[self.clone()], VerifySignatures::True, spec) + } +} + impl> LoadCase for Operations { fn load_from_dir(path: &Path, fork_name: ForkName) -> Result { let spec = &testing_spec::(fork_name); diff --git a/testing/ef_tests/src/handler.rs b/testing/ef_tests/src/handler.rs index 69f6937ad85..410a37e7682 100644 --- a/testing/ef_tests/src/handler.rs +++ b/testing/ef_tests/src/handler.rs @@ -20,9 +20,8 @@ pub trait Handler { // Add forks here to exclude them from EF spec testing. Helpful for adding future or // unspecified forks. - // TODO(electra): Enable Electra once spec tests are available. fn disabled_forks(&self) -> Vec { - vec![ForkName::Electra] + vec![] } fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool { @@ -245,6 +244,14 @@ impl SszStaticHandler { Self::for_forks(ForkName::list_all()[3..].to_vec()) } + pub fn deneb_and_later() -> Self { + Self::for_forks(ForkName::list_all()[4..].to_vec()) + } + + pub fn electra_and_later() -> Self { + Self::for_forks(ForkName::list_all()[5..].to_vec()) + } + pub fn pre_electra() -> Self { Self::for_forks(ForkName::list_all()[0..5].to_vec()) } @@ -577,7 +584,7 @@ impl Handler for ForkChoiceHandler { // No FCU override tests prior to bellatrix. if self.handler_name == "should_override_forkchoice_update" - && (fork_name == ForkName::Base || fork_name == ForkName::Altair) + && !fork_name.bellatrix_enabled() { return false; } @@ -613,9 +620,7 @@ impl Handler for OptimisticSyncHandler { } fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool { - fork_name != ForkName::Base - && fork_name != ForkName::Altair - && cfg!(not(feature = "fake_crypto")) + fork_name.bellatrix_enabled() && cfg!(not(feature = "fake_crypto")) } } @@ -798,13 +803,12 @@ impl Handler for MerkleProofValidityHandler { "single_merkle_proof".into() } - fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool { - fork_name != ForkName::Base - // Test is skipped due to some changes in the Capella light client - // spec. - // - // https://github.com/sigp/lighthouse/issues/4022 - && fork_name != ForkName::Capella && fork_name != ForkName::Deneb + fn is_enabled_for_fork(&self, _fork_name: ForkName) -> bool { + // Test is skipped due to some changes in the Capella light client + // spec. + // + // https://github.com/sigp/lighthouse/issues/4022 + false } } @@ -829,10 +833,7 @@ impl Handler for KzgInclusionMerkleProofValidityHandler bool { // Enabled in Deneb - fork_name != ForkName::Base - && fork_name != ForkName::Altair - && fork_name != ForkName::Bellatrix - && fork_name != ForkName::Capella + fork_name == ForkName::Deneb } } diff --git a/testing/ef_tests/src/lib.rs b/testing/ef_tests/src/lib.rs index 5ab2b4b7b43..e55551be701 100644 --- a/testing/ef_tests/src/lib.rs +++ b/testing/ef_tests/src/lib.rs @@ -3,8 +3,8 @@ pub use cases::WithdrawalsPayload; pub use cases::{ Case, EffectiveBalanceUpdates, Eth1DataReset, HistoricalRootsUpdate, HistoricalSummariesUpdate, InactivityUpdates, JustificationAndFinalization, ParticipationFlagUpdates, - ParticipationRecordUpdates, RandaoMixesReset, RegistryUpdates, RewardsAndPenalties, Slashings, - SlashingsReset, SyncCommitteeUpdates, + ParticipationRecordUpdates, PendingBalanceDeposits, PendingConsolidations, RandaoMixesReset, + RegistryUpdates, RewardsAndPenalties, Slashings, SlashingsReset, SyncCommitteeUpdates, }; pub use decode::log_file_access; pub use error::Error; diff --git a/testing/ef_tests/src/type_name.rs b/testing/ef_tests/src/type_name.rs index f886431b400..d6ef873ead4 100644 --- a/testing/ef_tests/src/type_name.rs +++ b/testing/ef_tests/src/type_name.rs @@ -54,25 +54,31 @@ type_name_generic!(BeaconBlockBodyAltair, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyBellatrix, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyCapella, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyDeneb, "BeaconBlockBody"); +type_name_generic!(BeaconBlockBodyElectra, "BeaconBlockBody"); type_name!(BeaconBlockHeader); type_name_generic!(BeaconState); type_name!(BlobIdentifier); type_name_generic!(BlobSidecar); type_name!(Checkpoint); +type_name!(Consolidation); type_name_generic!(ContributionAndProof); type_name!(Deposit); type_name!(DepositData); type_name!(DepositMessage); +type_name!(DepositRequest); type_name!(Eth1Data); +type_name!(ExecutionLayerWithdrawalRequest); type_name_generic!(ExecutionPayload); type_name_generic!(ExecutionPayloadBellatrix, "ExecutionPayload"); type_name_generic!(ExecutionPayloadCapella, "ExecutionPayload"); type_name_generic!(ExecutionPayloadDeneb, "ExecutionPayload"); +type_name_generic!(ExecutionPayloadElectra, "ExecutionPayload"); type_name_generic!(FullPayload, "ExecutionPayload"); type_name_generic!(ExecutionPayloadHeader); type_name_generic!(ExecutionPayloadHeaderBellatrix, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderCapella, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderDeneb, "ExecutionPayloadHeader"); +type_name_generic!(ExecutionPayloadHeaderElectra, "ExecutionPayloadHeader"); type_name_generic!(BlindedPayload, "ExecutionPayloadHeader"); type_name!(Fork); type_name!(ForkData); @@ -84,6 +90,7 @@ type_name_generic!(LightClientBootstrap); type_name_generic!(LightClientBootstrapAltair, "LightClientBootstrap"); type_name_generic!(LightClientBootstrapCapella, "LightClientBootstrap"); type_name_generic!(LightClientBootstrapDeneb, "LightClientBootstrap"); +type_name_generic!(LightClientBootstrapElectra, "LightClientBootstrap"); type_name_generic!(LightClientFinalityUpdate); type_name_generic!(LightClientFinalityUpdateAltair, "LightClientFinalityUpdate"); type_name_generic!( @@ -91,10 +98,15 @@ type_name_generic!( "LightClientFinalityUpdate" ); type_name_generic!(LightClientFinalityUpdateDeneb, "LightClientFinalityUpdate"); +type_name_generic!( + LightClientFinalityUpdateElectra, + "LightClientFinalityUpdate" +); type_name_generic!(LightClientHeader); -type_name_generic!(LightClientHeaderDeneb, "LightClientHeader"); -type_name_generic!(LightClientHeaderCapella, "LightClientHeader"); type_name_generic!(LightClientHeaderAltair, "LightClientHeader"); +type_name_generic!(LightClientHeaderCapella, "LightClientHeader"); +type_name_generic!(LightClientHeaderDeneb, "LightClientHeader"); +type_name_generic!(LightClientHeaderElectra, "LightClientHeader"); type_name_generic!(LightClientOptimisticUpdate); type_name_generic!( LightClientOptimisticUpdateAltair, @@ -108,17 +120,26 @@ type_name_generic!( LightClientOptimisticUpdateDeneb, "LightClientOptimisticUpdate" ); +type_name_generic!( + LightClientOptimisticUpdateElectra, + "LightClientOptimisticUpdate" +); type_name_generic!(LightClientUpdate); type_name_generic!(LightClientUpdateAltair, "LightClientUpdate"); type_name_generic!(LightClientUpdateCapella, "LightClientUpdate"); type_name_generic!(LightClientUpdateDeneb, "LightClientUpdate"); +type_name_generic!(LightClientUpdateElectra, "LightClientUpdate"); type_name_generic!(PendingAttestation); +type_name!(PendingConsolidation); +type_name!(PendingPartialWithdrawal); +type_name!(PendingBalanceDeposit); type_name!(ProposerSlashing); type_name_generic!(SignedAggregateAndProof); type_name_generic!(SignedAggregateAndProofBase, "SignedAggregateAndProof"); type_name_generic!(SignedAggregateAndProofElectra, "SignedAggregateAndProof"); type_name_generic!(SignedBeaconBlock); type_name!(SignedBeaconBlockHeader); +type_name!(SignedConsolidation); type_name_generic!(SignedContributionAndProof); type_name!(SignedVoluntaryExit); type_name!(SigningData); diff --git a/testing/ef_tests/tests/tests.rs b/testing/ef_tests/tests/tests.rs index 60685140100..10a57a6b45e 100644 --- a/testing/ef_tests/tests/tests.rs +++ b/testing/ef_tests/tests/tests.rs @@ -1,7 +1,7 @@ #![cfg(feature = "ef_tests")] use ef_tests::*; -use types::{MainnetEthSpec, MinimalEthSpec, *}; +use types::{ExecutionLayerWithdrawalRequest, MainnetEthSpec, MinimalEthSpec, *}; // Check that the hand-computed multiplications on EthSpec are correctly computed. // This test lives here because one is most likely to muck these up during a spec update. @@ -14,6 +14,10 @@ fn check_typenum_values() { E::SlotsPerEth1VotingPeriod::to_u64(), E::EpochsPerEth1VotingPeriod::to_u64() * E::SlotsPerEpoch::to_u64() ); + assert_eq!( + E::MaxValidatorsPerSlot::to_u64(), + E::MaxCommitteesPerSlot::to_u64() * E::MaxValidatorsPerCommittee::to_u64() + ); } #[test] @@ -88,6 +92,27 @@ fn operations_withdrawals() { OperationsHandler::>::default().run(); } +#[test] +fn operations_execution_layer_withdrawal_reqeusts() { + OperationsHandler::::default().run(); + OperationsHandler::::default().run(); +} + +#[test] +#[cfg(not(feature = "fake_crypto"))] +fn operations_deposit_requests() { + //TODO(electra): re-enable mainnet once they update the name for this + // OperationsHandler::::default().run(); + // OperationsHandler::::default().run(); +} + +#[test] +fn operations_consolidations() { + OperationsHandler::::default().run(); + //TODO(electra): re-enable mainnet once they make tests for this + //OperationsHandler::::default().run(); +} + #[test] fn operations_bls_to_execution_change() { OperationsHandler::::default().run(); @@ -217,7 +242,11 @@ mod ssz_static { use ef_tests::{Handler, SszStaticHandler, SszStaticTHCHandler, SszStaticWithSpecHandler}; use types::blob_sidecar::BlobIdentifier; use types::historical_summary::HistoricalSummary; - use types::{AttesterSlashingBase, AttesterSlashingElectra, LightClientBootstrapAltair, *}; + use types::{ + AttesterSlashingBase, AttesterSlashingElectra, Consolidation, + ExecutionLayerWithdrawalRequest, LightClientBootstrapAltair, PendingBalanceDeposit, + PendingPartialWithdrawal, *, + }; ssz_static_test!(attestation_data, AttestationData); ssz_static_test!(beacon_block, SszStaticWithSpecHandler, BeaconBlock<_>); @@ -267,6 +296,18 @@ mod ssz_static { .run(); } + #[test] + fn indexed_attestation() { + SszStaticHandler::, MinimalEthSpec>::pre_electra() + .run(); + SszStaticHandler::, MainnetEthSpec>::pre_electra() + .run(); + SszStaticHandler::, MinimalEthSpec>::electra_only() + .run(); + SszStaticHandler::, MainnetEthSpec>::electra_only() + .run(); + } + #[test] fn signed_aggregate_and_proof() { SszStaticHandler::, MinimalEthSpec>::pre_electra( @@ -318,6 +359,10 @@ mod ssz_static { .run(); SszStaticHandler::, MainnetEthSpec>::deneb_only() .run(); + SszStaticHandler::, MinimalEthSpec>::electra_only() + .run(); + SszStaticHandler::, MainnetEthSpec>::electra_only() + .run(); } // Altair and later @@ -352,6 +397,11 @@ mod ssz_static { .run(); SszStaticHandler::, MainnetEthSpec>::deneb_only() .run(); + // TODO(electra) re-enable once https://github.com/sigp/lighthouse/issues/6002 is resolved + // SszStaticHandler::, MinimalEthSpec>::electra_only() + // .run(); + // SszStaticHandler::, MainnetEthSpec>::electra_only() + // .run(); } // LightClientHeader has no internal indicator of which fork it is for, so we test it separately. @@ -377,35 +427,27 @@ mod ssz_static { .run(); SszStaticHandler::, MainnetEthSpec>::deneb_only() .run(); + SszStaticHandler::, MinimalEthSpec>::electra_only( + ) + .run(); + SszStaticHandler::, MainnetEthSpec>::electra_only( + ) + .run(); } // LightClientOptimisticUpdate has no internal indicator of which fork it is for, so we test it separately. #[test] fn light_client_optimistic_update() { - SszStaticHandler::, MinimalEthSpec>::altair_only( - ) - .run(); - SszStaticHandler::, MainnetEthSpec>::altair_only( - ) - .run(); - SszStaticHandler::, MinimalEthSpec>::bellatrix_only( - ) - .run(); - SszStaticHandler::, MainnetEthSpec>::bellatrix_only( - ) - .run(); - SszStaticHandler::, MinimalEthSpec>::capella_only( - ) - .run(); - SszStaticHandler::, MainnetEthSpec>::capella_only( - ) - .run(); - SszStaticHandler::, MinimalEthSpec>::deneb_only( - ) - .run(); - SszStaticHandler::, MainnetEthSpec>::deneb_only( - ) - .run(); + SszStaticHandler::, MinimalEthSpec>::altair_only().run(); + SszStaticHandler::, MainnetEthSpec>::altair_only().run(); + SszStaticHandler::, MinimalEthSpec>::bellatrix_only().run(); + SszStaticHandler::, MainnetEthSpec>::bellatrix_only().run(); + SszStaticHandler::, MinimalEthSpec>::capella_only().run(); + SszStaticHandler::, MainnetEthSpec>::capella_only().run(); + SszStaticHandler::, MinimalEthSpec>::deneb_only().run(); + SszStaticHandler::, MainnetEthSpec>::deneb_only().run(); + SszStaticHandler::, MinimalEthSpec>::electra_only().run(); + SszStaticHandler::, MainnetEthSpec>::electra_only().run(); } // LightClientFinalityUpdate has no internal indicator of which fork it is for, so we test it separately. @@ -435,6 +477,13 @@ mod ssz_static { SszStaticHandler::, MainnetEthSpec>::deneb_only( ) .run(); + // TODO(electra) re-enable once https://github.com/sigp/lighthouse/issues/6002 is resolved + // SszStaticHandler::, MinimalEthSpec>::electra_only( + // ) + // .run(); + // SszStaticHandler::, MainnetEthSpec>::electra_only( + // ) + // .run(); } // LightClientUpdate has no internal indicator of which fork it is for, so we test it separately. @@ -458,6 +507,13 @@ mod ssz_static { .run(); SszStaticHandler::, MainnetEthSpec>::deneb_only() .run(); + // TODO(electra) re-enable once https://github.com/sigp/lighthouse/issues/6002 is resolved + // SszStaticHandler::, MinimalEthSpec>::electra_only( + // ) + // .run(); + // SszStaticHandler::, MainnetEthSpec>::electra_only( + // ) + // .run(); } #[test] @@ -511,6 +567,10 @@ mod ssz_static { .run(); SszStaticHandler::, MainnetEthSpec>::deneb_only() .run(); + SszStaticHandler::, MinimalEthSpec>::electra_only() + .run(); + SszStaticHandler::, MainnetEthSpec>::electra_only() + .run(); } #[test] @@ -527,6 +587,10 @@ mod ssz_static { ::deneb_only().run(); SszStaticHandler::, MainnetEthSpec> ::deneb_only().run(); + SszStaticHandler::, MinimalEthSpec> + ::electra_only().run(); + SszStaticHandler::, MainnetEthSpec> + ::electra_only().run(); } #[test] @@ -549,14 +613,14 @@ mod ssz_static { #[test] fn blob_sidecar() { - SszStaticHandler::, MinimalEthSpec>::deneb_only().run(); - SszStaticHandler::, MainnetEthSpec>::deneb_only().run(); + SszStaticHandler::, MinimalEthSpec>::deneb_and_later().run(); + SszStaticHandler::, MainnetEthSpec>::deneb_and_later().run(); } #[test] fn blob_identifier() { - SszStaticHandler::::deneb_only().run(); - SszStaticHandler::::deneb_only().run(); + SszStaticHandler::::deneb_and_later().run(); + SszStaticHandler::::deneb_and_later().run(); } #[test] @@ -564,6 +628,51 @@ mod ssz_static { SszStaticHandler::::capella_and_later().run(); SszStaticHandler::::capella_and_later().run(); } + + #[test] + fn consolidation() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + } + + // TODO(electra) re-enable when EF tests are updated + // #[test] + // fn deposit_request() { + // SszStaticHandler::::electra_and_later().run(); + // SszStaticHandler::::electra_and_later().run(); + // } + + #[test] + fn execution_layer_withdrawal_request() { + SszStaticHandler::::electra_and_later() + .run(); + SszStaticHandler::::electra_and_later() + .run(); + } + + #[test] + fn pending_balance_deposit() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + } + + #[test] + fn pending_consolidation() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + } + + #[test] + fn pending_partial_withdrawal() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + } + + #[test] + fn signed_consolidation() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + } } #[test] @@ -606,6 +715,18 @@ fn epoch_processing_eth1_data_reset() { EpochProcessingHandler::::default().run(); } +#[test] +fn epoch_processing_pending_balance_deposits() { + EpochProcessingHandler::::default().run(); + EpochProcessingHandler::::default().run(); +} + +#[test] +fn epoch_processing_pending_consolidations() { + EpochProcessingHandler::::default().run(); + EpochProcessingHandler::::default().run(); +} + #[test] fn epoch_processing_effective_balance_updates() { EpochProcessingHandler::::default().run();