From db27997a514e5c26d45eeccd28b8a11e1192f92c Mon Sep 17 00:00:00 2001 From: Kostia Savchuk Date: Tue, 24 Mar 2026 10:09:10 +0100 Subject: [PATCH 1/2] mvp --- node/bin/src/config/mod.rs | 16 ++++++++++++++++ node/bin/src/lib.rs | 5 +++-- node/bin/src/main.rs | 11 +++++++++-- node/bin/src/provider.rs | 6 ++++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/node/bin/src/config/mod.rs b/node/bin/src/config/mod.rs index 0f5fa538d..6094ce21f 100644 --- a/node/bin/src/config/mod.rs +++ b/node/bin/src/config/mod.rs @@ -41,6 +41,7 @@ pub struct Config { pub tx_validator_config: MempoolTxValidatorConfig, pub sequencer_config: SequencerConfig, pub l1_sender_config: L1SenderConfig, + pub provider_config: ProviderConfig, pub l1_watcher_config: L1WatcherConfig, pub batcher_config: BatcherConfig, pub prover_input_generator_config: ProverInputGeneratorConfig, @@ -84,6 +85,9 @@ impl Config { schema .insert(&L1SenderConfig::DESCRIPTION, "l1_sender") .expect("Failed to insert l1_sender config"); + schema + .insert(&ProviderConfig::DESCRIPTION, "provider") + .expect("Failed to insert provider config"); schema .insert(&L1WatcherConfig::DESCRIPTION, "l1_watcher") .expect("Failed to insert l1_watcher config"); @@ -549,6 +553,18 @@ pub struct L1SenderConfig { pub pubdata_mode: Option, } +#[derive(Clone, Debug, DescribeConfig, DeserializeConfig)] +#[config(derive(Default))] +pub struct ProviderConfig { + /// Number of retries for L1/SL RPC calls, excluding the initial attempt. + #[config(default_t = 2)] + pub max_retries: u32, + + /// Constant backoff duration between L1/SL RPC retries. + #[config(default_t = 200 * TimeUnit::Millis)] + pub retry_backoff: Duration, +} + #[derive(Clone, Debug, DescribeConfig, DeserializeConfig)] #[config(derive(Default))] pub struct L1WatcherConfig { diff --git a/node/bin/src/lib.rs b/node/bin/src/lib.rs index cd512e7a2..ec4fb6076 100644 --- a/node/bin/src/lib.rs +++ b/node/bin/src/lib.rs @@ -182,9 +182,10 @@ pub async fn run build_node_provider(url).await, + Some(url) => build_node_provider(url, &config.provider_config).await, None => l1_provider.clone(), }; let gateway_provider = config diff --git a/node/bin/src/main.rs b/node/bin/src/main.rs index b725cd5cb..f8e9a16b8 100644 --- a/node/bin/src/main.rs +++ b/node/bin/src/main.rs @@ -14,8 +14,8 @@ use zksync_os_server::config::{ ExternalPriceApiClientConfig, FeeConfig, GasAdjusterConfig, GeneralConfig, GenesisConfig, InteropFeeUpdaterConfig, L1SenderConfig, L1WatcherConfig, MempoolConfig, MempoolTxValidatorConfig, NetworkConfig, ObservabilityConfig, ProofStorageConfig, - ProverApiConfig, ProverInputGeneratorConfig, RebuildBlocksConfig, RpcConfig, SequencerConfig, - StateBackendConfig, StatusServerConfig, + ProverApiConfig, ProverInputGeneratorConfig, ProviderConfig, RebuildBlocksConfig, RpcConfig, + SequencerConfig, StateBackendConfig, StatusServerConfig, }; use zksync_os_server::default_protocol_version::{DEFAULT_ROCKS_DB_PATH, PROTOCOL_VERSION}; use zksync_os_server::{INTERNAL_CONFIG_FILE_NAME, run}; @@ -294,6 +294,12 @@ async fn build_external_config(repo: ConfigRepository<'_>) -> Config { l1_sender_config.pubdata_mode = None; } + let provider_config = repo + .single::() + .expect("Failed to load provider config") + .parse() + .expect("Failed to parse provider config"); + let l1_watcher_config = repo .single::() .expect("Failed to load L1 watcher config") @@ -409,6 +415,7 @@ async fn build_external_config(repo: ConfigRepository<'_>) -> Config { tx_validator_config, sequencer_config, l1_sender_config, + provider_config, l1_watcher_config, batcher_config, prover_input_generator_config, diff --git a/node/bin/src/provider.rs b/node/bin/src/provider.rs index c22e08630..9a7fe662d 100644 --- a/node/bin/src/provider.rs +++ b/node/bin/src/provider.rs @@ -1,3 +1,4 @@ +use crate::config::ProviderConfig; use alloy::network::{Ethereum, EthereumWallet}; use alloy::providers::fillers::{FillProvider, TxFiller}; use alloy::providers::{Provider, ProviderBuilder, WalletProvider}; @@ -42,13 +43,14 @@ impl RetryPolicy for OptimisticRetryPolicy { pub async fn build_node_provider( rpc_url: &str, + provider_config: &ProviderConfig, ) -> FillProvider< impl TxFiller + WalletProvider + 'static, impl Provider + Clone + 'static, > { let retry_layer = RetryBackoffLayer::new_with_policy( - 2, // max retries, excluding the initial attempt - 200, // backoff in ms, + provider_config.max_retries, + provider_config.retry_backoff.as_millis() as u64, u64::MAX, // compute units per second, considering it unlimited for now OptimisticRetryPolicy::default(), ); From 6ee73290d902c4cbe57cbeb6753f8c79266da5cf Mon Sep 17 00:00:00 2001 From: Kostia Savchuk Date: Tue, 24 Mar 2026 11:18:27 +0100 Subject: [PATCH 2/2] fix --- integration-tests/src/config.rs | 1 + integration-tests/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/integration-tests/src/config.rs b/integration-tests/src/config.rs index 2023de17a..fa493ccd0 100644 --- a/integration-tests/src/config.rs +++ b/integration-tests/src/config.rs @@ -145,6 +145,7 @@ fn load_config_from_path(config_path: &Path) -> Config { Config { genesis_config, l1_sender_config: config_repo.single().unwrap().parse().unwrap(), + provider_config: Default::default(), general_config: config_repo.single().unwrap().parse().unwrap(), network_config: Default::default(), rpc_config: Default::default(), diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 92929ae39..524c9006f 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -367,6 +367,7 @@ impl Tester { tx_validator_config: Default::default(), sequencer_config, l1_sender_config: default_config.l1_sender_config.clone(), + provider_config: Default::default(), l1_watcher_config: Default::default(), batcher_config: Default::default(), prover_input_generator_config: ProverInputGeneratorConfig {