From 4d6d8d7d362016ee01ff2f3401bec8a89db525ca Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Wed, 10 Jun 2026 16:43:07 +0300 Subject: [PATCH] Fix tests --- .../beacon_chain/tests/block_verification.rs | 79 ------------------- .../ef_tests/src/cases/epoch_processing.rs | 2 + 2 files changed, 2 insertions(+), 79 deletions(-) diff --git a/beacon_node/beacon_chain/tests/block_verification.rs b/beacon_node/beacon_chain/tests/block_verification.rs index 1b362027a9..74a521a79c 100644 --- a/beacon_node/beacon_chain/tests/block_verification.rs +++ b/beacon_node/beacon_chain/tests/block_verification.rs @@ -2111,85 +2111,6 @@ async fn gloas_get_head_can_return_justified_empty_payload_branch() { assert_eq!(payload_status, PayloadStatus::Empty); } -// Post-Gloas, `get_beacon_proposer_indices` excludes slashed validators. The lookup prefers the -// slashings cache but falls back to reading validators directly when the cache is cold (e.g. block -// replay / state reconstruction). This test asserts the cold-cache fallback produces exactly the -// same proposers as the warm cache, and that neither path ever selects a slashed validator. -#[tokio::test] -async fn gloas_proposer_indices_exclude_slashed_with_cold_cache() { - let spec = test_spec::(); - if !spec.fork_name_at_epoch(Epoch::new(0)).gloas_enabled() { - return; - } - - let harness = BeaconChainHarness::builder(MainnetEthSpec) - .spec(spec.into()) - .chain_config(ChainConfig { - archive: true, - ..ChainConfig::default() - }) - .keypairs(KEYPAIRS[0..VALIDATOR_COUNT].to_vec()) - .node_custody_type(NodeCustodyType::Supernode) - .fresh_ephemeral_store() - .mock_execution_layer() - .build(); - - // Advance a couple of epochs so we have a fully-formed Gloas state. - harness - .extend_slots(E::slots_per_epoch() as usize * 2) - .await; - - let spec = harness.chain.spec.clone(); - let mut state = harness.get_current_state(); - let current_epoch = state.current_epoch(); - - // Slash every odd-indexed validator directly on the state. A large slashed fraction ensures - // the filter materially changes the candidate set, so a regressed (non-filtering) fallback - // would diverge from the cache rather than passing by luck. - let mut slashed_count = 0; - for index in (1..VALIDATOR_COUNT).step_by(2) { - state.get_validator_mut(index).unwrap().slashed = true; - slashed_count += 1; - } - assert!( - slashed_count > 0, - "test must actually slash some validators" - ); - - // `current + 2` is beyond `next_epoch`, so it bypasses the cached proposer-lookahead - // early-return and exercises the slashed-filter path in `get_beacon_proposer_indices`. - let request_epoch = current_epoch + 2; - - // Warm path: rebuild the slashings cache so it reflects the validators we just slashed. - state.drop_all_caches().unwrap(); - state.build_slashings_cache().unwrap(); - assert!(state.slashings_cache_is_initialized()); - let warm = state - .get_beacon_proposer_indices(request_epoch, &spec) - .unwrap(); - - // Cold path: drop the slashings cache so the lookup falls back to reading validators directly. - state.drop_all_caches().unwrap(); - assert!(!state.slashings_cache_is_initialized()); - let cold = state - .get_beacon_proposer_indices(request_epoch, &spec) - .unwrap(); - - // The fallback must produce exactly the same proposers as the warm cache. - assert_eq!( - warm, cold, - "cold-cache fallback diverged from the slashings cache" - ); - - // And in both cases, no slashed validator may be selected as a proposer. - for proposer in &cold { - assert!( - !state.get_validator(*proposer).unwrap().slashed, - "slashed validator {proposer} was selected as a proposer" - ); - } -} - // This is a regression test for this bug: // https://github.com/sigp/lighthouse/issues/4332#issuecomment-1565092279 #[tokio::test] diff --git a/testing/ef_tests/src/cases/epoch_processing.rs b/testing/ef_tests/src/cases/epoch_processing.rs index ec243f05cc..950d817d7b 100644 --- a/testing/ef_tests/src/cases/epoch_processing.rs +++ b/testing/ef_tests/src/cases/epoch_processing.rs @@ -422,6 +422,8 @@ impl> Case for EpochProcessing { // Processing requires the committee caches. pre_state.build_all_committee_caches(spec).unwrap(); + // Proposer index computation (e.g. proposer lookahead) requires the slashings cache. + pre_state.build_slashings_cache().unwrap(); let mut state = pre_state.clone(); let mut expected = self.post.clone();