From 2280e571995a70a154a4a4619126cdbf6f0b78c5 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 7 May 2025 10:15:49 -0400 Subject: [PATCH 1/2] refactor: update config to use derive --- bin/builder.rs | 15 +- bin/submit_transaction.rs | 66 ++++---- src/config.rs | 296 +++++++++++++----------------------- src/tasks/submit.rs | 2 +- src/test_utils.rs | 9 +- tests/block_builder_test.rs | 8 +- 6 files changed, 157 insertions(+), 239 deletions(-) diff --git a/bin/builder.rs b/bin/builder.rs index a6a2f33..86cd191 100644 --- a/bin/builder.rs +++ b/bin/builder.rs @@ -6,7 +6,7 @@ use builder::{ tx_poller, }, }; -use init4_bin_base::{deps::tracing, utils::calc::SlotCalculator}; +use init4_bin_base::{deps::tracing, utils::from_env::FromEnv}; use signet_sim::SimCache; use std::sync::Arc; use tokio::select; @@ -19,15 +19,13 @@ async fn main() -> eyre::Result<()> { let _guard = init4_bin_base::init4(); let init_span_guard = info_span!("builder initialization"); - let config = BuilderConfig::load_from_env()?.clone(); + let config = BuilderConfig::from_env()?.clone(); let constants = config.load_pecorino_constants(); let authenticator = Authenticator::new(&config)?; - let (host_provider, ru_provider, sequencer_signer) = tokio::try_join!( - config.connect_host_provider(), - config.connect_ru_provider(), - config.connect_sequencer_signer(), - )?; + let (host_provider, sequencer_signer) = + tokio::try_join!(config.connect_host_provider(), config.connect_sequencer_signer(),)?; + let ru_provider = config.connect_ru_provider(); let zenith = config.connect_zenith(host_provider.clone()); @@ -55,8 +53,7 @@ async fn main() -> eyre::Result<()> { let (submit_channel, submit_jh) = submit.spawn(); let sim_items = SimCache::new(); - let slot_calculator = - SlotCalculator::new(config.start_timestamp, config.chain_offset, config.target_slot_time); + let slot_calculator = config.slot_calculator; let sim = Arc::new(Simulator::new(&config, ru_provider.clone(), slot_calculator)); diff --git a/bin/submit_transaction.rs b/bin/submit_transaction.rs index 6aec853..55e2dbe 100644 --- a/bin/submit_transaction.rs +++ b/bin/submit_transaction.rs @@ -5,32 +5,65 @@ use alloy::{ rpc::types::eth::TransactionRequest, signers::aws::AwsSigner, }; -use aws_config::BehaviorVersion; -use builder::config::{HostProvider, load_address, load_string, load_u64, load_url}; +use builder::config::HostProvider; use init4_bin_base::{ deps::metrics::{counter, histogram}, init4, + utils::from_env::FromEnv, }; use std::time::{Duration, Instant}; use tokio::time::timeout; +#[derive(Debug, Clone, FromEnv)] +struct Config { + #[from_env(var = "RPC_URL", desc = "Ethereum RPC URL")] + rpc_url: String, + #[from_env(var = "CHAIN_ID", desc = "Ethereum chain ID")] + chain_id: u64, + #[from_env(var = "AWS_KMS_KEY_ID", desc = "AWS KMS key ID")] + kms_key_id: String, + #[from_env(var = "RECIPIENT_ADDRESS", desc = "Recipient address")] + recipient_address: Address, + #[from_env(var = "SLEEP_TIME", desc = "Time to sleep between transactions")] + sleep_time: u64, +} + +impl Config { + async fn provider(&self) -> HostProvider { + let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await; + let client = aws_sdk_kms::Client::new(&config); + let signer = + AwsSigner::new(client, self.kms_key_id.clone(), Some(self.chain_id)).await.unwrap(); + + ProviderBuilder::new() + .wallet(EthereumWallet::from(signer)) + .connect(&self.rpc_url) + .await + .unwrap() + } +} + #[tokio::main] async fn main() { init4(); tracing::trace!("connecting to provider"); - let (provider, recipient_address, sleep_time) = connect_from_config().await; + + let config = Config::from_env().unwrap(); + let provider = config.provider().await; + let recipient_address = config.recipient_address; + let sleep_time = config.sleep_time; loop { tracing::debug!("attempting transaction"); - send_transaction(provider.clone(), recipient_address).await; + send_transaction(&provider, recipient_address).await; tracing::debug!(sleep_time, "sleeping"); tokio::time::sleep(tokio::time::Duration::from_secs(sleep_time)).await; } } -async fn send_transaction(provider: HostProvider, recipient_address: Address) { +async fn send_transaction(provider: &HostProvider, recipient_address: Address) { // construct simple transaction to send ETH to a recipient let tx = TransactionRequest::default() .with_from(provider.default_signer_address()) @@ -66,26 +99,3 @@ async fn send_transaction(provider: HostProvider, recipient_address: Address) { tracing::debug!(success = receipt.status(), mine_time, hash, "transaction mined"); histogram!("txn_submitter.tx_mine_time").record(mine_time as f64); } - -async fn connect_from_config() -> (HostProvider, Address, u64) { - // load signer config values from .env - let rpc_url = load_url("RPC_URL").unwrap(); - let chain_id = load_u64("CHAIN_ID").unwrap(); - let kms_key_id = load_string("AWS_KMS_KEY_ID").unwrap(); - // load transaction sending config value from .env - let recipient_address: Address = load_address("RECIPIENT_ADDRESS").unwrap(); - let sleep_time = load_u64("SLEEP_TIME").unwrap(); - - // connect signer & provider - let config = aws_config::load_defaults(BehaviorVersion::latest()).await; - let client = aws_sdk_kms::Client::new(&config); - let signer = AwsSigner::new(client, kms_key_id.to_string(), Some(chain_id)).await.unwrap(); - - let provider = ProviderBuilder::new() - .wallet(EthereumWallet::from(signer)) - .connect(&rpc_url) - .await - .unwrap(); - - (provider, recipient_address, sleep_time) -} diff --git a/src/config.rs b/src/config.rs index b442212..18cf0ee 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,144 +14,147 @@ use alloy::{ }, }; use eyre::Result; +use init4_bin_base::utils::{calc::SlotCalculator, from_env::FromEnv}; use oauth2::url; use signet_types::config::{HostConfig, PredeployTokens, RollupConfig, SignetSystemConstants}; use signet_zenith::Zenith; -use std::{borrow::Cow, env, num, str::FromStr}; +use std::borrow::Cow; -// Keys for .env variables that need to be set to configure the builder. -const HOST_CHAIN_ID: &str = "HOST_CHAIN_ID"; -const RU_CHAIN_ID: &str = "RU_CHAIN_ID"; -const HOST_RPC_URL: &str = "HOST_RPC_URL"; -const ROLLUP_RPC_URL: &str = "ROLLUP_RPC_URL"; -const TX_BROADCAST_URLS: &str = "TX_BROADCAST_URLS"; -const ZENITH_ADDRESS: &str = "ZENITH_ADDRESS"; -const BUILDER_HELPER_ADDRESS: &str = "BUILDER_HELPER_ADDRESS"; -const QUINCEY_URL: &str = "QUINCEY_URL"; -const BUILDER_PORT: &str = "BUILDER_PORT"; -const SEQUENCER_KEY: &str = "SEQUENCER_KEY"; // empty (to use Quincey) OR AWS key ID (to use AWS signer) OR raw private key (to use local signer) -const BUILDER_KEY: &str = "BUILDER_KEY"; // AWS key ID (to use AWS signer) OR raw private key (to use local signer) -const BLOCK_CONFIRMATION_BUFFER: &str = "BLOCK_CONFIRMATION_BUFFER"; -const CHAIN_OFFSET: &str = "CHAIN_OFFSET"; -const TARGET_SLOT_TIME: &str = "TARGET_SLOT_TIME"; -const BUILDER_REWARDS_ADDRESS: &str = "BUILDER_REWARDS_ADDRESS"; -const ROLLUP_BLOCK_GAS_LIMIT: &str = "ROLLUP_BLOCK_GAS_LIMIT"; -const TX_POOL_URL: &str = "TX_POOL_URL"; -const AUTH_TOKEN_REFRESH_INTERVAL: &str = "AUTH_TOKEN_REFRESH_INTERVAL"; -const TX_POOL_CACHE_DURATION: &str = "TX_POOL_CACHE_DURATION"; -const OAUTH_CLIENT_ID: &str = "OAUTH_CLIENT_ID"; -const OAUTH_CLIENT_SECRET: &str = "OAUTH_CLIENT_SECRET"; -const OAUTH_AUTHENTICATE_URL: &str = "OAUTH_AUTHENTICATE_URL"; -const OAUTH_TOKEN_URL: &str = "OAUTH_TOKEN_URL"; -const CONCURRENCY_LIMIT: &str = "CONCURRENCY_LIMIT"; -const START_TIMESTAMP: &str = "START_TIMESTAMP"; +/// Type alias for the provider used to build and submit blocks to the host. +pub type HostProvider = FillProvider< + JoinFill< + JoinFill< + Identity, + JoinFill>>, + >, + WalletFiller, + >, + RootProvider, + Ethereum, +>; /// Configuration for a builder running a specific rollup on a specific host /// chain. -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] +#[derive(serde::Deserialize, Debug, Clone, FromEnv)] pub struct BuilderConfig { /// The chain ID of the host chain + #[from_env(var = "HOST_CHAIN_ID", desc = "The chain ID of the host chain")] pub host_chain_id: u64, - /// The chain ID of the host chain + /// The chain ID of the rollup chain + #[from_env(var = "RU_CHAIN_ID", desc = "The chain ID of the rollup chain")] pub ru_chain_id: u64, /// URL for Host RPC node. + #[from_env(var = "HOST_RPC_URL", desc = "URL for Host RPC node", infallible)] pub host_rpc_url: Cow<'static, str>, /// URL for the Rollup RPC node. + #[from_env(var = "ROLLUP_RPC_URL", desc = "URL for Rollup RPC node", infallible)] pub ru_rpc_url: Cow<'static, str>, /// Additional RPC URLs to which to broadcast transactions. /// NOTE: should not include the host_rpc_url value + #[from_env( + var = "TX_BROADCAST_URLS", + desc = "Additional RPC URLs to which to broadcast transactions", + infallible + )] pub tx_broadcast_urls: Vec>, /// address of the Zenith contract on Host. + #[from_env(var = "ZENITH_ADDRESS", desc = "address of the Zenith contract on Host")] pub zenith_address: Address, /// address of the Builder Helper contract on Host. + #[from_env( + var = "BUILDER_HELPER_ADDRESS", + desc = "address of the Builder Helper contract on Host" + )] pub builder_helper_address: Address, /// URL for remote Quincey Sequencer server to sign blocks. /// Disregarded if a sequencer_signer is configured. + #[from_env( + var = "QUINCEY_URL", + desc = "URL for remote Quincey Sequencer server to sign blocks", + infallible + )] pub quincey_url: Cow<'static, str>, /// Port for the Builder server. - pub builder_port: u16, + #[from_env(var = "BUILDER_PORT", desc = "Port for the Builder server", optional)] + pub builder_port: Option, /// Key to access Sequencer Wallet - AWS Key ID _OR_ local private key. /// Set IFF using local Sequencer signing instead of remote Quincey signing. + #[from_env( + var = "SEQUENCER_KEY", + desc = "Key to access Sequencer Wallet - AWS Key ID _OR_ local private key, set IFF using local Sequencer signing instead of remote Quincey signing", + infallible, + optional + )] pub sequencer_key: Option, /// Key to access Builder transaction submission wallet - AWS Key ID _OR_ local private key. + #[from_env( + var = "BUILDER_KEY", + desc = "Key to access Builder transaction submission wallet - AWS Key ID _OR_ local private key", + infallible + )] pub builder_key: String, /// Buffer in seconds in which the `submitBlock` transaction must confirm on the Host chain. + #[from_env( + var = "BLOCK_CONFIRMATION_BUFFER", + desc = "Buffer in seconds in which the `submitBlock` transaction must confirm on the Host chain" + )] pub block_confirmation_buffer: u64, - /// The offset between Unix time and the chain's block times. For Holesky, this is 0; for Ethereum, 11. - pub chain_offset: u64, - /// The slot time at which the Builder should begin building a block. 0 to begin at the very start of the slot; 6 to begin in the middle; etc. - pub target_slot_time: u64, + /// Address on Rollup to which Builder will receive user transaction fees. + #[from_env( + var = "BUILDER_REWARDS_ADDRESS", + desc = "Address on Rollup to which Builder will receive user transaction fees" + )] pub builder_rewards_address: Address, /// Gas limit for RU block. /// NOTE: a "smart" builder would determine this programmatically by simulating the block. + #[from_env(var = "ROLLUP_BLOCK_GAS_LIMIT", desc = "Gas limit for RU block")] pub rollup_block_gas_limit: u64, /// URL of the tx pool to poll for incoming transactions. + #[from_env( + var = "TX_POOL_URL", + desc = "URL of the tx pool to poll for incoming transactions", + infallible + )] pub tx_pool_url: Cow<'static, str>, /// Duration in seconds transactions can live in the tx-pool cache. + #[from_env( + var = "TX_POOL_CACHE_DURATION", + desc = "Duration in seconds transactions can live in the tx-pool cache" + )] pub tx_pool_cache_duration: u64, /// OAuth client ID for the builder. + #[from_env(var = "OAUTH_CLIENT_ID", desc = "OAuth client ID for the builder")] pub oauth_client_id: String, /// OAuth client secret for the builder. + #[from_env(var = "OAUTH_CLIENT_SECRET", desc = "OAuth client secret for the builder")] pub oauth_client_secret: String, /// OAuth authenticate URL for the builder for performing OAuth logins. + #[from_env( + var = "OAUTH_AUTHENTICATE_URL", + desc = "OAuth authenticate URL for the builder for performing OAuth logins" + )] pub oauth_authenticate_url: String, /// OAuth token URL for the builder to get an OAuth2 access token + #[from_env( + var = "OAUTH_TOKEN_URL", + desc = "OAuth token URL for the builder to get an OAuth2 access token" + )] pub oauth_token_url: String, /// The oauth token refresh interval in seconds. + #[from_env(var = "CONCURRENCY_LIMIT", desc = "The oauth token refresh interval in seconds")] pub oauth_token_refresh_interval: u64, /// The max number of simultaneous block simulations to run. + #[from_env( + var = "CONCURRENCY_LIMIT", + desc = "The max number of simultaneous block simulations to run" + )] pub concurrency_limit: usize, - /// The anchor for slot time and number calculations before adjusting for chain offset. - pub start_timestamp: u64, -} - -/// Error loading the configuration. -#[derive(Debug, thiserror::Error)] -pub enum ConfigError { - /// Error loading from environment variable - #[error("missing or non-unicode environment variable: {0}")] - Var(String), - /// Error parsing environment variable - #[error("failed to parse environment variable: {0}")] - Parse(#[from] num::ParseIntError), - /// Error parsing boolean environment variable - #[error("failed to parse boolean environment variable")] - ParseBool, - /// Error parsing hex from environment variable - #[error("failed to parse hex: {0}")] - Hex(#[from] hex::FromHexError), - /// Error connecting to the provider - #[error("failed to connect to provider: {0}")] - Provider(#[from] alloy::transports::TransportError), - /// Error connecting to the signer - #[error("failed to connect to signer: {0}")] - Signer(#[from] SignerError), - /// I/O error - #[error("I/O error: {0}")] - Io(#[from] std::io::Error), -} -impl ConfigError { - /// Missing or non-unicode env var. - pub fn missing(s: &str) -> Self { - ConfigError::Var(s.to_string()) - } + /// The slot calculator for the builder. + pub slot_calculator: SlotCalculator, } -/// Type alias for the provider used to build and submit blocks to the host. -pub type HostProvider = FillProvider< - JoinFill< - JoinFill< - Identity, - JoinFill>>, - >, - WalletFiller, - >, - RootProvider, - Ethereum, ->; - /// Type alias for the provider used to simulate against rollup state. pub type RuProvider = RootProvider; @@ -159,90 +162,48 @@ pub type RuProvider = RootProvider; pub type ZenithInstance

= Zenith::ZenithInstance<(), P, alloy::network::Ethereum>; impl BuilderConfig { - /// Load the builder configuration from environment variables. - pub fn load_from_env() -> Result { - Ok(BuilderConfig { - host_chain_id: load_u64(HOST_CHAIN_ID)?, - ru_chain_id: load_u64(RU_CHAIN_ID)?, - host_rpc_url: load_url(HOST_RPC_URL)?, - ru_rpc_url: load_url(ROLLUP_RPC_URL)?, - tx_broadcast_urls: env::var(TX_BROADCAST_URLS) - .unwrap_or_default() - .split(',') - .map(str::trim) - .filter(|url| !url.is_empty()) - .map(ToOwned::to_owned) - .map(Into::into) - .collect(), - zenith_address: load_address(ZENITH_ADDRESS)?, - builder_helper_address: load_address(BUILDER_HELPER_ADDRESS)?, - quincey_url: load_url(QUINCEY_URL)?, - builder_port: load_u16(BUILDER_PORT)?, - sequencer_key: load_string_option(SEQUENCER_KEY), - builder_key: load_string(BUILDER_KEY)?, - block_confirmation_buffer: load_u64(BLOCK_CONFIRMATION_BUFFER)?, - chain_offset: load_u64(CHAIN_OFFSET)?, - target_slot_time: load_u64(TARGET_SLOT_TIME)?, - builder_rewards_address: load_address(BUILDER_REWARDS_ADDRESS)?, - rollup_block_gas_limit: load_u64(ROLLUP_BLOCK_GAS_LIMIT)?, - tx_pool_url: load_url(TX_POOL_URL)?, - tx_pool_cache_duration: load_u64(TX_POOL_CACHE_DURATION)?, - oauth_client_id: load_string(OAUTH_CLIENT_ID)?, - oauth_client_secret: load_string(OAUTH_CLIENT_SECRET)?, - oauth_authenticate_url: load_string(OAUTH_AUTHENTICATE_URL)?, - oauth_token_url: load_string(OAUTH_TOKEN_URL)?, - oauth_token_refresh_interval: load_u64(AUTH_TOKEN_REFRESH_INTERVAL)?, - concurrency_limit: load_concurrency_limit()?, - start_timestamp: load_u64(START_TIMESTAMP)?, - }) - } - /// Connect to the Builder signer. - pub async fn connect_builder_signer(&self) -> Result { - LocalOrAws::load(&self.builder_key, Some(self.host_chain_id)).await.map_err(Into::into) + pub async fn connect_builder_signer(&self) -> Result { + LocalOrAws::load(&self.builder_key, Some(self.host_chain_id)).await } /// Connect to the Sequencer signer. - pub async fn connect_sequencer_signer(&self) -> Result, ConfigError> { - match &self.sequencer_key { - Some(sequencer_key) => LocalOrAws::load(sequencer_key, Some(self.host_chain_id)) + pub async fn connect_sequencer_signer(&self) -> eyre::Result> { + if let Some(sequencer_key) = &self.sequencer_key { + LocalOrAws::load(sequencer_key, Some(self.host_chain_id)) .await .map_err(Into::into) - .map(Some), - None => Ok(None), + .map(Some) + } else { + Ok(None) } } /// Connect to the Rollup rpc provider. - pub async fn connect_ru_provider(&self) -> Result, ConfigError> { + pub fn connect_ru_provider(&self) -> RootProvider { let url = url::Url::parse(&self.ru_rpc_url).expect("failed to parse URL"); - let provider = RootProvider::::new_http(url); - Ok(provider) + RootProvider::::new_http(url) } /// Connect to the Host rpc provider. - pub async fn connect_host_provider(&self) -> Result { + pub async fn connect_host_provider(&self) -> eyre::Result { let builder_signer = self.connect_builder_signer().await?; - let provider = ProviderBuilder::new() + ProviderBuilder::new() .wallet(EthereumWallet::from(builder_signer)) .connect(&self.host_rpc_url) .await - .map_err(ConfigError::Provider)?; - - Ok(provider) + .map_err(Into::into) } /// Connect additional broadcast providers. - pub async fn connect_additional_broadcast(&self) -> Result, ConfigError> { - let mut providers: Vec = Vec::with_capacity(self.tx_broadcast_urls.len()); - - for url_str in self.tx_broadcast_urls.iter() { - let url = url::Url::parse(url_str).expect("failed to parse URL"); - let provider = RootProvider::new_http(url); - providers.push(provider); - } - - Ok(providers) + pub fn connect_additional_broadcast(&self) -> Vec { + self.tx_broadcast_urls + .iter() + .map(|url_str| { + let url = url::Url::parse(url_str).expect("failed to parse URL"); + RootProvider::new_http(url) + }) + .collect::>() } /// Connect to the Zenith instance, using the specified provider. @@ -276,50 +237,3 @@ impl BuilderConfig { SignetSystemConstants::new(host, rollup) } } - -/// Load a string from an environment variable. -pub fn load_string(key: &str) -> Result { - env::var(key).map_err(|_| ConfigError::missing(key)) -} - -/// Load a string from an environment variable, returning None if the variable -/// is not set. -fn load_string_option(key: &str) -> Option { - load_string(key).ok() -} - -/// Load a boolean from an environment variable. -pub fn load_u64(key: &str) -> Result { - let val = load_string(key)?; - val.parse::().map_err(Into::into) -} - -/// Load a u16 from an environment variable. -fn load_u16(key: &str) -> Result { - let val = load_string(key)?; - val.parse::().map_err(Into::into) -} - -/// Load a URL from an environment variable. -pub fn load_url(key: &str) -> Result, ConfigError> { - load_string(key).map(Into::into) -} - -/// Load an address from an environment variable. -pub fn load_address(key: &str) -> Result { - let address = load_string(key)?; - Address::from_str(&address) - .map_err(|_| ConfigError::Var(format!("Invalid address format for {}", key))) -} - -/// Checks the configured concurrency parameter and, if none is set, checks the available -/// system concurrency with `std::thread::available_parallelism` and returns that. -pub fn load_concurrency_limit() -> Result { - match load_u16(CONCURRENCY_LIMIT) { - Ok(env) => Ok(env as usize), - Err(_) => { - let limit = std::thread::available_parallelism()?.get(); - Ok(limit) - } - } -} diff --git a/src/tasks/submit.rs b/src/tasks/submit.rs index 3d3c2db..ff5db52 100644 --- a/src/tasks/submit.rs +++ b/src/tasks/submit.rs @@ -206,7 +206,7 @@ impl SubmitTask { let fut = spawn_provider_send!(&self.host_provider, &tx); // Spawn send_tx futures for all additional broadcast host_providers - for host_provider in self.config.connect_additional_broadcast().await? { + for host_provider in self.config.connect_additional_broadcast() { spawn_provider_send!(&host_provider, &tx); } diff --git a/src/test_utils.rs b/src/test_utils.rs index 2e6fc8d..1102835 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -11,6 +11,7 @@ use alloy::{ }; use chrono::{DateTime, Utc}; use eyre::Result; +use init4_bin_base::utils::calc::SlotCalculator; use std::{ str::FromStr, time::{Instant, SystemTime}, @@ -31,8 +32,7 @@ pub fn setup_test_config() -> Result { sequencer_key: None, builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(), block_confirmation_buffer: 1, - chain_offset: 0, - target_slot_time: 1, + builder_rewards_address: Address::default(), rollup_block_gas_limit: 3_000_000_000, tx_pool_url: "http://localhost:9000/".into(), @@ -44,7 +44,10 @@ pub fn setup_test_config() -> Result { oauth_token_refresh_interval: 300, // 5 minutes builder_helper_address: Address::default(), concurrency_limit: 1000, - start_timestamp: 1740681556, // pecorino start timestamp as sane default + slot_calculator: SlotCalculator::new( + 1740681556, // pecorino start timestamp as sane default + 0, 1, + ), }; Ok(config) } diff --git a/tests/block_builder_test.rs b/tests/block_builder_test.rs index 8d2e65a..739189e 100644 --- a/tests/block_builder_test.rs +++ b/tests/block_builder_test.rs @@ -108,13 +108,7 @@ mod tests { // Create a rollup provider let ru_provider = RootProvider::::new_http(anvil_instance.endpoint_url()); - // Create a builder with a test slot calculator - let slot_calculator = SlotCalculator::new( - config.start_timestamp, - config.chain_offset, - config.target_slot_time, - ); - let sim = Arc::new(Simulator::new(&config, ru_provider.clone(), slot_calculator)); + let sim = Arc::new(Simulator::new(&config, ru_provider.clone(), config.slot_calculator)); // Create a shared sim cache let sim_cache = SimCache::new(); From 717926bee1ab336297a40ff3bc165459850b62a2 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 8 May 2025 08:53:00 -0400 Subject: [PATCH 2/2] fix: not optional --- src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 18cf0ee..3a1a6a9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -75,8 +75,8 @@ pub struct BuilderConfig { )] pub quincey_url: Cow<'static, str>, /// Port for the Builder server. - #[from_env(var = "BUILDER_PORT", desc = "Port for the Builder server", optional)] - pub builder_port: Option, + #[from_env(var = "BUILDER_PORT", desc = "Port for the Builder server")] + pub builder_port: u16, /// Key to access Sequencer Wallet - AWS Key ID _OR_ local private key. /// Set IFF using local Sequencer signing instead of remote Quincey signing. #[from_env(