From 5267cbf103f0584b4683422008fd19de8ded5fff Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Fri, 9 Jan 2026 12:45:24 -0300 Subject: [PATCH 01/18] chore: decouple ntx builder --- CHANGELOG.md | 1 + bin/node/src/commands/block_producer.rs | 3 - bin/node/src/commands/bundled.rs | 13 ----- crates/block-producer/src/server/mod.rs | 15 +---- crates/ntx-builder/src/builder.rs | 74 ++++++++++++++----------- crates/ntx-builder/src/store.rs | 35 +++++++----- 6 files changed, 68 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f93bb299d..aa9161865 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Added `GetLimits` endpoint to the RPC server ([#1410](https://github.com/0xMiden/miden-node/pull/1410)). - Added gRPC-Web probe support to the `miden-network-monitor` binary ([#1484](https://github.com/0xMiden/miden-node/pull/1484)). - Add DB schema change check ([#1268](https://github.com/0xMiden/miden-node/pull/1485)). +- Decoupled ntx-builder from block-producer startup by loading network accounts asynchronously via a background task ([#????](https://github.com/0xMiden/miden-node/pull/????)). ### Changes diff --git a/bin/node/src/commands/block_producer.rs b/bin/node/src/commands/block_producer.rs index d50182d87..5cfbc78fc 100644 --- a/bin/node/src/commands/block_producer.rs +++ b/bin/node/src/commands/block_producer.rs @@ -1,10 +1,8 @@ -use std::sync::Arc; use std::time::Duration; use anyhow::Context; use miden_node_block_producer::BlockProducer; use miden_node_utils::grpc::UrlExt; -use tokio::sync::Barrier; use url::Url; use super::{ENV_BLOCK_PRODUCER_URL, ENV_STORE_BLOCK_PRODUCER_URL}; @@ -93,7 +91,6 @@ impl BlockProducerCommand { block_interval: block_producer.block_interval, max_txs_per_batch: block_producer.max_txs_per_batch, max_batches_per_block: block_producer.max_batches_per_block, - production_checkpoint: Arc::new(Barrier::new(1)), grpc_timeout, mempool_tx_capacity: block_producer.mempool_tx_capacity, } diff --git a/bin/node/src/commands/bundled.rs b/bin/node/src/commands/bundled.rs index 594959aa4..3ad01013d 100644 --- a/bin/node/src/commands/bundled.rs +++ b/bin/node/src/commands/bundled.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; use std::path::PathBuf; -use std::sync::Arc; use std::time::Duration; use anyhow::Context; @@ -14,7 +13,6 @@ use miden_protocol::block::BlockSigner; use miden_protocol::crypto::dsa::ecdsa_k256_keccak::SecretKey; use miden_protocol::utils::Deserializable; use tokio::net::TcpListener; -use tokio::sync::Barrier; use tokio::task::JoinSet; use url::Url; @@ -222,19 +220,11 @@ impl BundledCommand { }) .id(); - // A sync point between the ntx-builder and block-producer components. let should_start_ntx_builder = !ntx_builder.disabled; - let checkpoint = if should_start_ntx_builder { - Barrier::new(2) - } else { - Barrier::new(1) - }; - let checkpoint = Arc::new(checkpoint); // Start block-producer. The block-producer's endpoint is available after loading completes. let block_producer_id = join_set .spawn({ - let checkpoint = Arc::clone(&checkpoint); let store_url = Url::parse(&format!("http://{store_block_producer_address}")) .context("Failed to parse URL")?; let validator_url = Url::parse(&format!("http://{validator_address}")) @@ -250,7 +240,6 @@ impl BundledCommand { block_interval: block_producer.block_interval, max_batches_per_block: block_producer.max_batches_per_block, max_txs_per_batch: block_producer.max_txs_per_batch, - production_checkpoint: checkpoint, grpc_timeout, mempool_tx_capacity: block_producer.mempool_tx_capacity, } @@ -320,8 +309,6 @@ impl BundledCommand { store_ntx_builder_url, block_producer_url, ntx_builder.tx_prover_url, - ntx_builder.ticker_interval, - checkpoint, ntx_builder.script_cache_size, ) .run() diff --git a/crates/block-producer/src/server/mod.rs b/crates/block-producer/src/server/mod.rs index e4f8edfcc..16e06ee3e 100644 --- a/crates/block-producer/src/server/mod.rs +++ b/crates/block-producer/src/server/mod.rs @@ -18,7 +18,7 @@ use miden_protocol::block::BlockNumber; use miden_protocol::transaction::ProvenTransaction; use miden_protocol::utils::serde::Deserializable; use tokio::net::TcpListener; -use tokio::sync::{Barrier, Mutex, RwLock}; +use tokio::sync::{Mutex, RwLock}; use tokio_stream::wrappers::{ReceiverStream, TcpListenerStream}; use tonic::Status; use tower_http::trace::TraceLayer; @@ -65,11 +65,6 @@ pub struct BlockProducer { pub max_txs_per_batch: usize, /// The maximum number of batches per block. pub max_batches_per_block: usize, - /// Block production only begins after this checkpoint barrier completes. - /// - /// The block-producers gRPC endpoint will be available before this point, so this lets the - /// mempool synchronize its event stream without risking a race condition. - pub production_checkpoint: Arc, /// Server-side timeout for an individual gRPC request. /// /// If the handler takes longer than this duration, the server cancels the call. @@ -155,12 +150,7 @@ impl BlockProducer { // any complete or fail, we can shutdown the rest (somewhat) gracefully. let mut tasks = tokio::task::JoinSet::new(); - // Launch the gRPC server and wait at the checkpoint for any other components to be in sync. - // - // This is used to ensure the ntx-builder can subscribe to the mempool events without - // playing catch up caused by block-production. - // - // This is a temporary work-around until the ntx-builder can resync on the fly. + // Launch the gRPC server. let rpc_id = tasks .spawn({ let mempool = mempool.clone(); @@ -171,7 +161,6 @@ impl BlockProducer { } }) .id(); - self.production_checkpoint.wait().await; let batch_builder_id = tasks .spawn({ diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index 3d0a00aab..df168b094 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -1,6 +1,5 @@ use std::num::NonZeroUsize; use std::sync::Arc; -use std::time::Duration; use anyhow::Context; use futures::TryStreamExt; @@ -8,13 +7,13 @@ use miden_node_proto::domain::account::NetworkAccountPrefix; use miden_node_proto::domain::mempool::MempoolEvent; use miden_node_utils::lru_cache::LruCache; use miden_protocol::Word; +use miden_protocol::account::AccountId; use miden_protocol::account::delta::AccountUpdateDetails; use miden_protocol::block::BlockHeader; use miden_protocol::crypto::merkle::mmr::PartialMmr; use miden_protocol::note::NoteScript; use miden_protocol::transaction::PartialBlockchain; -use tokio::sync::{Barrier, RwLock}; -use tokio::time; +use tokio::sync::{RwLock, mpsc}; use url::Url; use crate::MAX_IN_PROGRESS_TXS; @@ -76,13 +75,6 @@ pub struct NetworkTransactionBuilder { /// Address of the remote prover. If `None`, transactions will be proven locally, which is /// undesirable due to the performance impact. tx_prover_url: Option, - /// Interval for checking pending notes and executing network transactions. - ticker_interval: Duration, - /// A checkpoint used to sync start-up process with the block-producer. - /// - /// This informs the block-producer when we have subscribed to mempool events and that it is - /// safe to begin block-production. - bp_checkpoint: Arc, /// Shared LRU cache for storing retrieved note scripts to avoid repeated store calls. /// This cache is shared across all account actors. script_cache: LruCache, @@ -91,13 +83,16 @@ pub struct NetworkTransactionBuilder { } impl NetworkTransactionBuilder { + /// Channel capacity for account loading. Each item in the channel is a batch of account IDs + /// loaded from a single page. A small capacity is sufficient since each page can contain + /// up to ~289,000 accounts. + const ACCOUNT_CHANNEL_CAPACITY: usize = 4; + /// Creates a new instance of the network transaction builder. pub fn new( store_url: Url, block_producer_url: Url, tx_prover_url: Option, - ticker_interval: Duration, - bp_checkpoint: Arc, script_cache_size: NonZeroUsize, ) -> Self { let script_cache = LruCache::new(script_cache_size); @@ -106,8 +101,6 @@ impl NetworkTransactionBuilder { store_url, block_producer_url, tx_prover_url, - ticker_interval, - bp_checkpoint, script_cache, coordinator, } @@ -127,15 +120,6 @@ impl NetworkTransactionBuilder { .await .context("failed to subscribe to mempool events")?; - // Unlock the block-producer's block production. The block-producer is prevented from - // producing blocks until we have subscribed to mempool events. - // - // This is a temporary work-around until the ntx-builder can resync on the fly. - self.bp_checkpoint.wait().await; - - let mut interval = tokio::time::interval(self.ticker_interval); - interval.set_missed_tick_behavior(time::MissedTickBehavior::Skip); - // Create chain state that will be updated by the coordinator and read by actors. let chain_state = Arc::new(RwLock::new(ChainState::new(chain_tip_header, chain_mmr))); @@ -147,15 +131,16 @@ impl NetworkTransactionBuilder { script_cache: self.script_cache.clone(), }; - // Create initial set of actors based on all known network accounts. - let account_ids = store.get_network_account_ids().await?; - for account_id in account_ids { - if let Ok(account_prefix) = NetworkAccountPrefix::try_from(account_id) { - self.coordinator - .spawn_actor(AccountOrigin::store(account_prefix), &actor_context) - .await?; + // Spawn a background task to load network accounts from the store. + // Accounts are sent through a channel in batches and processed in the main event loop. + let (account_tx, mut account_rx) = + mpsc::channel::>(Self::ACCOUNT_CHANNEL_CAPACITY); + let account_loader_store = store.clone(); + tokio::spawn(async move { + if let Err(err) = account_loader_store.stream_network_account_ids(account_tx).await { + tracing::error!(%err, "failed to load network accounts from store"); } - } + }); // Main loop which manages actors and passes mempool events to them. loop { @@ -176,8 +161,35 @@ impl NetworkTransactionBuilder { chain_state.clone(), ).await?; }, + // Handle account batches loaded from the store. + // Once all accounts are loaded, the channel closes and this branch + // becomes inactive (recv returns None and we stop matching). + Some(account_ids) = account_rx.recv() => { + self.handle_loaded_accounts(account_ids, &actor_context).await?; + }, + } + } + } + + /// Handles a batch of account IDs loaded from the store by spawning actors for them. + #[tracing::instrument( + name = "ntx.builder.handle_loaded_accounts", + skip(self, account_ids, actor_context), + fields(count = account_ids.len()) + )] + async fn handle_loaded_accounts( + &mut self, + account_ids: Vec, + actor_context: &AccountActorContext, + ) -> Result<(), anyhow::Error> { + for account_id in account_ids { + if let Ok(account_prefix) = NetworkAccountPrefix::try_from(account_id) { + self.coordinator + .spawn_actor(AccountOrigin::store(account_prefix), actor_context) + .await?; } } + Ok(()) } /// Handles mempool events by sending them to actors via the coordinator and/or spawning new diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 447571a5a..4153cc530 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -173,21 +173,24 @@ impl StoreClient { Ok(all_notes) } - /// Get all network account IDs. + /// Streams network account IDs to the provided sender, page-by-page. /// - /// Since the `GetNetworkAccountIds` method is paginated, we loop through all pages until we - /// reach the end. + /// This method is designed to be run in a background task, sending accounts to the main event + /// loop as they are loaded. This allows the ntx-builder to start processing mempool events + /// without waiting for all accounts to be preloaded. /// /// Each page can return up to `MAX_RESPONSE_PAYLOAD_BYTES / AccountId::SERIALIZED_SIZE` - /// accounts (~289,000). With `100_000` iterations, which is assumed to be sufficient for the - /// foreseeable future. - #[instrument(target = COMPONENT, name = "store.client.get_network_account_ids", skip_all, err)] - pub async fn get_network_account_ids(&self) -> Result, StoreError> { - const MAX_ITERATIONS: u32 = 100_000; + /// accounts (~289,000). With 1000 iterations, this supports up to ~524 million network + /// accounts, which is assumed to be sufficient for the foreseeable future. + #[instrument(target = COMPONENT, name = "store.client.stream_network_account_ids", skip_all, err)] + pub async fn stream_network_account_ids( + &self, + sender: tokio::sync::mpsc::Sender>, + ) -> Result<(), StoreError> { + const MAX_ITERATIONS: u32 = 1000; let mut block_range = BlockNumber::from(0)..=BlockNumber::from(u32::MAX); - let mut ids = Vec::new(); let mut iterations_count = 0; loop { @@ -198,14 +201,14 @@ impl StoreClient { .await? .into_inner(); - let accounts: Result, ConversionError> = response + let accounts = response .account_ids .into_iter() .map(|account_id| { AccountId::read_from_bytes(&account_id.id) .map_err(|err| ConversionError::deserialization_error("account_id", err)) }) - .collect(); + .collect::, ConversionError>>()?; let pagination_info = response.pagination_info.ok_or( ConversionError::MissingFieldInProtobufRepresentation { @@ -214,7 +217,13 @@ impl StoreClient { }, )?; - ids.extend(accounts?); + if !accounts.is_empty() { + // Send the entire batch at once. If the receiver is dropped, stop loading. + if sender.send(accounts).await.is_err() { + return Ok(()); + } + } + iterations_count += 1; block_range = BlockNumber::from(pagination_info.block_num)..=BlockNumber::from(u32::MAX); @@ -228,7 +237,7 @@ impl StoreClient { } } - Ok(ids) + Ok(()) } #[instrument(target = COMPONENT, name = "store.client.get_note_script_by_root", skip_all, err)] From 2c0a1b2b151ef89b03364c6e20a7a889b2bd781c Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Mon, 12 Jan 2026 17:18:47 -0300 Subject: [PATCH 02/18] review: send one account at a time --- crates/ntx-builder/src/builder.rs | 23 ++++++++++------------- crates/ntx-builder/src/store.rs | 6 +++--- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index df168b094..624eede73 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -134,7 +134,7 @@ impl NetworkTransactionBuilder { // Spawn a background task to load network accounts from the store. // Accounts are sent through a channel in batches and processed in the main event loop. let (account_tx, mut account_rx) = - mpsc::channel::>(Self::ACCOUNT_CHANNEL_CAPACITY); + mpsc::channel::(Self::ACCOUNT_CHANNEL_CAPACITY); let account_loader_store = store.clone(); tokio::spawn(async move { if let Err(err) = account_loader_store.stream_network_account_ids(account_tx).await { @@ -164,8 +164,8 @@ impl NetworkTransactionBuilder { // Handle account batches loaded from the store. // Once all accounts are loaded, the channel closes and this branch // becomes inactive (recv returns None and we stop matching). - Some(account_ids) = account_rx.recv() => { - self.handle_loaded_accounts(account_ids, &actor_context).await?; + Some(account_id) = account_rx.recv() => { + self.handle_loaded_account(account_id, &actor_context).await?; }, } } @@ -174,20 +174,17 @@ impl NetworkTransactionBuilder { /// Handles a batch of account IDs loaded from the store by spawning actors for them. #[tracing::instrument( name = "ntx.builder.handle_loaded_accounts", - skip(self, account_ids, actor_context), - fields(count = account_ids.len()) + skip(self, account_id, actor_context) )] - async fn handle_loaded_accounts( + async fn handle_loaded_account( &mut self, - account_ids: Vec, + account_id: AccountId, actor_context: &AccountActorContext, ) -> Result<(), anyhow::Error> { - for account_id in account_ids { - if let Ok(account_prefix) = NetworkAccountPrefix::try_from(account_id) { - self.coordinator - .spawn_actor(AccountOrigin::store(account_prefix), actor_context) - .await?; - } + if let Ok(account_prefix) = NetworkAccountPrefix::try_from(account_id) { + self.coordinator + .spawn_actor(AccountOrigin::store(account_prefix), actor_context) + .await?; } Ok(()) } diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 4153cc530..1635bcc81 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -185,7 +185,7 @@ impl StoreClient { #[instrument(target = COMPONENT, name = "store.client.stream_network_account_ids", skip_all, err)] pub async fn stream_network_account_ids( &self, - sender: tokio::sync::mpsc::Sender>, + sender: tokio::sync::mpsc::Sender, ) -> Result<(), StoreError> { const MAX_ITERATIONS: u32 = 1000; @@ -217,9 +217,9 @@ impl StoreClient { }, )?; - if !accounts.is_empty() { + for account in accounts { // Send the entire batch at once. If the receiver is dropped, stop loading. - if sender.send(accounts).await.is_err() { + if sender.send(account).await.is_err() { return Ok(()); } } From 9ff989d04377c6682fdf61cc72bdab2e1298edfb Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Mon, 12 Jan 2026 17:32:43 -0300 Subject: [PATCH 03/18] review: increase channel capacity, remove pagination reference --- crates/ntx-builder/src/builder.rs | 6 ++---- crates/ntx-builder/src/store.rs | 6 +----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index 624eede73..877555e01 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -83,10 +83,8 @@ pub struct NetworkTransactionBuilder { } impl NetworkTransactionBuilder { - /// Channel capacity for account loading. Each item in the channel is a batch of account IDs - /// loaded from a single page. A small capacity is sufficient since each page can contain - /// up to ~289,000 accounts. - const ACCOUNT_CHANNEL_CAPACITY: usize = 4; + /// Channel capacity for account loading. + const ACCOUNT_CHANNEL_CAPACITY: usize = 100_000; /// Creates a new instance of the network transaction builder. pub fn new( diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 1635bcc81..16d433700 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -173,15 +173,11 @@ impl StoreClient { Ok(all_notes) } - /// Streams network account IDs to the provided sender, page-by-page. + /// Streams network account IDs to the provided sender. /// /// This method is designed to be run in a background task, sending accounts to the main event /// loop as they are loaded. This allows the ntx-builder to start processing mempool events /// without waiting for all accounts to be preloaded. - /// - /// Each page can return up to `MAX_RESPONSE_PAYLOAD_BYTES / AccountId::SERIALIZED_SIZE` - /// accounts (~289,000). With 1000 iterations, this supports up to ~524 million network - /// accounts, which is assumed to be sufficient for the foreseeable future. #[instrument(target = COMPONENT, name = "store.client.stream_network_account_ids", skip_all, err)] pub async fn stream_network_account_ids( &self, From cd08232a2d9b77ac3315047f5359bf6e35495f92 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Mon, 12 Jan 2026 18:04:52 -0300 Subject: [PATCH 04/18] review: return NetworkAccountPrefix --- crates/ntx-builder/src/builder.rs | 15 ++++++--------- crates/ntx-builder/src/store.rs | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index 877555e01..aa85d8b1e 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -7,7 +7,6 @@ use miden_node_proto::domain::account::NetworkAccountPrefix; use miden_node_proto::domain::mempool::MempoolEvent; use miden_node_utils::lru_cache::LruCache; use miden_protocol::Word; -use miden_protocol::account::AccountId; use miden_protocol::account::delta::AccountUpdateDetails; use miden_protocol::block::BlockHeader; use miden_protocol::crypto::merkle::mmr::PartialMmr; @@ -132,7 +131,7 @@ impl NetworkTransactionBuilder { // Spawn a background task to load network accounts from the store. // Accounts are sent through a channel in batches and processed in the main event loop. let (account_tx, mut account_rx) = - mpsc::channel::(Self::ACCOUNT_CHANNEL_CAPACITY); + mpsc::channel::(Self::ACCOUNT_CHANNEL_CAPACITY); let account_loader_store = store.clone(); tokio::spawn(async move { if let Err(err) = account_loader_store.stream_network_account_ids(account_tx).await { @@ -172,18 +171,16 @@ impl NetworkTransactionBuilder { /// Handles a batch of account IDs loaded from the store by spawning actors for them. #[tracing::instrument( name = "ntx.builder.handle_loaded_accounts", - skip(self, account_id, actor_context) + skip(self, account_prefix, actor_context) )] async fn handle_loaded_account( &mut self, - account_id: AccountId, + account_prefix: NetworkAccountPrefix, actor_context: &AccountActorContext, ) -> Result<(), anyhow::Error> { - if let Ok(account_prefix) = NetworkAccountPrefix::try_from(account_id) { - self.coordinator - .spawn_actor(AccountOrigin::store(account_prefix), actor_context) - .await?; - } + self.coordinator + .spawn_actor(AccountOrigin::store(account_prefix), actor_context) + .await?; Ok(()) } diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 16d433700..73705441a 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -181,7 +181,7 @@ impl StoreClient { #[instrument(target = COMPONENT, name = "store.client.stream_network_account_ids", skip_all, err)] pub async fn stream_network_account_ids( &self, - sender: tokio::sync::mpsc::Sender, + sender: tokio::sync::mpsc::Sender, ) -> Result<(), StoreError> { const MAX_ITERATIONS: u32 = 1000; @@ -201,10 +201,19 @@ impl StoreClient { .account_ids .into_iter() .map(|account_id| { - AccountId::read_from_bytes(&account_id.id) - .map_err(|err| ConversionError::deserialization_error("account_id", err)) + let account_id = AccountId::read_from_bytes(&account_id.id).map_err(|err| { + StoreError::DeserializationError(ConversionError::deserialization_error( + "account_id", + err, + )) + })?; + NetworkAccountPrefix::try_from(account_id).map_err(|_| { + StoreError::MalformedResponse( + "account id is not a valid network account".into(), + ) + }) }) - .collect::, ConversionError>>()?; + .collect::, StoreError>>()?; let pagination_info = response.pagination_info.ok_or( ConversionError::MissingFieldInProtobufRepresentation { From 5a58026647505cd40425242fa2c3abe70f254e04 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Mon, 12 Jan 2026 18:29:01 -0300 Subject: [PATCH 05/18] review: improve tracing --- crates/ntx-builder/src/store.rs | 115 ++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 73705441a..223fee744 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -178,7 +178,7 @@ impl StoreClient { /// This method is designed to be run in a background task, sending accounts to the main event /// loop as they are loaded. This allows the ntx-builder to start processing mempool events /// without waiting for all accounts to be preloaded. - #[instrument(target = COMPONENT, name = "store.client.stream_network_account_ids", skip_all, err)] + #[instrument(target = COMPONENT, name = "store.client.load_committed_accounts", skip_all, err)] pub async fn stream_network_account_ids( &self, sender: tokio::sync::mpsc::Sender, @@ -190,44 +190,12 @@ impl StoreClient { let mut iterations_count = 0; loop { - let response = self - .inner - .clone() - .get_network_account_ids(Into::::into(block_range.clone())) - .await? - .into_inner(); - - let accounts = response - .account_ids - .into_iter() - .map(|account_id| { - let account_id = AccountId::read_from_bytes(&account_id.id).map_err(|err| { - StoreError::DeserializationError(ConversionError::deserialization_error( - "account_id", - err, - )) - })?; - NetworkAccountPrefix::try_from(account_id).map_err(|_| { - StoreError::MalformedResponse( - "account id is not a valid network account".into(), - ) - }) - }) - .collect::, StoreError>>()?; + let (accounts, pagination_info) = self.fetch_page(block_range.clone()).await?; - let pagination_info = response.pagination_info.ok_or( - ConversionError::MissingFieldInProtobufRepresentation { - entity: "NetworkAccountIdList", - field_name: "pagination_info", - }, - )?; + let chain_tip = pagination_info.chain_tip; + let current_height = pagination_info.block_num; - for account in accounts { - // Send the entire batch at once. If the receiver is dropped, stop loading. - if sender.send(account).await.is_err() { - return Ok(()); - } - } + self.submit_page(accounts, &sender, chain_tip, current_height).await?; iterations_count += 1; block_range = @@ -245,6 +213,79 @@ impl StoreClient { Ok(()) } + #[instrument( + target = COMPONENT, + name = "store.client.fetch_page", + skip_all, + fields(chain_tip, current_height), + err + )] + async fn fetch_page( + &self, + block_range: std::ops::RangeInclusive, + ) -> Result<(Vec, proto::rpc::PaginationInfo), StoreError> { + let response = self + .inner + .clone() + .get_network_account_ids(Into::::into(block_range)) + .await? + .into_inner(); + + let accounts = response + .account_ids + .into_iter() + .map(|account_id| { + let account_id = AccountId::read_from_bytes(&account_id.id).map_err(|err| { + StoreError::DeserializationError(ConversionError::deserialization_error( + "account_id", + err, + )) + })?; + NetworkAccountPrefix::try_from(account_id).map_err(|_| { + StoreError::MalformedResponse( + "account id is not a valid network account".into(), + ) + }) + }) + .collect::, StoreError>>()?; + + let pagination_info = response.pagination_info.ok_or( + ConversionError::MissingFieldInProtobufRepresentation { + entity: "NetworkAccountIdList", + field_name: "pagination_info", + }, + )?; + + tracing::Span::current() + .record("chain_tip", pagination_info.chain_tip) + .record("current_height", pagination_info.block_num); + + Ok((accounts, pagination_info)) + } + + #[instrument( + target = COMPONENT, + name = "store.client.submit_page", + skip(self, accounts, sender), + fields(chain_tip = chain_tip, current_height = current_height) + )] + async fn submit_page( + &self, + accounts: Vec, + sender: &tokio::sync::mpsc::Sender, + chain_tip: u32, + current_height: u32, + ) -> Result<(), StoreError> { + for account in accounts { + // If the receiver is dropped, stop loading. + if sender.send(account).await.is_err() { + return Ok(()); + } + } + + Ok(()) + } + #[instrument(target = COMPONENT, name = "store.client.get_note_script_by_root", skip_all, err)] pub async fn get_note_script_by_root( &self, From 05909a916e65b43670732f89a76608e861215e02 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Mon, 12 Jan 2026 18:35:16 -0300 Subject: [PATCH 06/18] review: add exponential backoff --- crates/ntx-builder/src/store.rs | 34 +++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 223fee744..0400c6858 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -224,12 +224,34 @@ impl StoreClient { &self, block_range: std::ops::RangeInclusive, ) -> Result<(Vec, proto::rpc::PaginationInfo), StoreError> { - let response = self - .inner - .clone() - .get_network_account_ids(Into::::into(block_range)) - .await? - .into_inner(); + let mut retry_counter = 0u32; + + let response = loop { + match self + .inner + .clone() + .get_network_account_ids(Into::::into(block_range.clone())) + .await + { + Ok(response) => break response.into_inner(), + Err(err) => { + // Exponential backoff with base 500ms and max 30s. + let backoff = Duration::from_millis(500) + .saturating_mul(1 << retry_counter) + .min(Duration::from_secs(30)); + + tracing::warn!( + ?backoff, + %retry_counter, + %err, + "store connection failed while fetching committed accounts page, retrying" + ); + + retry_counter += 1; + tokio::time::sleep(backoff).await; + }, + } + }; let accounts = response .account_ids From f15f3131a1784b0f1f6eed05f537f64de62c3bf2 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Mon, 12 Jan 2026 18:37:24 -0300 Subject: [PATCH 07/18] review: remove max iterations --- crates/ntx-builder/src/store.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 0400c6858..7e7350ee6 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -183,12 +183,8 @@ impl StoreClient { &self, sender: tokio::sync::mpsc::Sender, ) -> Result<(), StoreError> { - const MAX_ITERATIONS: u32 = 1000; - let mut block_range = BlockNumber::from(0)..=BlockNumber::from(u32::MAX); - let mut iterations_count = 0; - loop { let (accounts, pagination_info) = self.fetch_page(block_range.clone()).await?; @@ -197,17 +193,12 @@ impl StoreClient { self.submit_page(accounts, &sender, chain_tip, current_height).await?; - iterations_count += 1; block_range = BlockNumber::from(pagination_info.block_num)..=BlockNumber::from(u32::MAX); if pagination_info.block_num >= pagination_info.chain_tip { break; } - - if iterations_count >= MAX_ITERATIONS { - return Err(StoreError::MaxIterationsReached("GetNetworkAccountIds".to_string())); - } } Ok(()) @@ -345,6 +336,4 @@ pub enum StoreError { MalformedResponse(String), #[error("failed to parse response")] DeserializationError(#[from] ConversionError), - #[error("max iterations reached: {0}")] - MaxIterationsReached(String), } From 3103972b8fdd7298a0c76b95a3fcabdd6a4a15fe Mon Sep 17 00:00:00 2001 From: Santiago Pittella <87827390+SantiagoPittella@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:58:17 -0300 Subject: [PATCH 08/18] review: reduce channel capacity Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> --- crates/ntx-builder/src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index aa85d8b1e..c1b901621 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -83,7 +83,7 @@ pub struct NetworkTransactionBuilder { impl NetworkTransactionBuilder { /// Channel capacity for account loading. - const ACCOUNT_CHANNEL_CAPACITY: usize = 100_000; + const ACCOUNT_CHANNEL_CAPACITY: usize = 1_000; /// Creates a new instance of the network transaction builder. pub fn new( From ec652396ef78cb5d75140872f3ed39f457aece1e Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Wed, 14 Jan 2026 12:38:18 -0300 Subject: [PATCH 09/18] review: abort on failure --- crates/ntx-builder/src/builder.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index c1b901621..2998dca39 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -133,11 +133,13 @@ impl NetworkTransactionBuilder { let (account_tx, mut account_rx) = mpsc::channel::(Self::ACCOUNT_CHANNEL_CAPACITY); let account_loader_store = store.clone(); - tokio::spawn(async move { - if let Err(err) = account_loader_store.stream_network_account_ids(account_tx).await { - tracing::error!(%err, "failed to load network accounts from store"); - } + let account_loader_handle = tokio::spawn(async move { + account_loader_store + .stream_network_account_ids(account_tx) + .await + .context("failed to load network accounts from store") }); + let mut account_loader = Some(account_loader_handle); // Main loop which manages actors and passes mempool events to them. loop { @@ -164,6 +166,18 @@ impl NetworkTransactionBuilder { Some(account_id) = account_rx.recv() => { self.handle_loaded_account(account_id, &actor_context).await?; }, + // Handle account loader task completion/failure. + // If the task fails, we abort since the builder would be in a degraded state + // where existing notes against network accounts won't be processed. + Some(result) = async { + match account_loader.as_mut() { + Some(handle) => Some(handle.await), + None => std::future::pending().await, + } + } => { + account_loader = None; + result.context("account loader task panicked")??; + }, } } } From bf5a7b8b639dd34bc07a412a4d7453874cfce340 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Wed, 14 Jan 2026 12:55:28 -0300 Subject: [PATCH 10/18] fix: exponential backoff overflow --- crates/ntx-builder/src/block_producer.rs | 4 ++-- crates/ntx-builder/src/store.rs | 4 ++-- crates/rpc/src/server/api.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ntx-builder/src/block_producer.rs b/crates/ntx-builder/src/block_producer.rs index 7c1af9d8f..77f51903a 100644 --- a/crates/ntx-builder/src/block_producer.rs +++ b/crates/ntx-builder/src/block_producer.rs @@ -65,9 +65,9 @@ impl BlockProducerClient { loop { match self.subscribe_to_mempool(chain_tip).await { Err(err) if err.code() == tonic::Code::Unavailable => { - // exponential backoff with base 500ms and max 30s + // Exponential backoff with base 500ms and max 30s. let backoff = Duration::from_millis(500) - .saturating_mul(1 << retry_counter) + .saturating_mul(1 << retry_counter.min(6)) .min(Duration::from_secs(30)); tracing::warn!( diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 7e7350ee6..bfe4b5319 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -57,7 +57,7 @@ impl StoreClient { Err(StoreError::GrpcClientError(err)) => { // Exponential backoff with base 500ms and max 30s. let backoff = Duration::from_millis(500) - .saturating_mul(1 << retry_counter) + .saturating_mul(1 << retry_counter.min(6)) .min(Duration::from_secs(30)); tracing::warn!( @@ -228,7 +228,7 @@ impl StoreClient { Err(err) => { // Exponential backoff with base 500ms and max 30s. let backoff = Duration::from_millis(500) - .saturating_mul(1 << retry_counter) + .saturating_mul(1 << retry_counter.min(6)) .min(Duration::from_secs(30)); tracing::warn!( diff --git a/crates/rpc/src/server/api.rs b/crates/rpc/src/server/api.rs index 86bb35e59..bd1f0bd52 100644 --- a/crates/rpc/src/server/api.rs +++ b/crates/rpc/src/server/api.rs @@ -131,9 +131,9 @@ impl RpcService { return Ok(header); }, Err(err) if err.code() == tonic::Code::Unavailable => { - // exponential backoff with base 500ms and max 30s + // Exponential backoff with base 500ms and max 30s. let backoff = Duration::from_millis(500) - .saturating_mul(1 << retry_counter) + .saturating_mul(1 << retry_counter.min(6)) .min(Duration::from_secs(30)); tracing::warn!( From c5e8c7dae649f99e29013f24703a8dcaa00c1aa5 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Wed, 14 Jan 2026 13:29:05 -0300 Subject: [PATCH 11/18] review: fix instrumentation --- crates/ntx-builder/src/store.rs | 37 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index bfe4b5319..9afb2c056 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -1,3 +1,4 @@ +use std::ops::RangeInclusive; use std::time::Duration; use miden_node_proto::clients::{Builder, StoreNtxBuilderClient}; @@ -178,30 +179,40 @@ impl StoreClient { /// This method is designed to be run in a background task, sending accounts to the main event /// loop as they are loaded. This allows the ntx-builder to start processing mempool events /// without waiting for all accounts to be preloaded. - #[instrument(target = COMPONENT, name = "store.client.load_committed_accounts", skip_all, err)] pub async fn stream_network_account_ids( &self, sender: tokio::sync::mpsc::Sender, ) -> Result<(), StoreError> { let mut block_range = BlockNumber::from(0)..=BlockNumber::from(u32::MAX); - loop { - let (accounts, pagination_info) = self.fetch_page(block_range.clone()).await?; + while let Some(next_start) = self.load_page(block_range, &sender).await? { + block_range = next_start..=BlockNumber::from(u32::MAX); + } - let chain_tip = pagination_info.chain_tip; - let current_height = pagination_info.block_num; + Ok(()) + } - self.submit_page(accounts, &sender, chain_tip, current_height).await?; + /// Loads a single page of network accounts and submits them to the sender. + /// + /// Returns the next block number to fetch from, or `None` if the chain tip has been reached. + #[instrument(target = COMPONENT, name = "store.client.load_accounts_page", skip_all, err)] + async fn load_page( + &self, + block_range: RangeInclusive, + sender: &tokio::sync::mpsc::Sender, + ) -> Result, StoreError> { + let (accounts, pagination_info) = self.fetch_page(block_range).await?; - block_range = - BlockNumber::from(pagination_info.block_num)..=BlockNumber::from(u32::MAX); + let chain_tip = pagination_info.chain_tip; + let current_height = pagination_info.block_num; - if pagination_info.block_num >= pagination_info.chain_tip { - break; - } - } + self.submit_page(accounts, sender, chain_tip, current_height).await?; - Ok(()) + if current_height >= chain_tip { + Ok(None) + } else { + Ok(Some(BlockNumber::from(current_height))) + } } #[instrument( From 7b2b39204a2ba5ce1fa0f466a3909cb3067eb578 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Tue, 20 Jan 2026 12:28:10 -0300 Subject: [PATCH 12/18] review: add warn! when receiver drops --- crates/ntx-builder/src/store.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 9afb2c056..e8d1fa48b 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -303,6 +303,7 @@ impl StoreClient { for account in accounts { // If the receiver is dropped, stop loading. if sender.send(account).await.is_err() { + tracing::warn!("Account receiver dropped"); return Ok(()); } } From 47697320af8a48afdef0a0d0fdf6853f0130df56 Mon Sep 17 00:00:00 2001 From: Santiago Pittella <87827390+SantiagoPittella@users.noreply.github.com> Date: Tue, 20 Jan 2026 12:30:08 -0300 Subject: [PATCH 13/18] review: flatten double result Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> --- crates/ntx-builder/src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index 2998dca39..e6234b2a6 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -176,7 +176,7 @@ impl NetworkTransactionBuilder { } } => { account_loader = None; - result.context("account loader task panicked")??; + result.context("account loader task panicked").flatten()?; }, } } From 628ecf0edba4aed0b967ed02ea71e37091878150 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Tue, 20 Jan 2026 13:26:33 -0300 Subject: [PATCH 14/18] review: remove Option --- crates/ntx-builder/src/builder.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/ntx-builder/src/builder.rs b/crates/ntx-builder/src/builder.rs index e6234b2a6..7cb692940 100644 --- a/crates/ntx-builder/src/builder.rs +++ b/crates/ntx-builder/src/builder.rs @@ -133,13 +133,12 @@ impl NetworkTransactionBuilder { let (account_tx, mut account_rx) = mpsc::channel::(Self::ACCOUNT_CHANNEL_CAPACITY); let account_loader_store = store.clone(); - let account_loader_handle = tokio::spawn(async move { + let mut account_loader_handle = tokio::spawn(async move { account_loader_store .stream_network_account_ids(account_tx) .await .context("failed to load network accounts from store") }); - let mut account_loader = Some(account_loader_handle); // Main loop which manages actors and passes mempool events to them. loop { @@ -169,14 +168,13 @@ impl NetworkTransactionBuilder { // Handle account loader task completion/failure. // If the task fails, we abort since the builder would be in a degraded state // where existing notes against network accounts won't be processed. - Some(result) = async { - match account_loader.as_mut() { - Some(handle) => Some(handle.await), - None => std::future::pending().await, - } - } => { - account_loader = None; - result.context("account loader task panicked").flatten()?; + result = &mut account_loader_handle => { + result + .context("account loader task panicked") + .flatten()?; + + tracing::info!("account loading from store completed"); + account_loader_handle = tokio::spawn(std::future::pending()); }, } } From 1cdbf264a1995c4967d01b30aae540d0fc29a66f Mon Sep 17 00:00:00 2001 From: Santiago Pittella <87827390+SantiagoPittella@users.noreply.github.com> Date: Tue, 20 Jan 2026 13:27:45 -0300 Subject: [PATCH 15/18] review: remove fields from trace Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> --- crates/ntx-builder/src/store.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index e8d1fa48b..5bad20269 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -290,8 +290,7 @@ impl StoreClient { #[instrument( target = COMPONENT, name = "store.client.submit_page", - skip(self, accounts, sender), - fields(chain_tip = chain_tip, current_height = current_height) + skip_all )] async fn submit_page( &self, From bee1f9e0ecc5c6160c54db3dff59534768b355f6 Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Tue, 20 Jan 2026 14:48:08 -0300 Subject: [PATCH 16/18] review: remove parameters from submit_page --- crates/ntx-builder/src/store.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 5bad20269..6585a3a5a 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -206,7 +206,7 @@ impl StoreClient { let chain_tip = pagination_info.chain_tip; let current_height = pagination_info.block_num; - self.submit_page(accounts, sender, chain_tip, current_height).await?; + self.submit_page(accounts, sender).await?; if current_height >= chain_tip { Ok(None) @@ -215,13 +215,7 @@ impl StoreClient { } } - #[instrument( - target = COMPONENT, - name = "store.client.fetch_page", - skip_all, - fields(chain_tip, current_height), - err - )] + #[instrument(target = COMPONENT, name = "store.client.fetch_page", skip_all, err)] async fn fetch_page( &self, block_range: std::ops::RangeInclusive, @@ -280,10 +274,6 @@ impl StoreClient { }, )?; - tracing::Span::current() - .record("chain_tip", pagination_info.chain_tip) - .record("current_height", pagination_info.block_num); - Ok((accounts, pagination_info)) } @@ -296,8 +286,6 @@ impl StoreClient { &self, accounts: Vec, sender: &tokio::sync::mpsc::Sender, - chain_tip: u32, - current_height: u32, ) -> Result<(), StoreError> { for account in accounts { // If the receiver is dropped, stop loading. From aeefdf6dd04c005e4f140ba1ef79af471699d78b Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Tue, 20 Jan 2026 14:52:08 -0300 Subject: [PATCH 17/18] review: log full errors --- crates/ntx-builder/src/store.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index 6585a3a5a..d89b4fc01 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -8,6 +8,7 @@ use miden_node_proto::errors::ConversionError; use miden_node_proto::generated::rpc::BlockRange; use miden_node_proto::generated::{self as proto}; use miden_node_proto::try_convert; +use miden_node_utils::tracing::OpenTelemetrySpanExt; use miden_protocol::Word; use miden_protocol::account::{Account, AccountId}; use miden_protocol::block::{BlockHeader, BlockNumber}; @@ -201,12 +202,17 @@ impl StoreClient { block_range: RangeInclusive, sender: &tokio::sync::mpsc::Sender, ) -> Result, StoreError> { - let (accounts, pagination_info) = self.fetch_page(block_range).await?; + let (accounts, pagination_info) = self + .fetch_page(block_range) + .await + .inspect_err(|err| tracing::Span::current().set_error(err))?; let chain_tip = pagination_info.chain_tip; let current_height = pagination_info.block_num; - self.submit_page(accounts, sender).await?; + self.submit_page(accounts, sender) + .await + .inspect_err(|err| tracing::Span::current().set_error(err))?; if current_height >= chain_tip { Ok(None) From e76ea6a47c8c8f107df92062e828851df14600ca Mon Sep 17 00:00:00 2001 From: SantiagoPittella Date: Tue, 20 Jan 2026 15:01:14 -0300 Subject: [PATCH 18/18] review: rename submit and fetch page functions --- crates/ntx-builder/src/store.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ntx-builder/src/store.rs b/crates/ntx-builder/src/store.rs index d89b4fc01..5f3ee59c6 100644 --- a/crates/ntx-builder/src/store.rs +++ b/crates/ntx-builder/src/store.rs @@ -203,14 +203,14 @@ impl StoreClient { sender: &tokio::sync::mpsc::Sender, ) -> Result, StoreError> { let (accounts, pagination_info) = self - .fetch_page(block_range) + .fetch_network_account_ids_page(block_range) .await .inspect_err(|err| tracing::Span::current().set_error(err))?; let chain_tip = pagination_info.chain_tip; let current_height = pagination_info.block_num; - self.submit_page(accounts, sender) + self.send_accounts_to_channel(accounts, sender) .await .inspect_err(|err| tracing::Span::current().set_error(err))?; @@ -221,8 +221,8 @@ impl StoreClient { } } - #[instrument(target = COMPONENT, name = "store.client.fetch_page", skip_all, err)] - async fn fetch_page( + #[instrument(target = COMPONENT, name = "store.client.fetch_network_account_ids_page", skip_all, err)] + async fn fetch_network_account_ids_page( &self, block_range: std::ops::RangeInclusive, ) -> Result<(Vec, proto::rpc::PaginationInfo), StoreError> { @@ -285,10 +285,10 @@ impl StoreClient { #[instrument( target = COMPONENT, - name = "store.client.submit_page", + name = "store.client.send_accounts_to_channel", skip_all )] - async fn submit_page( + async fn send_accounts_to_channel( &self, accounts: Vec, sender: &tokio::sync::mpsc::Sender,