Skip to content

Commit 37b37bc

Browse files
committed
refactor: create a static config
1 parent 35126e3 commit 37b37bc

File tree

16 files changed

+210
-228
lines changed

16 files changed

+210
-228
lines changed

bin/builder.rs

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
use builder::{
2-
config::BuilderConfig,
32
service::serve_builder,
43
tasks::{
5-
block::sim::Simulator, cache::CacheTasks, env::EnvTask, metrics::MetricsTask,
4+
block::sim::SimulatorTask, cache::CacheTasks, env::EnvTask, metrics::MetricsTask,
65
submit::FlashbotsTask,
76
},
87
};
9-
use init4_bin_base::{
10-
deps::tracing::{info, info_span},
11-
utils::from_env::FromEnv,
12-
};
8+
use init4_bin_base::deps::tracing::{info, info_span};
139
use tokio::select;
1410

1511
// Note: Must be set to `multi_thread` to support async tasks.
@@ -19,45 +15,33 @@ async fn main() -> eyre::Result<()> {
1915
let _guard = init4_bin_base::init4();
2016
let init_span_guard = info_span!("builder initialization");
2117

22-
// Pull the configuration from the environment
23-
let config = BuilderConfig::from_env()?.clone();
24-
25-
// We connect the providers greedily, so we can fail early if the
26-
// RU WS connection is invalid.
27-
let (ru_provider, host_provider) =
28-
tokio::try_join!(config.connect_ru_provider(), config.connect_host_provider(),)?;
29-
let quincey = config.connect_quincey().await?;
30-
3118
// Spawn the EnvTask
32-
let env_task =
33-
EnvTask::new(config.clone(), host_provider.clone(), quincey, ru_provider.clone());
34-
let (block_env, env_jh) = env_task.spawn();
19+
let (env_task, metrics_task) = tokio::try_join!(EnvTask::new(), MetricsTask::new())?;
3520

36-
// Spawn the cache system
37-
let cache_tasks = CacheTasks::new(config.clone(), block_env.clone());
38-
let cache_system = cache_tasks.spawn();
21+
// Spawn the Env task
22+
let (block_env, env_jh) = env_task.spawn();
3923

40-
// Set up the metrics task
41-
let metrics = MetricsTask::new(host_provider.clone());
42-
let (tx_channel, metrics_jh) = metrics.spawn();
24+
// Spawn the metrics task
25+
let (tx_channel, metrics_jh) = metrics_task.spawn();
4326

44-
// Spawn the Flashbots task
45-
let submit = FlashbotsTask::new(config.clone(), tx_channel).await?;
46-
let (submit_channel, submit_jh) = submit.spawn();
27+
// Set up the cache, submit, and simulator tasks
28+
let cache_tasks = CacheTasks::new(block_env.clone());
29+
let (submit_task, simulator_task) =
30+
tokio::try_join!(FlashbotsTask::new(tx_channel.clone()), SimulatorTask::new(block_env),)?;
4731

48-
// Set up the simulator
49-
let sim = Simulator::new(&config, host_provider, ru_provider, block_env);
50-
let build_jh = sim.spawn_simulator_task(cache_system.sim_cache, submit_channel);
32+
// Spawn the cache, submit, and simulator tasks
33+
let cache_system = cache_tasks.spawn();
34+
let (submit_channel, submit_jh) = submit_task.spawn();
35+
let build_jh = simulator_task.spawn_simulator_task(cache_system.sim_cache, submit_channel);
5136

5237
// Start the healthcheck server
53-
let server = serve_builder(([0, 0, 0, 0], config.builder_port));
38+
let server = serve_builder(([0, 0, 0, 0], builder::config().builder_port));
5439

5540
// We have finished initializing the builder, so we can drop the init span
5641
// guard.
5742
drop(init_span_guard);
5843

5944
select! {
60-
6145
_ = env_jh => {
6246
info!("env task finished");
6347
},

src/config.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,10 @@ impl BuilderConfig {
215215
}
216216

217217
/// Connect to a Flashbots bundle provider.
218-
pub async fn connect_flashbots(
219-
&self,
220-
config: &BuilderConfig,
221-
) -> Result<FlashbotsProvider, eyre::Error> {
218+
pub async fn connect_flashbots(&self) -> Result<FlashbotsProvider, eyre::Error> {
222219
let endpoint =
223-
config.flashbots_endpoint.clone().expect("flashbots endpoint must be configured");
224-
let signer = config.connect_builder_signer().await?;
220+
self.flashbots_endpoint.clone().expect("flashbots endpoint must be configured");
221+
let signer = self.connect_builder_signer().await?;
225222
let flashbots: FlashbotsProvider =
226223
ProviderBuilder::new().wallet(signer).connect_http(endpoint);
227224
Ok(flashbots)

src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,41 @@ pub mod utils;
3333
/// Test utilitites
3434
pub mod test_utils;
3535

36+
use init4_bin_base::utils::from_env::FromEnv;
3637
// Anonymous import suppresses warnings about unused imports.
3738
use openssl as _;
39+
use signet_constants::SignetSystemConstants;
40+
use std::sync::OnceLock;
41+
42+
/// Global static configuration for the Builder binary.
43+
pub static CONFIG: OnceLock<config::BuilderConfig> = OnceLock::new();
44+
45+
/// Load the Builder configuration from the environment and store it in the
46+
/// global static CONFIG variable. Returns a reference to the configuration.
47+
///
48+
/// # Panics
49+
///
50+
/// Panics if the configuration cannot be loaded from the environment AND no
51+
/// other configuration has been previously initialized.
52+
pub fn config_from_env() -> &'static config::BuilderConfig {
53+
CONFIG.get_or_init(|| config::BuilderConfig::from_env().expect("Failed to load Builder config"))
54+
}
55+
56+
/// Get a reference to the global Builder configuration.
57+
///
58+
/// # Panics
59+
///
60+
/// Panics if the configuration has not been initialized.
61+
pub fn config() -> &'static config::BuilderConfig {
62+
CONFIG.get().expect("Builder config not initialized")
63+
}
64+
65+
/// Get a reference to the Signet system constants from the global Builder
66+
/// configuration.
67+
///
68+
/// # Panics
69+
///
70+
/// Panics if the configuration has not been initialized.
71+
pub fn constants() -> &'static SignetSystemConstants {
72+
&config().constants
73+
}

src/tasks/block/sim.rs

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,6 @@ use tokio::{
2222
};
2323
use tracing::{Instrument, Span, debug, instrument};
2424

25-
/// `Simulator` is responsible for periodically building blocks and submitting them for
26-
/// signing and inclusion in the blockchain. It wraps a rollup provider and a slot
27-
/// calculator with a builder configuration.
28-
#[derive(Debug)]
29-
pub struct Simulator {
30-
/// Configuration for the builder.
31-
pub config: BuilderConfig,
32-
/// Host Provider to interact with the host chain.
33-
pub host_provider: HostProvider,
34-
/// A provider that cannot sign transactions, used for interacting with the rollup.
35-
pub ru_provider: RuProvider,
36-
/// The block configuration environment on which to simulate
37-
pub sim_env: watch::Receiver<Option<SimEnv>>,
38-
}
39-
4025
/// SimResult bundles a BuiltBlock to the BlockEnv it was simulated against.
4126
#[derive(Debug, Clone)]
4227
pub struct SimResult {
@@ -79,25 +64,30 @@ impl SimResult {
7964
}
8065
}
8166

82-
impl Simulator {
83-
/// Creates a new `Simulator` instance.
84-
///
85-
/// # Arguments
86-
///
87-
/// - `config`: The configuration for the builder.
88-
/// - `ru_provider`: A provider for interacting with the rollup.
89-
/// - `block_env`: A receiver for the block environment to simulate against.
90-
///
91-
/// # Returns
92-
///
93-
/// A new `Simulator` instance.
94-
pub fn new(
95-
config: &BuilderConfig,
96-
host_provider: HostProvider,
97-
ru_provider: RuProvider,
98-
sim_env: watch::Receiver<Option<SimEnv>>,
99-
) -> Self {
100-
Self { config: config.clone(), host_provider, ru_provider, sim_env }
67+
/// A task that builds blocks based on incoming [`SimEnv`]s and a simulation
68+
/// cache.
69+
#[derive(Debug)]
70+
pub struct SimulatorTask {
71+
/// Configuration for the builder.
72+
config: &'static BuilderConfig,
73+
/// Host Provider to interact with the host chain.
74+
host_provider: HostProvider,
75+
/// A provider that cannot sign transactions, used for interacting with the rollup.
76+
ru_provider: RuProvider,
77+
/// The block configuration environments on which to simulate
78+
envs: watch::Receiver<Option<SimEnv>>,
79+
}
80+
81+
impl SimulatorTask {
82+
/// Create a new `SimulatorTask` instance. This task must be spawned to
83+
/// begin processing incoming block environments.
84+
pub async fn new(envs: watch::Receiver<Option<SimEnv>>) -> eyre::Result<Self> {
85+
let config = crate::config();
86+
87+
let (host_provider, ru_provider) =
88+
tokio::try_join!(config.connect_host_provider(), config.connect_ru_provider())?;
89+
90+
Ok(Self { config, host_provider, ru_provider, envs })
10191
}
10292

10393
/// Get the slot calculator.
@@ -110,18 +100,17 @@ impl Simulator {
110100
&self.config.constants
111101
}
112102

113-
/// Handles building a single block.
103+
/// Build a single block
114104
///
115-
/// Builds a block in the block environment with items from the simulation cache
116-
/// against the database state. When the `finish_by` deadline is reached, it
117-
/// stops simulating and returns the block.
105+
/// Build a block in the sim environment with items from the simulation
106+
/// cache against the database state. When the `finish_by` deadline is
107+
/// reached, it stops simulating and returns the block.
118108
///
119109
/// # Arguments
120110
///
121-
/// - `constants`: The system constants for the rollup.
122111
/// - `sim_items`: The simulation cache containing transactions and bundles.
123112
/// - `finish_by`: The deadline by which the block must be built.
124-
/// - `block_env`: The block environment to simulate against.
113+
/// - `sim_env`: The block environment to simulate against.
125114
///
126115
/// # Returns
127116
///
@@ -209,11 +198,11 @@ impl Simulator {
209198
) {
210199
loop {
211200
// Wait for the block environment to be set
212-
if self.sim_env.changed().await.is_err() {
201+
if self.envs.changed().await.is_err() {
213202
tracing::error!("block_env channel closed - shutting down simulator task");
214203
return;
215204
}
216-
let Some(sim_env) = self.sim_env.borrow_and_update().clone() else { return };
205+
let Some(sim_env) = self.envs.borrow_and_update().clone() else { return };
217206

218207
let span = sim_env.span();
219208
span_info!(span, "new block environment received");

src/tasks/cache/bundle.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,33 @@ const POLL_INTERVAL_MS: u64 = 1000;
1717
#[derive(Debug)]
1818
pub struct BundlePoller {
1919
/// The builder configuration values.
20-
pub config: BuilderConfig,
20+
config: &'static BuilderConfig,
2121
/// Authentication module that periodically fetches and stores auth tokens.
22-
pub token: SharedToken,
22+
token: SharedToken,
2323
/// Holds a Reqwest client
24-
pub client: Client,
24+
client: Client,
2525
/// Defines the interval at which the bundler polls the tx-pool for bundles.
26-
pub poll_interval_ms: u64,
26+
poll_interval_ms: u64,
27+
}
28+
29+
impl Default for BundlePoller {
30+
fn default() -> Self {
31+
Self::new()
32+
}
2733
}
2834

2935
/// Implements a poller for the block builder to pull bundles from the tx-pool.
3036
impl BundlePoller {
3137
/// Creates a new BundlePoller from the provided builder config.
32-
pub fn new(config: &BuilderConfig, token: SharedToken) -> Self {
33-
Self {
34-
config: config.clone(),
35-
token,
36-
client: Client::new(),
37-
poll_interval_ms: POLL_INTERVAL_MS,
38-
}
38+
pub fn new() -> Self {
39+
Self::new_with_poll_interval_ms(POLL_INTERVAL_MS)
3940
}
4041

4142
/// Creates a new BundlePoller from the provided builder config and with the specified poll interval in ms.
42-
pub fn new_with_poll_interval_ms(
43-
config: &BuilderConfig,
44-
token: SharedToken,
45-
poll_interval_ms: u64,
46-
) -> Self {
47-
Self { config: config.clone(), token, client: Client::new(), poll_interval_ms }
43+
pub fn new_with_poll_interval_ms(poll_interval_ms: u64) -> Self {
44+
let config = crate::config();
45+
let token = config.oauth_token();
46+
Self { config, token, client: Client::new(), poll_interval_ms }
4847
}
4948

5049
/// Fetches bundles from the transaction cache and returns them.

src/tasks/cache/system.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,33 @@
11
use signet_sim::SimCache;
22
use tokio::{sync::watch, task::JoinHandle};
33

4-
use crate::{
5-
config::BuilderConfig,
6-
tasks::{
7-
cache::{BundlePoller, CacheTask, TxPoller},
8-
env::SimEnv,
9-
},
4+
use crate::tasks::{
5+
cache::{BundlePoller, CacheTask, TxPoller},
6+
env::SimEnv,
107
};
118

129
/// The block builder's cache system.
1310
#[derive(Debug)]
1411
pub struct CacheTasks {
15-
/// The builder config.
16-
pub config: BuilderConfig,
1712
/// The block environment receiver.
18-
pub block_env: watch::Receiver<Option<SimEnv>>,
13+
block_env: watch::Receiver<Option<SimEnv>>,
1914
}
2015

2116
impl CacheTasks {
2217
/// Create a new [`CacheSystem`] with the given components.
23-
pub const fn new(config: BuilderConfig, block_env: watch::Receiver<Option<SimEnv>>) -> Self {
24-
Self { config, block_env }
18+
pub const fn new(block_env: watch::Receiver<Option<SimEnv>>) -> Self {
19+
Self { block_env }
2520
}
2621

2722
/// Spawn a new [`CacheSystem`], which starts the
2823
/// [`CacheTask`], [`TxPoller`], and [`BundlePoller`] internally and yields their [`JoinHandle`]s.
2924
pub fn spawn(&self) -> CacheSystem {
3025
// Tx Poller pulls transactions from the cache
31-
let tx_poller = TxPoller::new(&self.config);
26+
let tx_poller = TxPoller::new();
3227
let (tx_receiver, tx_poller) = tx_poller.spawn();
3328

3429
// Bundle Poller pulls bundles from the cache
35-
let bundle_poller = BundlePoller::new(&self.config, self.config.oauth_token());
30+
let bundle_poller = BundlePoller::new();
3631
let (bundle_receiver, bundle_poller) = bundle_poller.spawn();
3732

3833
// Set up the cache task

src/tasks/cache/tx.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,37 @@ struct TxPoolResponse {
1818
transactions: Vec<TxEnvelope>,
1919
}
2020

21-
/// Implements a poller for the block builder to pull transactions from the transaction pool.
21+
/// Implements a poller for the block builder to pull transactions from the
22+
/// transaction pool.
2223
#[derive(Debug, Clone)]
2324
pub struct TxPoller {
2425
/// Config values from the Builder.
25-
pub config: BuilderConfig,
26+
config: &'static BuilderConfig,
2627
/// Reqwest Client for fetching transactions from the cache.
27-
pub client: Client,
28+
client: Client,
2829
/// Defines the interval at which the service should poll the cache.
29-
pub poll_interval_ms: u64,
30+
poll_interval_ms: u64,
31+
}
32+
33+
impl Default for TxPoller {
34+
fn default() -> Self {
35+
Self::new()
36+
}
3037
}
3138

3239
/// [`TxPoller`] implements a poller task that fetches transactions from the transaction pool
3340
/// and sends them into the provided channel sender.
3441
impl TxPoller {
3542
/// Returns a new [`TxPoller`] with the given config.
3643
/// * Defaults to 1000ms poll interval (1s).
37-
pub fn new(config: &BuilderConfig) -> Self {
38-
Self { config: config.clone(), client: Client::new(), poll_interval_ms: POLL_INTERVAL_MS }
44+
pub fn new() -> Self {
45+
Self::new_with_poll_interval_ms(POLL_INTERVAL_MS)
3946
}
4047

4148
/// Returns a new [`TxPoller`] with the given config and cache polling interval in milliseconds.
42-
pub fn new_with_poll_interval_ms(config: &BuilderConfig, poll_interval_ms: u64) -> Self {
43-
Self { config: config.clone(), client: Client::new(), poll_interval_ms }
49+
pub fn new_with_poll_interval_ms(poll_interval_ms: u64) -> Self {
50+
let config = crate::config();
51+
Self { config, client: Client::new(), poll_interval_ms }
4452
}
4553

4654
/// Returns the poll duration as a [`Duration`].

0 commit comments

Comments
 (0)