Gloas alpha spec 9 (#9393)

Changes implemented

Ensure bids are for a higher slot than their parent (https://github.com/ethereum/consensus-specs/pull/5302)
Ignore PTC attestations for empty assigned slots (https://github.com/ethereum/consensus-specs/pull/5281)
Limit should_build_on_full checks to the previous slot (https://github.com/ethereum/consensus-specs/pull/5309)
Apply proposer boost if dependent roots match (https://github.com/ethereum/consensus-specs/pull/5306)
Exclude slashed validators from proposing (EIP-8045) (https://github.com/ethereum/consensus-specs/pull/5115)
Force the proposer to reorg late payloads (https://github.com/ethereum/consensus-specs/pull/5210)
Remove support for old deposit mechanism in Fulu (https://github.com/ethereum/consensus-specs/pull/4704)


  


Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>

Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com>

Co-Authored-By: Eitan Seri-Levi <eserilev@gmail.com>

Co-Authored-By: Michael Sproul <michael@sigmaprime.io>

Co-Authored-By: Michael Sproul <michaelsproul@users.noreply.github.com>
This commit is contained in:
Eitan Seri-Levi
2026-06-15 16:56:09 -07:00
committed by GitHub
parent d8e406b6ac
commit 58e35bc96f
33 changed files with 785 additions and 247 deletions

View File

@@ -542,6 +542,27 @@ where
}
}
/// Returns the dependent root for `block_root`, per the spec `get_dependent_root` helper.
fn get_dependent_root(
&self,
block_root: Hash256,
current_slot: Slot,
spec: &ChainSpec,
) -> Result<Option<Hash256>, Error<T::Error>> {
let epoch = current_slot.epoch(E::slots_per_epoch());
if epoch <= spec.min_seed_lookahead {
return Ok(Some(Hash256::zero()));
}
let dependent_slot = epoch
.saturating_sub(spec.min_seed_lookahead)
.start_slot(E::slots_per_epoch())
.saturating_sub(1_u64);
self.get_ancestor(block_root, dependent_slot)
}
/// Run the fork choice rule to determine the head.
///
/// ## Specification
@@ -768,7 +789,6 @@ where
block_delay: Duration,
state: &BeaconState<E>,
payload_verification_status: PayloadVerificationStatus,
canonical_head_proposer_index: u64,
spec: &ChainSpec,
) -> Result<(), Error<T::Error>> {
let _timer = metrics::start_timer(&metrics::FORK_CHOICE_ON_BLOCK_TIMES);
@@ -780,10 +800,17 @@ where
return Ok(());
}
// Provide the slot (as per the system clock) to the `fc_store` and then return its view of
// the current slot. The `fc_store` will ensure that the `current_slot` is never
// decreasing, a property which we must maintain.
let current_slot = self.update_time(system_time_current_slot)?;
let head_root = if system_time_current_slot == self.fc_store.get_current_slot() {
// Fork choice has already run for the current slot, so we can safely use the cached
// head without recomputing it.
self.cached_fork_choice_view().head_block_root
} else {
// Fork choice hasn't run for the current slot yet: run it, updating the fork choice
// store's current slot in the process.
self.get_head(system_time_current_slot, spec)?.0
};
let current_slot = self.fc_store.get_current_slot();
debug_assert_eq!(current_slot, system_time_current_slot);
// Parent block must be known.
let parent_block = self
@@ -833,19 +860,24 @@ where
let attestation_threshold = spec.get_attestation_due::<E>(block.slot());
// Add proposer score boost if the block is the first timely block for this slot and its
// proposer matches the expected proposer on the canonical chain (per spec
// `update_proposer_boost_root`, introduced in v1.7.0-alpha.5).
// Add proposer score boost if the block is the first timely block for this slot and it
// shares the same dependent root as the canonical chain head (per spec
// `update_proposer_boost_root`).
let is_before_attesting_interval = block_delay < attestation_threshold;
let is_timely = current_slot == block.slot() && is_before_attesting_interval;
let is_first_block = self.fc_store.proposer_boost_root().is_zero();
let is_canonical_proposer = block.proposer_index() == canonical_head_proposer_index;
if current_slot == block.slot()
&& is_before_attesting_interval
&& is_first_block
&& is_canonical_proposer
{
self.fc_store.set_proposer_boost_root(block_root);
if is_timely && is_first_block {
// The block isn't in fork choice so resolve its dependent root via its parent.
let block_dependent_root =
self.get_dependent_root(block.parent_root(), current_slot, spec)?;
let head_dependent_root = self.get_dependent_root(head_root, current_slot, spec)?;
// Add proposer score boost if the block is timely, not conflicting with an
// existing block, with the same dependent root as the canonical chain head.
if block_dependent_root.is_some() && block_dependent_root == head_dependent_root {
self.fc_store.set_proposer_boost_root(block_root);
}
}
// Update store with checkpoints if necessary
@@ -1581,9 +1613,10 @@ where
&self,
block_root: &Hash256,
parent_payload_status: PayloadStatus,
current_slot: Slot,
) -> Result<bool, Error<T::Error>> {
self.proto_array
.should_build_on_full::<E>(block_root, parent_payload_status)
.should_build_on_full::<E>(block_root, parent_payload_status, current_slot)
.map_err(Error::ProtoArrayStringError)
}

View File

@@ -316,7 +316,6 @@ impl ForkChoiceTest {
Duration::from_secs(0),
&state,
PayloadVerificationStatus::Verified,
block.message().proposer_index(),
&self.harness.chain.spec,
)
.unwrap();
@@ -360,7 +359,6 @@ impl ForkChoiceTest {
Duration::from_secs(0),
&state,
PayloadVerificationStatus::Verified,
block.message().proposer_index(),
&self.harness.chain.spec,
)
.expect_err("on_block did not return an error");