diff --git a/crates/core/src/rpc/full.rs b/crates/core/src/rpc/full.rs index 43f6f688..8996998d 100644 --- a/crates/core/src/rpc/full.rs +++ b/crates/core/src/rpc/full.rs @@ -3382,6 +3382,33 @@ mod tests { ); } + #[tokio::test(flavor = "multi_thread")] + async fn test_get_block_respects_confirmed_commitment_visibility() { + let setup = TestSetup::new(SurfpoolFullRpc); + + setup.context.svm_locker.with_svm_writer(|svm_writer| { + svm_writer.latest_epoch_info.absolute_slot = 10; + }); + + let res = setup + .rpc + .get_block( + Some(setup.context), + 10, + Some(RpcEncodingConfigWrapper::Current(Some(RpcBlockConfig { + commitment: Some(CommitmentConfig::confirmed()), + ..RpcBlockConfig::default() + }))), + ) + .await + .unwrap(); + + assert!( + res.is_none(), + "A confirmed getBlock request should not expose a slot newer than the confirmed slot" + ); + } + #[test_case(TransactionVersion::Legacy(Legacy::Legacy) ; "Legacy transactions")] #[test_case(TransactionVersion::Number(0) ; "V0 transactions")] #[tokio::test(flavor = "multi_thread")] diff --git a/crates/core/src/surfnet/locker.rs b/crates/core/src/surfnet/locker.rs index 33a3767f..fb4f6d70 100644 --- a/crates/core/src/surfnet/locker.rs +++ b/crates/core/src/surfnet/locker.rs @@ -3049,6 +3049,18 @@ impl SurfnetSvmLocker { slot: &Slot, config: &RpcBlockConfig, ) -> SurfpoolContextualizedResult> { + let committed_slot = self.get_slot_for_commitment(&config.commitment.unwrap_or_default()); + if *slot > committed_slot { + return Ok(SvmAccessContext { + slot: committed_slot, + latest_epoch_info: self.get_epoch_info(), + latest_blockhash: self + .get_latest_blockhash(&CommitmentConfig::processed()) + .unwrap_or_default(), + inner: None, + }); + } + let first_local_slot = self.get_first_local_slot(); let result = if first_local_slot.is_some() && first_local_slot.unwrap() > *slot {