From 6976431c3500107e7ef526958020e3623541a1b9 Mon Sep 17 00:00:00 2001 From: sergerad Date: Mon, 30 Mar 2026 13:37:50 +1300 Subject: [PATCH 1/5] update upper bound logic for SyncChainMmrRequest --- bin/stress-test/src/store/mod.rs | 4 ++-- crates/proto/src/domain/block.rs | 30 ++++++++++++++++++++++++ crates/rpc/src/tests.rs | 4 ++-- crates/store/src/server/rpc_api.rs | 37 ++++++++++++------------------ proto/proto/rpc.proto | 35 +++++++++++----------------- 5 files changed, 63 insertions(+), 47 deletions(-) diff --git a/bin/stress-test/src/store/mod.rs b/bin/stress-test/src/store/mod.rs index 2f3862bca..ee92204d1 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 6383c255d..fedfb26ec 100644 --- a/crates/proto/src/domain/block.rs +++ b/crates/proto/src/domain/block.rs @@ -358,6 +358,36 @@ 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). + LastCommitted, + /// Sync up to the latest proven block. + LastProven, +} + +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::LastCommitted(_) => Ok(Self::LastCommitted), + UpperBound::LastProven(_) => Ok(Self::LastProven), + } + } +} + // BLOCK RANGE // ================================================================================================ diff --git a/crates/rpc/src/tests.rs b/crates/rpc/src/tests.rs index 8ed9524f8..0f6a8f52b 100644 --- a/crates/rpc/src/tests.rs +++ b/crates/rpc/src/tests.rs @@ -607,8 +607,8 @@ 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::LastCommitted(true)), }; 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 2ef33295e..ee1d46a7e 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::MissingFieldHelper; +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::{ @@ -161,15 +160,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(|| proto::rpc::SyncChainMmrRequest::missing_field(stringify!(block_range))) - .map_err(SyncChainMmrError::DeserializationFailed)?; + let block_from = BlockNumber::from(request.block_from); - // 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 + // 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::LastCommitted); + + let block_to = match sync_target { + SyncTarget::BlockNumber(block_num) => block_num.min(chain_tip), + SyncTarget::LastCommitted => chain_tip, + SyncTarget::LastProven => self .state .db() .select_latest_proven_in_sequence_block_num() @@ -177,19 +181,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 2823083d5..b5a570ddc 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -492,30 +492,23 @@ 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; -} - // 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; + reserved 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 effective tip. + fixed32 block_num = 3; + // Sync up to the latest committed block (chain tip). + bool last_committed = 4; + // Sync up to the latest proven block. + bool last_proven = 5; + } } // Represents the result of syncing chain MMR. From 36cd5aab6b4838f027eabb1d2115a5d553310a69 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 31 Mar 2026 10:58:41 +1300 Subject: [PATCH 2/5] Fix effective tip comment --- proto/proto/rpc.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/proto/rpc.proto b/proto/proto/rpc.proto index b5a570ddc..0b559883e 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -502,7 +502,7 @@ message SyncChainMmrRequest { // 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 effective tip. + // Sync up to this specific block number (inclusive), clamped to the committed chain tip. fixed32 block_num = 3; // Sync up to the latest committed block (chain tip). bool last_committed = 4; From 07599d3040b292c463c348f50a1b5ceb897adee4 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 31 Mar 2026 11:00:02 +1300 Subject: [PATCH 3/5] RM reserved 2 --- proto/proto/rpc.proto | 2 -- 1 file changed, 2 deletions(-) diff --git a/proto/proto/rpc.proto b/proto/proto/rpc.proto index 0b559883e..b44b48095 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -498,8 +498,6 @@ message SyncChainMmrRequest { // already present in the caller's MMR so the delta begins at the next block. fixed32 block_from = 1; - reserved 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. From 58d09d2af6789abb141b5014163b58eb7eb15266 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 31 Mar 2026 11:04:18 +1300 Subject: [PATCH 4/5] rename proto fields --- crates/proto/src/domain/block.rs | 8 ++++---- crates/rpc/src/tests.rs | 2 +- crates/store/src/server/rpc_api.rs | 6 +++--- proto/proto/rpc.proto | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/proto/src/domain/block.rs b/crates/proto/src/domain/block.rs index fedfb26ec..76f8f278b 100644 --- a/crates/proto/src/domain/block.rs +++ b/crates/proto/src/domain/block.rs @@ -367,9 +367,9 @@ pub enum SyncTarget { /// Sync up to a specific block number (inclusive). BlockNumber(BlockNumber), /// Sync up to the latest committed block (chain tip). - LastCommitted, + CommittedChainTip, /// Sync up to the latest proven block. - LastProven, + ProvenChainTip, } impl TryFrom for SyncTarget { @@ -382,8 +382,8 @@ impl TryFrom for SyncTarget { match value { UpperBound::BlockNum(block_num) => Ok(Self::BlockNumber(block_num.into())), - UpperBound::LastCommitted(_) => Ok(Self::LastCommitted), - UpperBound::LastProven(_) => Ok(Self::LastProven), + UpperBound::CommittedChainTip(_) => Ok(Self::CommittedChainTip), + UpperBound::ProvenChainTip(_) => Ok(Self::ProvenChainTip), } } } diff --git a/crates/rpc/src/tests.rs b/crates/rpc/src/tests.rs index 0f6a8f52b..51e521a18 100644 --- a/crates/rpc/src/tests.rs +++ b/crates/rpc/src/tests.rs @@ -608,7 +608,7 @@ async fn sync_chain_mmr_returns_delta() { let request = proto::rpc::SyncChainMmrRequest { block_from: 0, - upper_bound: Some(proto::rpc::sync_chain_mmr_request::UpperBound::LastCommitted(true)), + upper_bound: Some(proto::rpc::sync_chain_mmr_request::UpperBound::CommittedChainTip(true)), }; 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 ee1d46a7e..fc37449c4 100644 --- a/crates/store/src/server/rpc_api.rs +++ b/crates/store/src/server/rpc_api.rs @@ -168,12 +168,12 @@ impl rpc_server::Rpc for StoreApi { .map(SyncTarget::try_from) .transpose() .map_err(SyncChainMmrError::DeserializationFailed)? - .unwrap_or(SyncTarget::LastCommitted); + .unwrap_or(SyncTarget::CommittedChainTip); let block_to = match sync_target { SyncTarget::BlockNumber(block_num) => block_num.min(chain_tip), - SyncTarget::LastCommitted => chain_tip, - SyncTarget::LastProven => self + SyncTarget::CommittedChainTip => chain_tip, + SyncTarget::ProvenChainTip => self .state .db() .select_latest_proven_in_sequence_block_num() diff --git a/proto/proto/rpc.proto b/proto/proto/rpc.proto index b44b48095..76d4c1681 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -503,9 +503,9 @@ message SyncChainMmrRequest { // Sync up to this specific block number (inclusive), clamped to the committed chain tip. fixed32 block_num = 3; // Sync up to the latest committed block (chain tip). - bool last_committed = 4; + bool committed_chain_tip = 4; // Sync up to the latest proven block. - bool last_proven = 5; + bool proven_chain_tip = 5; } } From 6e7f7cd856088e9a7c446d4e0219171427b31de9 Mon Sep 17 00:00:00 2001 From: sergerad Date: Wed, 1 Apr 2026 10:46:19 +1300 Subject: [PATCH 5/5] chain tip unspecified --- crates/proto/src/domain/block.rs | 10 ++++++++-- crates/rpc/src/tests.rs | 4 +++- proto/proto/rpc.proto | 19 ++++++++++++++----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/crates/proto/src/domain/block.rs b/crates/proto/src/domain/block.rs index 76f8f278b..99cd29d8c 100644 --- a/crates/proto/src/domain/block.rs +++ b/crates/proto/src/domain/block.rs @@ -382,8 +382,14 @@ impl TryFrom for SyncTarget { match value { UpperBound::BlockNum(block_num) => Ok(Self::BlockNumber(block_num.into())), - UpperBound::CommittedChainTip(_) => Ok(Self::CommittedChainTip), - UpperBound::ProvenChainTip(_) => Ok(Self::ProvenChainTip), + 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), + Ok(proto::rpc::ChainTip::Unspecified) | Err(_) => { + // TODO(currentpr): conversion error + Err(ConversionError::NotAValidFelt) + }, + }, } } } diff --git a/crates/rpc/src/tests.rs b/crates/rpc/src/tests.rs index 51e521a18..c1c81994c 100644 --- a/crates/rpc/src/tests.rs +++ b/crates/rpc/src/tests.rs @@ -608,7 +608,9 @@ async fn sync_chain_mmr_returns_delta() { let request = proto::rpc::SyncChainMmrRequest { block_from: 0, - upper_bound: Some(proto::rpc::sync_chain_mmr_request::UpperBound::CommittedChainTip(true)), + 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/proto/proto/rpc.proto b/proto/proto/rpc.proto index 76d4c1681..dc581f3dc 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -492,6 +492,15 @@ message SyncNotesResponse { // SYNC CHAIN MMR // ================================================================================================ +// 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 number from which to synchronize (inclusive). Set this to the last block @@ -501,12 +510,12 @@ message SyncChainMmrRequest { // 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 = 3; - // Sync up to the latest committed block (chain tip). - bool committed_chain_tip = 4; - // Sync up to the latest proven block. - bool proven_chain_tip = 5; + 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.