From 9176561236ee6aeca576298ee753d8d3e43c0311 Mon Sep 17 00:00:00 2001 From: rajgoesout Date: Fri, 28 Nov 2025 14:01:40 +0530 Subject: [PATCH] Set epoch schedule sysvar to match mainnet in surfnet init Fixes https://github.com/txtx/surfpool/issues/434 --- crates/core/src/surfnet/locker.rs | 53 +++++++++++++++++++++++++------ crates/core/src/surfnet/remote.rs | 5 +++ crates/core/src/surfnet/svm.rs | 4 +++ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/crates/core/src/surfnet/locker.rs b/crates/core/src/surfnet/locker.rs index 0dcc7d95..11f41664 100644 --- a/crates/core/src/surfnet/locker.rs +++ b/crates/core/src/surfnet/locker.rs @@ -34,6 +34,7 @@ use solana_client::{ use solana_clock::{Clock, Slot, UnixTimestamp}; use solana_commitment_config::{CommitmentConfig, CommitmentLevel}; use solana_epoch_info::EpochInfo; +use solana_epoch_schedule::EpochSchedule; use solana_hash::Hash; use solana_loader_v3_interface::{get_program_data_address, state::UpgradeableLoaderState}; use solana_message::{ @@ -205,23 +206,30 @@ impl SurfnetSvmLocker { do_profile_instructions: bool, log_bytes_limit: Option, ) -> SurfpoolResult { - let mut epoch_info = if let Some(remote_client) = remote_ctx { - remote_client.get_epoch_info().await? + let (mut epoch_info, epoch_schedule) = if let Some(remote_client) = remote_ctx { + let epoch_info = remote_client.get_epoch_info().await?; + let epoch_schedule = remote_client.get_epoch_schedule().await?; + (epoch_info, epoch_schedule) } else { - EpochInfo { - epoch: 0, - slot_index: 0, - slots_in_epoch: 0, - absolute_slot: FINALIZATION_SLOT_THRESHOLD, - block_height: FINALIZATION_SLOT_THRESHOLD, - transaction_count: None, - } + let epoch_schedule = EpochSchedule::without_warmup(); + ( + EpochInfo { + epoch: 0, + slot_index: 0, + slots_in_epoch: epoch_schedule.slots_per_epoch, + absolute_slot: FINALIZATION_SLOT_THRESHOLD, + block_height: FINALIZATION_SLOT_THRESHOLD, + transaction_count: None, + }, + epoch_schedule, + ) }; epoch_info.transaction_count = None; self.with_svm_writer(|svm_writer| { svm_writer.initialize( epoch_info.clone(), + epoch_schedule.clone(), slot_time, remote_ctx, do_profile_instructions, @@ -3303,6 +3311,7 @@ mod tests { use solana_account::Account; use solana_account_decoder::UiAccountEncoding; + use solana_epoch_schedule::EpochSchedule; use super::*; use crate::{ @@ -3845,4 +3854,28 @@ mod tests { ); assert!(result.is_err()); } + + #[tokio::test(flavor = "multi_thread")] + async fn initializes_epoch_schedule_without_warmup_when_offline() { + let (surfnet_svm, _simnet_events_rx, _geyser_events_rx) = SurfnetSvm::new(); + let svm_locker = SurfnetSvmLocker::new(surfnet_svm); + + svm_locker + .initialize(400, &None, false, None) + .await + .expect("initialize should succeed"); + + let epoch_schedule = + svm_locker.with_svm_reader(|svm_reader| svm_reader.inner.get_sysvar::()); + + assert!( + !epoch_schedule.warmup, + "offline initialization should disable warmup to match mainnet" + ); + assert_eq!( + epoch_schedule.get_first_slot_in_epoch(886), + 886_u64 * 432_000, + "first slot should align with mainnet epoch boundaries when warmup is disabled" + ); + } } diff --git a/crates/core/src/surfnet/remote.rs b/crates/core/src/surfnet/remote.rs index c87f75f5..45f2dd1b 100644 --- a/crates/core/src/surfnet/remote.rs +++ b/crates/core/src/surfnet/remote.rs @@ -19,6 +19,7 @@ use solana_client::{ use solana_clock::Slot; use solana_commitment_config::CommitmentConfig; use solana_epoch_info::EpochInfo; +use solana_epoch_schedule::EpochSchedule; use solana_hash::Hash; use solana_loader_v3_interface::get_program_data_address; use solana_pubkey::Pubkey; @@ -90,6 +91,10 @@ impl SurfnetRemoteClient { self.client.get_epoch_info().await.map_err(Into::into) } + pub async fn get_epoch_schedule(&self) -> SurfpoolResult { + self.client.get_epoch_schedule().await.map_err(Into::into) + } + pub async fn get_account( &self, pubkey: &Pubkey, diff --git a/crates/core/src/surfnet/svm.rs b/crates/core/src/surfnet/svm.rs index 27571485..efcec51b 100644 --- a/crates/core/src/surfnet/svm.rs +++ b/crates/core/src/surfnet/svm.rs @@ -47,6 +47,7 @@ use solana_client::{ use solana_clock::{Clock, Slot}; use solana_commitment_config::{CommitmentConfig, CommitmentLevel}; use solana_epoch_info::EpochInfo; +use solana_epoch_schedule::EpochSchedule; use solana_feature_gate_interface::Feature; use solana_genesis_config::GenesisConfig; use solana_hash::Hash; @@ -500,6 +501,7 @@ impl SurfnetSvm { pub fn initialize( &mut self, epoch_info: EpochInfo, + epoch_schedule: EpochSchedule, slot_time: u64, remote_ctx: &Option, do_profile_instructions: bool, @@ -518,6 +520,8 @@ impl SurfnetSvm { self.register_idl(template.idl, None); } + self.inner.set_sysvar(&epoch_schedule); + if let Some(remote_client) = remote_ctx { let _ = self .simnet_events_tx