From edcfee636cd7c32ee63e981ec0487a2798ec6518 Mon Sep 17 00:00:00 2001 From: Pawan Dhananjay Date: Sat, 27 Sep 2025 21:03:25 -0700 Subject: [PATCH] Fix bug in fork calculation at fork boundaries (#8121) N/A In #8101 , when we modified the logic to get the proposer index post fulu, we seem to have missed advancing the state at the fork boundaries to get the right `Fork` for signature verification. This led to lighthouse failing all gossip verification right after transitioning to fulu that was observed on the holesky shadow fork ``` Sep 26 14:24:00.088 DEBUG Rejected gossip block error: "InvalidSignature(ProposerSignature)", graffiti: "grandine-geth-super-1", slot: 640 Sep 26 14:24:00.099 WARN Could not verify block for gossip. Rejecting the block error: InvalidSignature(ProposerSignature) ``` I'm not completely sure this is the correct fix, but this fixes the issue with `InvalidProposerSignature` on the holesky shadow fork. Thanks to @eserilev for helping debug this Co-Authored-By: Pawan Dhananjay --- beacon_node/beacon_chain/src/beacon_proposer_cache.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_proposer_cache.rs b/beacon_node/beacon_chain/src/beacon_proposer_cache.rs index 47c44542c0..a64b4981cc 100644 --- a/beacon_node/beacon_chain/src/beacon_proposer_cache.rs +++ b/beacon_node/beacon_chain/src/beacon_proposer_cache.rs @@ -234,8 +234,14 @@ pub fn ensure_state_can_determine_proposers_for_epoch( if state.current_epoch() > maximum_epoch { Err(BeaconStateError::SlotOutOfBounds.into()) } else if state.current_epoch() >= minimum_epoch { - // Fulu allows us to access shufflings in multiple epochs (thanks to lookahead). - // Pre-Fulu we expect `minimum_epoch == maximum_epoch`, and this branch covers that case. + if target_epoch > state.current_epoch() { + let target_slot = target_epoch.start_slot(E::slots_per_epoch()); + + // Advance the state into the same epoch as the block. Use the "partial" method since state + // roots are not important for proposer/attester shuffling. + partial_state_advance(state, Some(state_root), target_slot, spec) + .map_err(BeaconChainError::from)?; + } Ok(()) } else { // State's current epoch is less than the minimum epoch.