From b0b7bf1cbbb9573afcce723840277c23d49a8628 Mon Sep 17 00:00:00 2001 From: Karl <214665535+karl-dz@users.noreply.github.com> Date: Wed, 26 Nov 2025 14:31:46 -0600 Subject: [PATCH 1/3] fix iterator --- crates/sentinel/src/client/solana.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/sentinel/src/client/solana.rs b/crates/sentinel/src/client/solana.rs index 65980d6e..5eaf1790 100644 --- a/crates/sentinel/src/client/solana.rs +++ b/crates/sentinel/src/client/solana.rs @@ -369,12 +369,15 @@ impl Iterator for PreviousEpochSlots { type Item = u64; fn next(&mut self) -> Option { - let result = self.current; - if self.current < self.step { - return None; + let next_slot = self.current; + + if self.current == 0 { + None + } else { + self.current = self.current.saturating_sub(self.step); + + Some(next_slot) } - self.current -= self.step; - Some(result) } } From df88c6dfb6e24c8d0efb7d3cd59d509ae7875296 Mon Sep 17 00:00:00 2001 From: Karl <214665535+karl-dz@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:01:19 -0600 Subject: [PATCH 2/3] clean up struct --- crates/sentinel/src/client/solana.rs | 37 +++++++++------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/crates/sentinel/src/client/solana.rs b/crates/sentinel/src/client/solana.rs index 5eaf1790..aab240a7 100644 --- a/crates/sentinel/src/client/solana.rs +++ b/crates/sentinel/src/client/solana.rs @@ -45,6 +45,8 @@ use crate::{AccessId, Error, Result, new_transaction}; const ACCESS_REQUEST_ACCOUNT_INDEX: usize = 2; +const SLOTS_PER_EPOCH: u64 = 432_000; + #[automock] #[async_trait] pub trait SolRpcClientType { @@ -281,9 +283,9 @@ impl SolRpcClient { validator_id: &Pubkey, previous_leader_epochs: u8, ) -> Result { - let latest_slot = self.client.get_slot().await?; + let epoch_slots = self.client.get_slot().await.map(PreviousEpochSlots)?; - for slot in PreviousEpochSlots::new(latest_slot).take(previous_leader_epochs as usize) { + for slot in epoch_slots.take(previous_leader_epochs as usize) { let config = RpcLeaderScheduleConfig { identity: Some(validator_id.to_string()), ..Default::default() @@ -348,35 +350,20 @@ fn is_request_access_instruction(ix: &CompiledInstruction, static_account_keys: == PassportInstructionData::REQUEST_ACCESS } -pub struct PreviousEpochSlots { - current: u64, - step: u64, -} - -impl PreviousEpochSlots { - // Number of slots per epoch - const SLOTS_PER_EPOCH: u64 = 432_000; - - pub fn new(start: u64) -> Self { - Self { - current: start, - step: Self::SLOTS_PER_EPOCH, - } - } -} +struct PreviousEpochSlots(u64); impl Iterator for PreviousEpochSlots { type Item = u64; fn next(&mut self) -> Option { - let next_slot = self.current; + let next_slot = &mut self.0; - if self.current == 0 { + if *next_slot == 0 { None } else { - self.current = self.current.saturating_sub(self.step); - - Some(next_slot) + let current_slot = *next_slot; + *next_slot = next_slot.saturating_sub(SLOTS_PER_EPOCH); + Some(current_slot) } } } @@ -389,14 +376,14 @@ mod test { fn test_reverse_iter() { let start_slot = 2_000_000; let num_epochs = 4; - let epoch_slots = PreviousEpochSlots::new(start_slot) + let epoch_slots = PreviousEpochSlots(start_slot) .take(num_epochs) .collect::>(); assert_eq!(epoch_slots.len(), 4); assert_eq!(epoch_slots.first().unwrap(), &start_slot); assert_eq!( epoch_slots.last().unwrap(), - &(start_slot - 3 * PreviousEpochSlots::SLOTS_PER_EPOCH), + &(start_slot - 3 * SLOTS_PER_EPOCH), ); } } From ed463d504e0b14f92da85024e0743df2a782c140 Mon Sep 17 00:00:00 2001 From: Karl <214665535+karl-dz@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:18:52 -0600 Subject: [PATCH 3/3] update CHANGELOG --- crates/sentinel/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/sentinel/CHANGELOG.md b/crates/sentinel/CHANGELOG.md index c44df3ea..26a9ff93 100644 --- a/crates/sentinel/CHANGELOG.md +++ b/crates/sentinel/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- fix(sentinel): improve previous epoch slot evaluation ([#213](https://github.com/doublezerofoundation/doublezero-offchain/pull/213)) + ## [0.2.2](https://github.com/doublezerofoundation/doublezero-offchain/releases/tag/sentinel/v0.2.2) - 2025-11-11 - fix(sentinel): retry on conn reset, one more time [#184](https://github.com/doublezerofoundation/doublezero-offchain/pull/184)