Gloas serve post block state for finalized/justified state requests (#9092)

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

Co-Authored-By: Pawan Dhananjay <pawandhananjay@gmail.com>
This commit is contained in:
Eitan Seri-Levi
2026-04-09 03:44:19 +09:00
committed by GitHub
parent 243eecc465
commit 2749e18d0e
3 changed files with 54 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
use crate::version::inconsistent_fork_rejection; use crate::version::inconsistent_fork_rejection;
use crate::{ExecutionOptimistic, state_id::checkpoint_slot_and_execution_optimistic}; use crate::{ExecutionOptimistic, state_id::checkpoint_block_and_execution_optimistic};
use beacon_chain::kzg_utils::reconstruct_blobs; use beacon_chain::kzg_utils::reconstruct_blobs;
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped}; use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped};
use eth2::beacon_response::{ExecutionOptimisticFinalizedMetadata, UnversionedResponse}; use eth2::beacon_response::{ExecutionOptimisticFinalizedMetadata, UnversionedResponse};
@@ -60,15 +60,15 @@ impl BlockId {
CoreBlockId::Finalized => { CoreBlockId::Finalized => {
let finalized_checkpoint = let finalized_checkpoint =
chain.canonical_head.cached_head().finalized_checkpoint(); chain.canonical_head.cached_head().finalized_checkpoint();
let (_slot, execution_optimistic) = let (_block, execution_optimistic) =
checkpoint_slot_and_execution_optimistic(chain, finalized_checkpoint)?; checkpoint_block_and_execution_optimistic(chain, finalized_checkpoint)?;
Ok((finalized_checkpoint.root, execution_optimistic, true)) Ok((finalized_checkpoint.root, execution_optimistic, true))
} }
CoreBlockId::Justified => { CoreBlockId::Justified => {
let justified_checkpoint = let justified_checkpoint =
chain.canonical_head.cached_head().justified_checkpoint(); chain.canonical_head.cached_head().justified_checkpoint();
let (_slot, execution_optimistic) = let (_block, execution_optimistic) =
checkpoint_slot_and_execution_optimistic(chain, justified_checkpoint)?; checkpoint_block_and_execution_optimistic(chain, justified_checkpoint)?;
Ok((justified_checkpoint.root, execution_optimistic, false)) Ok((justified_checkpoint.root, execution_optimistic, false))
} }
CoreBlockId::Slot(slot) => { CoreBlockId::Slot(slot) => {

View File

@@ -2,6 +2,7 @@ use crate::ExecutionOptimistic;
use crate::metrics; use crate::metrics;
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::types::StateId as CoreStateId; use eth2::types::StateId as CoreStateId;
use proto_array::Block;
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use types::{BeaconState, Checkpoint, EthSpec, Fork, Hash256, Slot}; use types::{BeaconState, Checkpoint, EthSpec, Fork, Hash256, Slot};
@@ -19,6 +20,8 @@ impl StateId {
Self(CoreStateId::Slot(slot)) Self(CoreStateId::Slot(slot))
} }
// TODO(gloas) add tests for finalized and justified checkpoint states to ensure
// we return the post block state for gloas
/// Return the state root identified by `self`. /// Return the state root identified by `self`.
pub fn root<T: BeaconChainTypes>( pub fn root<T: BeaconChainTypes>(
&self, &self,
@@ -41,15 +44,41 @@ impl StateId {
CoreStateId::Finalized => { CoreStateId::Finalized => {
let finalized_checkpoint = let finalized_checkpoint =
chain.canonical_head.cached_head().finalized_checkpoint(); chain.canonical_head.cached_head().finalized_checkpoint();
let (slot, execution_optimistic) =
checkpoint_slot_and_execution_optimistic(chain, finalized_checkpoint)?; let slot = finalized_checkpoint
.epoch
.start_slot(T::EthSpec::slots_per_epoch());
let (block, execution_optimistic) =
checkpoint_block_and_execution_optimistic(chain, finalized_checkpoint)?;
if chain
.spec
.fork_name_at_slot::<T::EthSpec>(block.slot)
.gloas_enabled()
{
return Ok((block.state_root, execution_optimistic, true));
}
(slot, execution_optimistic, true) (slot, execution_optimistic, true)
} }
CoreStateId::Justified => { CoreStateId::Justified => {
let justified_checkpoint = let justified_checkpoint =
chain.canonical_head.cached_head().justified_checkpoint(); chain.canonical_head.cached_head().justified_checkpoint();
let (slot, execution_optimistic) =
checkpoint_slot_and_execution_optimistic(chain, justified_checkpoint)?; let slot = justified_checkpoint
.epoch
.start_slot(T::EthSpec::slots_per_epoch());
let (block, execution_optimistic) =
checkpoint_block_and_execution_optimistic(chain, justified_checkpoint)?;
if chain
.spec
.fork_name_at_slot::<T::EthSpec>(block.slot)
.gloas_enabled()
{
return Ok((block.state_root, execution_optimistic, false));
}
(slot, execution_optimistic, false) (slot, execution_optimistic, false)
} }
CoreStateId::Slot(slot) => ( CoreStateId::Slot(slot) => (
@@ -254,13 +283,11 @@ impl fmt::Display for StateId {
} }
} }
/// Returns the first slot of the checkpoint's `epoch` and the execution status of the checkpoint's /// Returns checkpoint block and the execution status of the checkpoint's `root`.
/// `root`. pub fn checkpoint_block_and_execution_optimistic<T: BeaconChainTypes>(
pub fn checkpoint_slot_and_execution_optimistic<T: BeaconChainTypes>(
chain: &BeaconChain<T>, chain: &BeaconChain<T>,
checkpoint: Checkpoint, checkpoint: Checkpoint,
) -> Result<(Slot, ExecutionOptimistic), warp::reject::Rejection> { ) -> Result<(Block, ExecutionOptimistic), warp::reject::Rejection> {
let slot = checkpoint.epoch.start_slot(T::EthSpec::slots_per_epoch());
let fork_choice = chain.canonical_head.fork_choice_read_lock(); let fork_choice = chain.canonical_head.fork_choice_read_lock();
let finalized_checkpoint = fork_choice.cached_fork_choice_view().finalized_checkpoint; let finalized_checkpoint = fork_choice.cached_fork_choice_view().finalized_checkpoint;
@@ -277,5 +304,9 @@ pub fn checkpoint_slot_and_execution_optimistic<T: BeaconChainTypes>(
.map_err(BeaconChainError::ForkChoiceError) .map_err(BeaconChainError::ForkChoiceError)
.map_err(warp_utils::reject::unhandled_error)?; .map_err(warp_utils::reject::unhandled_error)?;
Ok((slot, execution_optimistic)) let block = fork_choice.get_block(&checkpoint.root).ok_or_else(|| {
warp_utils::reject::custom_not_found(format!("Block {:?} not found", checkpoint.root))
})?;
Ok((block, execution_optimistic))
} }

View File

@@ -125,7 +125,15 @@ impl fmt::Display for BlockId {
pub enum StateId { pub enum StateId {
Head, Head,
Genesis, Genesis,
/// Pre-gloas the finalized state is the checkpoint block state
/// advanced to the epoch boundary.
/// Post-gloas this state is always the checkpoint post-block state and is not advanced
/// to the epoch boundary.
Finalized, Finalized,
/// Pre-gloas the justified state is the checkpoint block state
/// advanced to the epoch boundary.
/// Post-gloas this state is always the checkpoint post-block state and is not advanced
/// to the epoch boundary.
Justified, Justified,
Slot(Slot), Slot(Slot),
Root(Hash256), Root(Hash256),