deprecate disallowed-offsets config for re-orgs (#9449)

https://github.com/ethereum/consensus-specs/pull/5348. As per discussions in issue we no longer need to support `disallowed-offsets` for pre-Fulu forks.


  


Co-Authored-By: hopinheimer <knmanas6@gmail.com>
This commit is contained in:
hopinheimer
2026-06-13 23:02:48 -04:00
committed by GitHub
parent 1d921b2b4e
commit 227a7c976f
15 changed files with 77 additions and 216 deletions

View File

@@ -5207,7 +5207,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
head_block_root,
re_org_head_threshold,
re_org_parent_threshold,
&self.config.re_org_disallowed_offsets,
re_org_max_epochs_since_finalization,
)
.map_err(|e| e.map_inner_error(Error::ProposerHeadForkChoiceError))?;
@@ -5244,44 +5243,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
return Err(Box::new(DoNotReOrg::HeadDistance.into()));
}
// Only attempt a re-org if we have a proposer registered for the re-org slot.
let proposing_at_re_org_slot = {
// We know our re-org block is not on the epoch boundary, so it has the same proposer
// shuffling as the head (but not necessarily the parent which may lie in the previous
// epoch).
let shuffling_decision_root = if self
.spec
.fork_name_at_slot::<T::EthSpec>(re_org_block_slot)
.fulu_enabled()
{
info.head_node.current_epoch_shuffling_id()
} else {
info.head_node.next_epoch_shuffling_id()
}
.shuffling_decision_block;
let proposer_index = self
.beacon_proposer_cache
.lock()
.get_slot::<T::EthSpec>(shuffling_decision_root, re_org_block_slot)
.ok_or_else(|| {
debug!(
slot = %re_org_block_slot,
decision_root = ?shuffling_decision_root,
"Fork choice override proposer shuffling miss"
);
Box::new(DoNotReOrg::NotProposing.into())
})?
.index as u64;
self.execution_layer
.as_ref()
.ok_or(ProposerHeadError::Error(Error::ExecutionLayerMissing))?
.has_proposer_preparation_data_blocking(proposer_index)
};
if !proposing_at_re_org_slot {
return Err(Box::new(DoNotReOrg::NotProposing.into()));
}
// TODO(gloas): reorg weight logic needs updating for Gloas. For now use
// total weight which is correct for pre-Gloas and conservative for post-Gloas.
let head_weight = info.head_node.weight();
@@ -5325,6 +5286,64 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
return Err(Box::new(DoNotReOrg::HeadNotLate.into()));
}
// Only attempt a re-org if we have a proposer registered for the re-org slot. This check
// runs after the cheaper checks above because it may compute (and cache) the proposer
// shuffling for the re-org slot's epoch on a cache miss.
let proposing_at_re_org_slot = {
// Since Fulu, proposer shuffling is computed one epoch in advance, so the shuffling
// for the re-org block's epoch is always decided by an ancestor of the head, even
// when the re-org block lies in the epoch after the head (epoch boundary re-org).
let proposal_in_head_epoch = re_org_block_slot.epoch(T::EthSpec::slots_per_epoch())
== head_slot.epoch(T::EthSpec::slots_per_epoch());
let shuffling_decision_root = if self
.spec
.fork_name_at_slot::<T::EthSpec>(re_org_block_slot)
.fulu_enabled()
&& proposal_in_head_epoch
{
info.head_node.current_epoch_shuffling_id()
} else {
info.head_node.next_epoch_shuffling_id()
}
.shuffling_decision_block;
let proposer_index = self
.with_proposer_cache::<u64, Error>(
shuffling_decision_root,
re_org_block_slot.epoch(T::EthSpec::slots_per_epoch()),
|proposers| {
proposers
.get_slot::<T::EthSpec>(re_org_block_slot)
.map(|proposer| proposer.index as u64)
},
|| {
debug!(
slot = %re_org_block_slot,
decision_root = ?shuffling_decision_root,
"Fork choice override proposer shuffling miss"
);
let head = self.canonical_head.cached_head();
Ok((head.head_state_root(), head.snapshot.beacon_state.clone()))
},
)
.map_err(|e| match e {
Error::ProposerCacheIncorrectState { .. } => {
// The head changed while we were computing the proposer shuffling.
// Decline the re-org rather than erroring out.
warn!("Head changed during fork choice override check");
Box::new(ProposerHeadError::from(DoNotReOrg::NotProposing))
}
e => Box::new(ProposerHeadError::Error(e)),
})?;
self.execution_layer
.as_ref()
.ok_or(ProposerHeadError::Error(Error::ExecutionLayerMissing))?
.has_proposer_preparation_data_blocking(proposer_index)
};
if !proposing_at_re_org_slot {
return Err(Box::new(DoNotReOrg::NotProposing.into()));
}
// TODO(gloas): V29 nodes don't carry execution_status, so this returns
// None for post-Gloas re-orgs. Need to source the EL block hash from
// the bid's block_hash instead. Re-org is disabled for Gloas for now.

View File

@@ -220,7 +220,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
canonical_head,
re_org_head_threshold,
re_org_parent_threshold,
&self.config.re_org_disallowed_offsets,
re_org_max_epochs_since_finalization,
)
.map_err(|e| match e {

View File

@@ -30,7 +30,6 @@ use kzg::Kzg;
use logging::crit;
use operation_pool::{OperationPool, PersistedOperationPool};
use parking_lot::{Mutex, RwLock};
use proto_array::DisallowedReOrgOffsets;
use rand::RngCore;
use rayon::prelude::*;
use slasher::Slasher;
@@ -176,15 +175,6 @@ where
self
}
/// Sets the proposer re-org disallowed offsets list.
pub fn proposer_re_org_disallowed_offsets(
mut self,
disallowed_offsets: DisallowedReOrgOffsets,
) -> Self {
self.chain_config.re_org_disallowed_offsets = disallowed_offsets;
self
}
/// Sets the store (database).
///
/// Should generally be called early in the build chain.

View File

@@ -1,5 +1,4 @@
use crate::custody_context::NodeCustodyType;
pub use proto_array::DisallowedReOrgOffsets;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use std::{collections::HashSet, sync::LazyLock, time::Duration};
@@ -36,11 +35,6 @@ pub struct ChainConfig {
pub archive: bool,
/// The max size of a message that can be sent over the network.
pub max_network_size: usize,
/// Additional epoch offsets at which re-orging block proposals are not permitted.
///
/// By default this list is empty, but it can be useful for reacting to network conditions, e.g.
/// slow gossip of re-org blocks at slot 1 in the epoch.
pub re_org_disallowed_offsets: DisallowedReOrgOffsets,
/// Number of milliseconds to wait for fork choice before proposing a block.
///
/// If set to 0 then block proposal will not wait for fork choice at all.
@@ -123,7 +117,6 @@ impl Default for ChainConfig {
weak_subjectivity_checkpoint: None,
archive: false,
max_network_size: 10 * 1_048_576, // 10M
re_org_disallowed_offsets: DisallowedReOrgOffsets::default(),
fork_choice_before_proposal_timeout_ms: DEFAULT_FORK_CHOICE_BEFORE_PROPOSAL_TIMEOUT,
// Builder fallback configs that are set in `clap` will override these.
builder_fallback_skips: 3,