Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bin/stress-test/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
36 changes: 36 additions & 0 deletions crates/proto/src/domain/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<proto::rpc::sync_chain_mmr_request::UpperBound> for SyncTarget {
type Error = ConversionError;

fn try_from(
value: proto::rpc::sync_chain_mmr_request::UpperBound,
) -> Result<Self, Self::Error> {
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
// ================================================================================================

Expand Down
6 changes: 4 additions & 2 deletions crates/rpc/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
39 changes: 15 additions & 24 deletions crates/store/src/server/rpc_api.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -169,37 +168,29 @@ 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::<proto::rpc::SyncChainMmrRequest>("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()
.await
.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 =
Expand Down
38 changes: 19 additions & 19 deletions proto/proto/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Comment on lines +523 to +528
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the recommended way to emulate sum types in protobuf?

Haven't seen bool used as a placeholder before - what happens if they're manually set to false?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value of the boolean is ignored

        match value {
            UpperBound::BlockNum(block_num) => Ok(Self::BlockNumber(block_num.into())),
            UpperBound::CommittedChainTip(_) => Ok(Self::CommittedChainTip),
            UpperBound::ProvenChainTip(_) => Ok(Self::ProvenChainTip),
        }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know. But since these are numbered fields, and protobuf default inits fields at the receiver, what actually happens if I send last_proven = false -- does it not still get last_committed = false.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely sure. Depends on what the generator does under the hood but I thought better to change oneof + enum anyway.


reserved 4;
}

// Represents the result of syncing chain MMR.
Expand Down
Loading