Skip to content
Merged
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
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
4 changes: 2 additions & 2 deletions proto/proto/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,8 @@ message BlockRange {
// Block number from which to start (inclusive).
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;
// Block number up to which to check (inclusive).
fixed32 block_to = 2;
}

// PAGINATION INFO
Expand Down
Loading