diff --git a/bin/stress-test/src/store/mod.rs b/bin/stress-test/src/store/mod.rs index 7c68b025e..cedd3e23a 100644 --- a/bin/stress-test/src/store/mod.rs +++ b/bin/stress-test/src/store/mod.rs @@ -469,8 +469,8 @@ async fn sync_chain_mmr( block_to: u32, ) -> SyncChainMmrRun { let sync_request = proto::rpc::SyncChainMmrRequest { - block_range: Some(proto::rpc::BlockRange { block_from, block_to: Some(block_to) }), - finality: proto::rpc::Finality::Committed.into(), + block_from, + upper_bound: Some(proto::rpc::sync_chain_mmr_request::UpperBound::BlockNum(block_to)), }; let start = Instant::now(); diff --git a/crates/proto/src/domain/block.rs b/crates/proto/src/domain/block.rs index 7f2646db0..19a4bf8bf 100644 --- a/crates/proto/src/domain/block.rs +++ b/crates/proto/src/domain/block.rs @@ -332,6 +332,42 @@ impl From<&FeeParameters> for proto::blockchain::FeeParameters { } } +// SYNC TARGET +// ================================================================================================ + +/// The target block to sync up to in a chain MMR sync request. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SyncTarget { + /// Sync up to a specific block number (inclusive). + BlockNumber(BlockNumber), + /// Sync up to the latest committed block (chain tip). + CommittedChainTip, + /// Sync up to the latest proven block. + ProvenChainTip, +} + +impl TryFrom for SyncTarget { + type Error = ConversionError; + + fn try_from( + value: proto::rpc::sync_chain_mmr_request::UpperBound, + ) -> Result { + use proto::rpc::sync_chain_mmr_request::UpperBound; + + match value { + UpperBound::BlockNum(block_num) => Ok(Self::BlockNumber(block_num.into())), + UpperBound::ChainTip(tip) => match proto::rpc::ChainTip::try_from(tip) { + Ok(proto::rpc::ChainTip::Committed) => Ok(Self::CommittedChainTip), + Ok(proto::rpc::ChainTip::Proven) => Ok(Self::ProvenChainTip), + // These variants should never be encountered. + Ok(proto::rpc::ChainTip::Unspecified) | Err(_) => { + Err(ConversionError::message("unexpected chain tip")) + }, + }, + } + } +} + // BLOCK RANGE // ================================================================================================ diff --git a/crates/rpc/src/tests.rs b/crates/rpc/src/tests.rs index 8ed9524f8..c1c81994c 100644 --- a/crates/rpc/src/tests.rs +++ b/crates/rpc/src/tests.rs @@ -607,8 +607,10 @@ async fn sync_chain_mmr_returns_delta() { let (store_runtime, _data_directory, _genesis, _store_addr) = start_store(store_listener).await; let request = proto::rpc::SyncChainMmrRequest { - block_range: Some(proto::rpc::BlockRange { block_from: 0, block_to: None }), - finality: proto::rpc::Finality::Committed.into(), + block_from: 0, + upper_bound: Some(proto::rpc::sync_chain_mmr_request::UpperBound::ChainTip( + proto::rpc::ChainTip::Committed.into(), + )), }; let response = rpc_client.sync_chain_mmr(request).await.expect("sync_chain_mmr should succeed"); let response = response.into_inner(); diff --git a/crates/store/src/server/rpc_api.rs b/crates/store/src/server/rpc_api.rs index 38dd9f9f4..58d0c55d8 100644 --- a/crates/store/src/server/rpc_api.rs +++ b/crates/store/src/server/rpc_api.rs @@ -1,6 +1,5 @@ use miden_node_proto::convert; -use miden_node_proto::domain::block::InvalidBlockRange; -use miden_node_proto::errors::ConversionError; +use miden_node_proto::domain::block::SyncTarget; use miden_node_proto::generated::store::rpc_server; use miden_node_proto::generated::{self as proto}; use miden_node_utils::limiter::{ @@ -169,17 +168,20 @@ impl rpc_server::Rpc for StoreApi { let request = request.into_inner(); let chain_tip = self.state.latest_block_num().await; - let block_range = request - .block_range - .ok_or_else(|| { - ConversionError::missing_field::("block_range") - }) - .map_err(SyncChainMmrError::DeserializationFailed)?; + let block_from = BlockNumber::from(request.block_from); + + // Determine upper bound to sync to or default to last committed block. + let sync_target = request + .upper_bound + .map(SyncTarget::try_from) + .transpose() + .map_err(SyncChainMmrError::DeserializationFailed)? + .unwrap_or(SyncTarget::CommittedChainTip); - // Determine the effective tip based on the requested finality level. - let effective_tip = match request.finality() { - proto::rpc::Finality::Unspecified | proto::rpc::Finality::Committed => chain_tip, - proto::rpc::Finality::Proven => self + let block_to = match sync_target { + SyncTarget::BlockNumber(block_num) => block_num.min(chain_tip), + SyncTarget::CommittedChainTip => chain_tip, + SyncTarget::ProvenChainTip => self .state .db() .select_latest_proven_in_sequence_block_num() @@ -187,19 +189,8 @@ impl rpc_server::Rpc for StoreApi { .map_err(SyncChainMmrError::DatabaseError)?, }; - let block_from = BlockNumber::from(block_range.block_from); - if block_from > effective_tip { - Err(SyncChainMmrError::FutureBlock { chain_tip: effective_tip, block_from })?; - } - - let block_to = - block_range.block_to.map_or(effective_tip, BlockNumber::from).min(effective_tip); - if block_from > block_to { - Err(SyncChainMmrError::InvalidBlockRange(InvalidBlockRange::StartGreaterThanEnd { - start: block_from, - end: block_to, - }))?; + Err(SyncChainMmrError::FutureBlock { chain_tip: block_to, block_from })?; } let block_range = block_from..=block_to; let mmr_delta = diff --git a/proto/proto/rpc.proto b/proto/proto/rpc.proto index 26dcbd8ac..d03e7f4db 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -504,30 +504,30 @@ message SyncNotesResponse { // SYNC CHAIN MMR // ================================================================================================ -// The finality level for chain data queries. -enum Finality { - // Return data up to the latest committed block. - FINALITY_UNSPECIFIED = 0; - // Return data up to the latest committed block. - FINALITY_COMMITTED = 1; - // Return data only up to the latest proven block. - FINALITY_PROVEN = 2; +// The chain tip variant to sync up to. +enum ChainTip { + CHAIN_TIP_UNSPECIFIED = 0; + // Sync up to the latest committed block (chain tip). + CHAIN_TIP_COMMITTED = 1; + // Sync up to the latest proven block. + CHAIN_TIP_PROVEN = 2; } // Chain MMR synchronization request. message SyncChainMmrRequest { - // Block range from which to synchronize the chain MMR. - // - // The response will contain MMR delta starting after `block_range.block_from` up to - // `block_range.block_to` or the effective tip (whichever is lower). Set `block_from` to the - // last block already present in the caller's MMR so the delta begins at the next block. - BlockRange block_range = 1; + // Block number from which to synchronize (inclusive). Set this to the last block + // already present in the caller's MMR so the delta begins at the next block. + fixed32 block_from = 1; - // The finality level to use when clamping the upper bound of the block range. - // - // When set to `FINALITY_UNSPECIFIED` or `FINALITY_COMMITTED`, the upper bound is clamped to the chain tip. - // When set to `FINALITY_PROVEN`, the upper bound is clamped to the latest proven block. - Finality finality = 2; + // Upper bound for the block range. Determines how far ahead to sync. + oneof upper_bound { + // Sync up to this specific block number (inclusive), clamped to the committed chain tip. + fixed32 block_num = 2; + // Sync up to a chain tip variant (committed or proven). + ChainTip chain_tip = 3; + } + + reserved 4; } // Represents the result of syncing chain MMR.