diff --git a/crates/blockchain/src/lib.rs b/crates/blockchain/src/lib.rs index dc4f1268..98961c91 100644 --- a/crates/blockchain/src/lib.rs +++ b/crates/blockchain/src/lib.rs @@ -1413,7 +1413,7 @@ impl Handler for BlockChainServer { // Early aggregation only advances the current slot's group counts, so a // late- or future-slot attestation can never cross the threshold; skip // the check unless this attestation is for the store's current slot. - let current_slot = self.store.time().expect("store time exists") / INTERVALS_PER_SLOT; + let current_slot = self.store.current_slot(); if msg.attestation.data.slot == current_slot { self.maybe_start_early_aggregation(ctx).await; } diff --git a/crates/blockchain/src/store.rs b/crates/blockchain/src/store.rs index 5f2a4657..0d3b3cdd 100644 --- a/crates/blockchain/src/store.rs +++ b/crates/blockchain/src/store.rs @@ -348,7 +348,7 @@ pub fn on_tick(store: &mut Store, timestamp_ms: u64, has_proposal: bool) { .set_time(store.time().unwrap() + 1) .expect("set_time should succeed"); - let slot = store.time().unwrap() / INTERVALS_PER_SLOT; + let slot = store.current_slot(); let interval = SlotInterval::from_intervals_since_genesis(store.time().unwrap()); trace!(%slot, ?interval, "processing tick"); @@ -637,7 +637,7 @@ fn on_block_core( // Horizon is the current slot plus one whole slot of margin, so an intended // early block still imports (mirrors the attestation future-slot guard, but // with a whole-slot rather than one-interval margin). - let current_slot = store.time().expect("DB read should succeed") / INTERVALS_PER_SLOT; + let current_slot = store.current_slot(); if slot > current_slot + 1 { return Err(StoreError::BlockTooFarInFuture { block_slot: slot, diff --git a/crates/storage/src/store.rs b/crates/storage/src/store.rs index 626cbf2e..51934e73 100644 --- a/crates/storage/src/store.rs +++ b/crates/storage/src/store.rs @@ -14,6 +14,7 @@ use ethlambda_types::{ Block, BlockBody, BlockHeader, MultiMessageAggregate, SignedBlock, SingleMessageAggregate, }, checkpoint::Checkpoint, + constants::INTERVALS_PER_SLOT, genesis::GenesisConfig, primitives::{H256, HashTreeRoot as _}, state::{ChainConfig, State, anchor_pair_is_consistent}, @@ -817,9 +818,8 @@ impl Store { /// Returns the current store time in interval counts since genesis. /// - /// Each increment represents one 800ms interval. Derive slot/interval as: - /// slot = time() / INTERVALS_PER_SLOT - /// interval = time() % INTERVALS_PER_SLOT + /// Each increment represents one 800ms interval. Use [`Self::current_slot`] + /// for the slot; the interval within it is `time() % INTERVALS_PER_SLOT`. pub fn time(&self) -> Result { self.get_metadata(KEY_TIME) } @@ -829,6 +829,11 @@ impl Store { self.set_metadata(KEY_TIME, &time) } + /// The current slot, derived from the store clock. + pub fn current_slot(&self) -> u64 { + self.time().expect("store time exists") / INTERVALS_PER_SLOT + } + // ============ Config ============ /// Returns the chain configuration.