Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- Added `StoreReplica` gRPC service with endpoints for streaming blocks and proofs ([#1987](https://github.com/0xMiden/node/pull/1987)).
- Replaced the network monitor's JavaScript dashboard with a server-rendered Maud + HTMX frontend ([#2024](https://github.com/0xMiden/node/pull/2024)).
- [BREAKING] Removed `CheckNullifiers` endpoint ([#2049](https://github.com/0xMiden/node/pull/2049)).
- [BREAKING] `BlockRange.block_to` is now required for all RPC endpoints ([#2056](https://github.com/0xMiden/node/pull/2056)).

## v0.14.10 (2026-05-29)

Expand Down
22 changes: 16 additions & 6 deletions bin/stress-test/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,17 @@ pub async fn bench_sync_notes(data_directory: PathBuf, iterations: usize, concur

wait_for_store(&store_client).await.unwrap();

// Get the latest block number to determine the range
let status = store_client.clone().status(()).await.unwrap().into_inner();
let chain_tip = status.chain_tip;

// each request will have `ACCOUNTS_PER_SYNC_NOTES` note tags and will be sent with block number
// 0.
let request = |_| {
let mut client = store_client.clone();
let account_batch: Vec<AccountId> =
account_ids.by_ref().take(ACCOUNTS_PER_SYNC_NOTES).collect();
tokio::spawn(async move { sync_notes(&mut client, account_batch).await })
tokio::spawn(async move { sync_notes(&mut client, account_batch, chain_tip).await })
};

// create a stream of tasks to send the requests
Expand All @@ -82,13 +86,14 @@ pub async fn bench_sync_notes(data_directory: PathBuf, iterations: usize, concur
pub async fn sync_notes(
api_client: &mut RpcClient<InterceptedService<Channel, OtelInterceptor>>,
account_ids: Vec<AccountId>,
chain_tip: u32,
) -> Duration {
let note_tags = account_ids
.iter()
.map(|id| u32::from(NoteTag::with_account_target(*id)))
.collect::<Vec<_>>();
let sync_request = proto::rpc::SyncNotesRequest {
block_range: Some(proto::rpc::BlockRange { block_from: 0, block_to: None }),
block_range: Some(proto::rpc::BlockRange { block_from: 0, block_to: chain_tip }),
note_tags,
};

Expand Down Expand Up @@ -128,6 +133,10 @@ pub async fn bench_sync_nullifiers(
.map(|a| AccountId::from_hex(a).unwrap())
.collect();

// Get the latest block number to determine the range
let status = store_client.clone().status(()).await.unwrap().into_inner();
Comment thread
kkovaacs marked this conversation as resolved.
let chain_tip = status.chain_tip;

// Get all nullifier prefixes from the store using sync_notes
let mut nullifier_prefixes: Vec<u32> = vec![];
let mut current_block_num = 0;
Expand All @@ -140,7 +149,7 @@ pub async fn bench_sync_nullifiers(
let sync_request = proto::rpc::SyncNotesRequest {
block_range: Some(proto::rpc::BlockRange {
block_from: current_block_num,
block_to: None,
block_to: chain_tip,
}),
note_tags,
};
Expand Down Expand Up @@ -191,7 +200,7 @@ pub async fn bench_sync_nullifiers(

let nullifiers_batch: Vec<u32> = nullifiers.by_ref().take(prefixes_per_request).collect();

tokio::spawn(async move { sync_nullifiers(&mut client, nullifiers_batch).await })
tokio::spawn(async move { sync_nullifiers(&mut client, nullifiers_batch, chain_tip).await })
};

// Create a stream of tasks to send the requests
Expand All @@ -216,9 +225,10 @@ pub async fn bench_sync_nullifiers(
async fn sync_nullifiers(
api_client: &mut RpcClient<InterceptedService<Channel, OtelInterceptor>>,
nullifiers_prefixes: Vec<u32>,
chain_tip: u32,
) -> (Duration, proto::rpc::SyncNullifiersResponse) {
let sync_request = proto::rpc::SyncNullifiersRequest {
block_range: Some(proto::rpc::BlockRange { block_from: 0, block_to: None }),
block_range: Some(proto::rpc::BlockRange { block_from: 0, block_to: chain_tip }),
nullifiers: nullifiers_prefixes,
prefix_len: 16,
};
Expand Down Expand Up @@ -345,7 +355,7 @@ pub async fn sync_transactions(
.collect::<Vec<_>>();

let sync_request = proto::rpc::SyncTransactionsRequest {
block_range: Some(proto::rpc::BlockRange { block_from, block_to: Some(block_to) }),
block_range: Some(proto::rpc::BlockRange { block_from, block_to }),
account_ids,
};

Expand Down
11 changes: 3 additions & 8 deletions crates/proto/src/domain/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,16 +380,11 @@ pub enum InvalidBlockRange {
}

impl proto::rpc::BlockRange {
/// Converts the block range into an inclusive range, using the fallback block number if the
/// block to is not specified.
/// Converts the block range into an inclusive range.
pub fn into_inclusive_range<T: From<InvalidBlockRange>>(
self,
fallback: &BlockNumber,
) -> Result<RangeInclusive<BlockNumber>, T> {
let block_range = RangeInclusive::new(
self.block_from.into(),
self.block_to.map_or(*fallback, BlockNumber::from),
);
let block_range = RangeInclusive::new(self.block_from.into(), self.block_to.into());

if block_range.start() > block_range.end() {
return Err(InvalidBlockRange::StartGreaterThanEnd {
Expand All @@ -415,7 +410,7 @@ impl From<RangeInclusive<BlockNumber>> for proto::rpc::BlockRange {
fn from(range: RangeInclusive<BlockNumber>) -> Self {
Self {
block_from: range.start().as_u32(),
block_to: Some(range.end().as_u32()),
block_to: range.end().as_u32(),
}
}
}
10 changes: 5 additions & 5 deletions crates/rpc/src/server/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ impl api_server::Api for RpcService {

let span = Span::current();
span.set_attribute("block_range.from", range.block_from);
span.set_attribute("block_range.to", range.block_to());
span.set_attribute("block_range.to", range.block_to);

debug!(target: COMPONENT, request = ?request.get_ref());

Expand Down Expand Up @@ -309,7 +309,7 @@ impl api_server::Api for RpcService {

let span = Span::current();
span.set_attribute("block_range.from", range.block_from);
span.set_attribute("block_range.to", range.block_to());
span.set_attribute("block_range.to", range.block_to);
debug!(target: COMPONENT, request = ?request.get_ref());

check::<QueryParamNoteTagLimit>(request.get_ref().note_tags.len())?;
Expand Down Expand Up @@ -364,7 +364,7 @@ impl api_server::Api for RpcService {
let span = Span::current();
span.set_attribute("account.id", account_id);
span.set_attribute("block_range.from", range.block_from);
span.set_attribute("block_range.to", range.block_to());
span.set_attribute("block_range.to", range.block_to);

debug!(target: COMPONENT, request = ?request.get_ref());

Expand All @@ -385,7 +385,7 @@ impl api_server::Api for RpcService {
let span = Span::current();
span.set_attribute("account.id", account_id);
span.set_attribute("block_range.from", range.block_from);
span.set_attribute("block_range.to", range.block_to());
span.set_attribute("block_range.to", range.block_to);

debug!(target: COMPONENT, request = ?request.get_ref());

Expand Down Expand Up @@ -618,7 +618,7 @@ impl api_server::Api for RpcService {

let span = Span::current();
span.set_attribute("block_range.from", range.block_from);
span.set_attribute("block_range.to", range.block_to());
span.set_attribute("block_range.to", range.block_to);
span.set_attribute("account.ids", format!("{account_ids:?}").as_str());
span.set_attribute("account.ids.count", n_accounts);

Expand Down
4 changes: 2 additions & 2 deletions crates/store/src/server/ntx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,16 @@ impl ntx_builder_server::NtxBuilder for StoreApi {
) -> Result<Response<proto::store::NetworkAccountIdList>, Status> {
let request = request.into_inner();

let mut chain_tip = self.state.chain_tip(Finality::Committed).await;
let block_range =
read_block_range::<GetNetworkAccountIdsError>(Some(request), "GetNetworkAccountIds")?
.into_inclusive_range::<GetNetworkAccountIdsError>(&chain_tip)?;
.into_inclusive_range::<GetNetworkAccountIdsError>()?;

let (account_ids, mut last_block_included) =
self.state.get_all_network_accounts(block_range).await.map_err(internal_error)?;

let account_ids = Vec::from_iter(account_ids.into_iter().map(Into::into));

let mut chain_tip = self.state.chain_tip(Finality::Committed).await;
if last_block_included > chain_tip {
last_block_included = chain_tip;
}
Expand Down
27 changes: 16 additions & 11 deletions crates/store/src/server/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ impl rpc_server::Rpc for StoreApi {
// Validate nullifier prefix list size before querying state.
check::<QueryParamNullifierPrefixLimit>(request.nullifiers.len())?;

let chain_tip = self.state.chain_tip(Finality::Committed).await;
let block_range =
read_block_range::<SyncNullifiersError>(request.block_range, "SyncNullifiersRequest")?
.into_inclusive_range::<SyncNullifiersError>(&chain_tip)?;
.into_inclusive_range::<SyncNullifiersError>()?;

let (nullifiers, block_num) = self
.state
Expand All @@ -88,6 +87,8 @@ impl rpc_server::Rpc for StoreApi {
})
.collect();

let chain_tip = self.state.chain_tip(Finality::Committed).await;

Ok(Response::new(proto::rpc::SyncNullifiersResponse {
pagination_info: Some(proto::rpc::PaginationInfo {
chain_tip: chain_tip.as_u32(),
Expand All @@ -104,10 +105,11 @@ impl rpc_server::Rpc for StoreApi {
) -> Result<Response<proto::rpc::SyncNotesResponse>, Status> {
let request = request.into_inner();

let chain_tip = self.state.chain_tip(Finality::Committed).await;
let block_range =
read_block_range::<NoteSyncError>(request.block_range, "SyncNotesRequest")?
.into_inclusive_range::<NoteSyncError>(&chain_tip)?;
.into_inclusive_range::<NoteSyncError>()?;

let chain_tip = self.state.chain_tip(Finality::Committed).await;
if *block_range.end() > chain_tip {
Err(NoteSyncError::FutureBlock { chain_tip, block_to: *block_range.end() })?;
}
Expand Down Expand Up @@ -171,7 +173,7 @@ impl rpc_server::Rpc for StoreApi {
Ok(Response::new(proto::rpc::SyncChainMmrResponse {
block_range: Some(proto::rpc::BlockRange {
block_from: block_range.start().as_u32(),
block_to: Some(block_range.end().as_u32()),
block_to: block_range.end().as_u32(),
}),
mmr_delta: Some(mmr_delta.into()),
block_header: Some(block_header.into()),
Expand Down Expand Up @@ -249,7 +251,6 @@ impl rpc_server::Rpc for StoreApi {
request: Request<proto::rpc::SyncAccountVaultRequest>,
) -> Result<Response<proto::rpc::SyncAccountVaultResponse>, Status> {
let request = request.into_inner();
let chain_tip = self.state.chain_tip(Finality::Committed).await;

let account_id: AccountId = read_account_id::<
proto::rpc::SyncAccountVaultRequest,
Expand All @@ -264,7 +265,7 @@ impl rpc_server::Rpc for StoreApi {
request.block_range,
"SyncAccountVaultRequest",
)?
.into_inclusive_range::<SyncAccountVaultError>(&chain_tip)?;
.into_inclusive_range::<SyncAccountVaultError>()?;

let (last_included_block, updates) = self
.state
Expand All @@ -284,6 +285,8 @@ impl rpc_server::Rpc for StoreApi {
})
.collect();

let chain_tip = self.state.chain_tip(Finality::Committed).await;

Ok(Response::new(proto::rpc::SyncAccountVaultResponse {
pagination_info: Some(proto::rpc::PaginationInfo {
chain_tip: chain_tip.as_u32(),
Expand Down Expand Up @@ -311,12 +314,11 @@ impl rpc_server::Rpc for StoreApi {
Err(SyncAccountStorageMapsError::AccountNotPublic(account_id))?;
}

let chain_tip = self.state.chain_tip(Finality::Committed).await;
let block_range = read_block_range::<SyncAccountStorageMapsError>(
request.block_range,
"SyncAccountStorageMapsRequest",
)?
.into_inclusive_range::<SyncAccountStorageMapsError>(&chain_tip)?;
.into_inclusive_range::<SyncAccountStorageMapsError>()?;

let storage_maps_page = self
.state
Expand All @@ -335,6 +337,8 @@ impl rpc_server::Rpc for StoreApi {
})
.collect();

let chain_tip = self.state.chain_tip(Finality::Committed).await;

Ok(Response::new(proto::rpc::SyncAccountStorageMapsResponse {
pagination_info: Some(proto::rpc::PaginationInfo {
chain_tip: chain_tip.as_u32(),
Expand Down Expand Up @@ -383,12 +387,11 @@ impl rpc_server::Rpc for StoreApi {

let request = request.into_inner();

let chain_tip = self.state.chain_tip(Finality::Committed).await;
let block_range = read_block_range::<SyncTransactionsError>(
request.block_range,
"SyncTransactionsRequest",
)?
.into_inclusive_range::<SyncTransactionsError>(&chain_tip)?;
.into_inclusive_range::<SyncTransactionsError>()?;

let account_ids: Vec<AccountId> =
read_account_ids::<SyncTransactionsError, _>(request.account_ids)?;
Expand All @@ -409,6 +412,8 @@ impl rpc_server::Rpc for StoreApi {
.map(crate::db::TransactionRecord::into_proto)
.collect();

let chain_tip = self.state.chain_tip(Finality::Committed).await;

Ok(Response::new(proto::rpc::SyncTransactionsResponse {
pagination_info: Some(proto::rpc::PaginationInfo {
chain_tip: chain_tip.as_u32(),
Expand Down
2 changes: 1 addition & 1 deletion proto/proto/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ message BlockRange {
fixed32 block_from = 1;

// Block number up to which to check (inclusive). If not specified, checks up to the latest block.
optional fixed32 block_to = 2;
fixed32 block_to = 2;
Comment thread
kkovaacs marked this conversation as resolved.
Outdated
}

// PAGINATION INFO
Expand Down
Loading