Relax requirements that a checkpoint state must be epoch aligned post-gloas

This commit is contained in:
Eitan Seri- Levi
2026-04-04 00:16:09 -07:00
parent 27af0ed82c
commit 5472c300dc
6 changed files with 90 additions and 8 deletions

View File

@@ -172,8 +172,9 @@ where
let mut anchor_state = anchor.beacon_state;
let mut anchor_block_header = anchor_state.latest_block_header().clone();
// The anchor state MUST be on an epoch boundary (it should be advanced by the caller).
if !anchor_state
// Pre-gloas the anchor state MUST be on an epoch boundary (it should be advanced by the caller).
// Post-gloas this requirement is relaxed.
if !anchor_state.fork_name_unchecked().gloas_enabled() && !anchor_state
.slot()
.as_u64()
.is_multiple_of(E::slots_per_epoch())

View File

@@ -42,6 +42,7 @@ use store::{Error as StoreError, HotColdDB, ItemStore, KeyValueStoreOp};
use task_executor::{ShutdownReason, TaskExecutor};
use tracing::{debug, error, info, warn};
use tree_hash::TreeHash;
use types::StatePayloadStatus;
use types::data::CustodyIndex;
use types::{
BeaconBlock, BeaconState, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecarList,
@@ -433,9 +434,15 @@ where
.clone()
.ok_or("weak_subjectivity_state requires a store")?;
// Ensure the state is advanced to an epoch boundary.
// Pre-gloas ensure the state is advanced to an epoch boundary.
// Post-gloas checkpoint states are always pending (post-block) and cannot
// be advanced across epoch boundaries without first checking for a payload
// envelope.
let slots_per_epoch = E::slots_per_epoch();
if weak_subj_state.slot() % slots_per_epoch != 0 {
if !weak_subj_state.fork_name_unchecked().gloas_enabled()
&& weak_subj_state.slot() % slots_per_epoch != 0
{
debug!(
state_slot = %weak_subj_state.slot(),
block_slot = %weak_subj_block.slot(),
@@ -568,7 +575,7 @@ where
// Write the state, block and blobs non-atomically, it doesn't matter if they're forgotten
// about on a crash restart.
store
.update_finalized_state(
.set_initial_finalized_state(
weak_subj_state_root,
weak_subj_block_root,
weak_subj_state.clone(),
@@ -617,7 +624,15 @@ where
.map_err(|e| format!("Failed to initialize data column info: {:?}", e))?,
);
// TODO(gloas): add check that checkpoint state is Pending
if weak_subj_state.fork_name_unchecked().gloas_enabled()
&& weak_subj_state.payload_status() != StatePayloadStatus::Pending
{
return Err(format!(
"Checkpoint sync state must be Pending (post-block) for Gloas, got {:?}",
weak_subj_state.payload_status()
));
}
let snapshot = BeaconSnapshot {
beacon_block_root: weak_subj_block_root,
execution_envelope: None,