Skip to content

Commit 2ce4654

Browse files
committed
refactor: Enable library usage of rollup-boost
* unify client configuration with ClientArgs struct * Consolidate BuilderArgs/L2ClientArgs into unified ClientArgs pattern * Move JWT handling into ClientArgs with helper methods * Update ProxyLayer to accept HttpClient instances instead of raw config * Add RollupBoostServer::new_from_args for cleaner initialization * Bump reth-rpc-layer to v1.8.2
1 parent a434815 commit 2ce4654

File tree

10 files changed

+1793
-896
lines changed

10 files changed

+1793
-896
lines changed

Cargo.lock

Lines changed: 1444 additions & 652 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@ url = "2.2.0"
2525
sha2 = { version = "0.10", default-features = false }
2626

2727
# Reth deps
28-
reth-optimism-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
28+
reth-optimism-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" }
2929

3030
# Alloy libraries
31-
alloy-rpc-types-engine = "1.0.35"
32-
alloy-rpc-types-eth = "1.0.35"
31+
alloy-rpc-types-engine = "1.0.37"
32+
alloy-rpc-types-eth = "1.0.37"
3333
alloy-primitives = { version = "1.3.1", features = ["rand"] }
34-
alloy-serde = "1.0.35"
35-
alloy-eips = "1.0.35"
36-
alloy-json-rpc = "1.0.35"
37-
alloy-consensus = "1.0.35"
38-
alloy-rpc-types = "1.0.35"
39-
alloy-genesis = "1.0.35"
40-
alloy-rpc-client = "1.0.35"
41-
alloy-provider = "1.0.35"
34+
alloy-serde = "1.0.37"
35+
alloy-eips = "1.0.37"
36+
alloy-json-rpc = "1.0.37"
37+
alloy-consensus = "1.0.37"
38+
alloy-rpc-types = "1.0.37"
39+
alloy-genesis = "1.0.37"
40+
alloy-rpc-client = "1.0.37"
41+
alloy-provider = "1.0.37"
4242
op-alloy-network = "0.20.0"
4343
op-alloy-rpc-types-engine = "0.20.0"
4444
op-alloy-consensus = "0.20.0"

crates/rollup-boost/src/cli.rs

Lines changed: 35 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
1-
use alloy_rpc_types_engine::JwtSecret;
1+
use crate::server::IntoRpcModule;
22
use clap::Parser;
3-
use eyre::bail;
4-
use jsonrpsee::{RpcModule, server::Server};
5-
use parking_lot::Mutex;
6-
use std::{
7-
net::{IpAddr, SocketAddr},
8-
path::PathBuf,
9-
str::FromStr,
10-
sync::Arc,
11-
};
3+
use jsonrpsee::server::Server;
4+
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
125
use tokio::signal::unix::{SignalKind, signal as unix_signal};
136
use tracing::{Level, info};
147

158
use crate::{
16-
BlockSelectionPolicy, Flashblocks, FlashblocksArgs, ProxyLayer, RollupBoostServer, RpcClient,
9+
BlockSelectionPolicy, ClientArgs, DebugServer, FlashblocksArgs, PayloadSource, ProxyLayer,
10+
RollupBoostServer,
1711
client::rpc::{BuilderArgs, L2ClientArgs},
1812
debug_api::ExecutionMode,
1913
get_version, init_metrics,
20-
payload::PayloadSource,
2114
probe::ProbeLayer,
2215
};
16+
use crate::{FlashblocksService, RpcClient};
2317

2418
#[derive(Clone, Parser, Debug)]
2519
#[clap(author, version = get_version(), about)]
@@ -112,90 +106,36 @@ impl RollupBoostArgs {
112106
init_metrics(&self)?;
113107

114108
let debug_addr = format!("{}:{}", self.debug_host, self.debug_server_port);
115-
let l2_client_args = self.l2_client;
116-
117-
let l2_auth_jwt = if let Some(secret) = l2_client_args.l2_jwt_token {
118-
secret
119-
} else if let Some(path) = l2_client_args.l2_jwt_path.as_ref() {
120-
JwtSecret::from_file(path)?
121-
} else {
122-
bail!("Missing L2 Client JWT secret");
123-
};
109+
let l2_client_args: ClientArgs = self.l2_client.clone().into();
110+
let l2_http_client = l2_client_args.new_http_client(PayloadSource::L2)?;
124111

125-
let l2_client = RpcClient::new(
126-
l2_client_args.l2_url.clone(),
127-
l2_auth_jwt,
128-
l2_client_args.l2_timeout,
129-
PayloadSource::L2,
130-
)?;
131-
132-
let builder_args = self.builder;
133-
let builder_auth_jwt = if let Some(secret) = builder_args.builder_jwt_token {
134-
secret
135-
} else if let Some(path) = builder_args.builder_jwt_path.as_ref() {
136-
JwtSecret::from_file(path)?
137-
} else {
138-
bail!("Missing Builder JWT secret");
139-
};
140-
141-
let builder_client = RpcClient::new(
142-
builder_args.builder_url.clone(),
143-
builder_auth_jwt,
144-
builder_args.builder_timeout,
145-
PayloadSource::Builder,
146-
)?;
112+
let builder_client_args: ClientArgs = self.builder.clone().into();
113+
let builder_http_client = builder_client_args.new_http_client(PayloadSource::Builder)?;
147114

148115
let (probe_layer, probes) = ProbeLayer::new();
149-
let execution_mode = Arc::new(Mutex::new(self.execution_mode));
150-
151-
let (rpc_module, health_handle): (RpcModule<()>, _) = if self.flashblocks.flashblocks {
152-
let flashblocks_args = self.flashblocks;
153-
let inbound_url = flashblocks_args.flashblocks_builder_url;
154-
let outbound_addr = SocketAddr::new(
155-
IpAddr::from_str(&flashblocks_args.flashblocks_host)?,
156-
flashblocks_args.flashblocks_port,
157-
);
158-
159-
let builder_client = Arc::new(Flashblocks::run(
160-
builder_client.clone(),
161-
inbound_url,
162-
outbound_addr,
163-
flashblocks_args.flashblock_builder_ws_reconnect_ms,
164-
)?);
165-
166-
let rollup_boost = RollupBoostServer::new(
167-
l2_client,
168-
builder_client,
169-
execution_mode.clone(),
170-
self.block_selection_policy,
171-
probes.clone(),
172-
self.external_state_root,
173-
self.ignore_unhealthy_builders,
174-
);
175116

117+
let (health_handle, rpc_module) = if self.flashblocks.flashblocks {
118+
let server = RollupBoostServer::<FlashblocksService>::new_from_args(
119+
self.clone(),
120+
probes.clone(),
121+
)?;
122+
let rollup_boost = Arc::new(server);
176123
let health_handle = rollup_boost
177124
.spawn_health_check(self.health_check_interval, self.max_unsafe_interval);
178-
179-
// Spawn the debug server
180-
rollup_boost.start_debug_server(debug_addr.as_str()).await?;
181-
(rollup_boost.try_into()?, health_handle)
125+
let debug_server = DebugServer::new(rollup_boost.clone());
126+
debug_server.run(&debug_addr).await?;
127+
let rpc_module = rollup_boost.into_rpc_module()?;
128+
(health_handle, rpc_module)
182129
} else {
183-
let rollup_boost = RollupBoostServer::new(
184-
l2_client,
185-
Arc::new(builder_client),
186-
execution_mode.clone(),
187-
self.block_selection_policy,
188-
probes.clone(),
189-
self.external_state_root,
190-
self.ignore_unhealthy_builders,
191-
);
192-
130+
let server =
131+
RollupBoostServer::<RpcClient>::new_from_args(self.clone(), probes.clone())?;
132+
let rollup_boost = Arc::new(server);
193133
let health_handle = rollup_boost
194134
.spawn_health_check(self.health_check_interval, self.max_unsafe_interval);
195-
196-
// Spawn the debug server
197-
rollup_boost.start_debug_server(debug_addr.as_str()).await?;
198-
(rollup_boost.try_into()?, health_handle)
135+
let debug_server = DebugServer::new(rollup_boost.clone());
136+
debug_server.run(&debug_addr).await?;
137+
let rpc_module = rollup_boost.into_rpc_module()?;
138+
(health_handle, rpc_module)
199139
};
200140

201141
// Build and start the server
@@ -205,12 +145,8 @@ impl RollupBoostArgs {
205145
tower::ServiceBuilder::new()
206146
.layer(probe_layer)
207147
.layer(ProxyLayer::new(
208-
l2_client_args.l2_url,
209-
l2_auth_jwt,
210-
l2_client_args.l2_timeout,
211-
builder_args.builder_url,
212-
builder_auth_jwt,
213-
builder_args.builder_timeout,
148+
l2_http_client.clone(),
149+
builder_http_client.clone(),
214150
));
215151

216152
let server = Server::builder()
@@ -247,6 +183,12 @@ impl RollupBoostArgs {
247183
}
248184
}
249185

186+
impl Default for RollupBoostArgs {
187+
fn default() -> Self {
188+
Self::parse_from::<_, &str>(std::iter::empty())
189+
}
190+
}
191+
250192
#[derive(Clone, Debug)]
251193
pub enum LogFormat {
252194
Json,

crates/rollup-boost/src/client/rpc.rs

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::EngineApiExt;
22
use crate::client::auth::AuthLayer;
3+
use crate::client::http::HttpClient as RollupBoostHttpClient;
34
use crate::payload::{NewPayload, OpExecutionPayloadEnvelope, PayloadSource, PayloadVersion};
45
use crate::server::EngineApiClient;
56
use crate::version::{CARGO_PKG_VERSION, VERGEN_GIT_SHA};
@@ -10,6 +11,7 @@ use alloy_rpc_types_engine::{
1011
};
1112
use alloy_rpc_types_eth::{Block, BlockNumberOrTag};
1213
use clap::{Parser, arg};
14+
use eyre::bail;
1315
use http::{HeaderMap, Uri};
1416
use jsonrpsee::core::async_trait;
1517
use jsonrpsee::core::middleware::layer::RpcLogger;
@@ -101,7 +103,7 @@ impl From<RpcClientError> for ErrorObjectOwned {
101103
///
102104
/// - **Engine API** calls are faciliated via the `auth_client` (requires JWT authentication).
103105
///
104-
#[derive(Clone)]
106+
#[derive(Clone, Debug)]
105107
pub struct RpcClient {
106108
/// Handles requests to the authenticated Engine API (requires JWT authentication)
107109
auth_client: RpcClientService,
@@ -376,8 +378,68 @@ impl EngineApiExt for RpcClient {
376378
}
377379
}
378380

381+
#[derive(Debug, Clone)]
382+
pub struct ClientArgs {
383+
/// Auth server address
384+
pub url: Uri,
385+
386+
/// Hex encoded JWT secret to use for the authenticated engine-API RPC server.
387+
pub jwt_token: Option<JwtSecret>,
388+
389+
/// Path to a JWT secret to use for the authenticated engine-API RPC server.
390+
pub jwt_path: Option<PathBuf>,
391+
392+
/// Timeout for http calls in milliseconds
393+
pub timeout: u64,
394+
}
395+
396+
impl ClientArgs {
397+
fn get_auth_jwt(&self) -> eyre::Result<JwtSecret> {
398+
if let Some(secret) = self.jwt_token {
399+
Ok(secret)
400+
} else if let Some(path) = self.jwt_path.as_ref() {
401+
Ok(JwtSecret::from_file(path)?)
402+
} else {
403+
bail!("Missing Client JWT secret");
404+
}
405+
}
406+
407+
pub fn new_rpc_client(&self, payload_source: PayloadSource) -> eyre::Result<RpcClient> {
408+
RpcClient::new(
409+
self.url.clone(),
410+
self.get_auth_jwt()?,
411+
self.timeout,
412+
payload_source,
413+
)
414+
.map_err(eyre::Report::from)
415+
}
416+
417+
pub fn new_http_client(
418+
&self,
419+
payload_source: PayloadSource,
420+
) -> eyre::Result<RollupBoostHttpClient> {
421+
Ok(RollupBoostHttpClient::new(
422+
self.url.clone(),
423+
self.get_auth_jwt()?,
424+
payload_source,
425+
self.timeout,
426+
))
427+
}
428+
}
429+
430+
impl Default for ClientArgs {
431+
fn default() -> Self {
432+
Self {
433+
url: "127.0.0.1:8551".parse::<Uri>().unwrap(),
434+
jwt_token: None,
435+
jwt_path: None,
436+
timeout: 1000,
437+
}
438+
}
439+
}
440+
379441
/// Generates Clap argument structs with a prefix to create a unique namespace when specifying RPC client config via the CLI.
380-
macro_rules! define_rpc_args {
442+
macro_rules! define_client_args {
381443
($(($name:ident, $prefix:ident)),*) => {
382444
$(
383445
paste! {
@@ -399,12 +461,30 @@ macro_rules! define_rpc_args {
399461
#[arg(long, env, default_value_t = 1000)]
400462
pub [<$prefix _timeout>]: u64,
401463
}
464+
465+
466+
impl From<$name> for ClientArgs {
467+
fn from(args: $name) -> Self {
468+
ClientArgs {
469+
url: args.[<$prefix _url>].clone(),
470+
jwt_token: args.[<$prefix _jwt_token>].clone(),
471+
jwt_path: args.[<$prefix _jwt_path>],
472+
timeout: args.[<$prefix _timeout>],
473+
}
474+
}
475+
}
476+
477+
impl Default for $name {
478+
fn default() -> Self {
479+
Self::parse_from::<_, &str>(std::iter::empty())
480+
}
481+
}
402482
}
403483
)*
404484
};
405485
}
406486

407-
define_rpc_args!((BuilderArgs, builder), (L2ClientArgs, l2));
487+
define_client_args!((BuilderArgs, builder), (L2ClientArgs, l2));
408488

409489
#[cfg(test)]
410490
pub mod tests {

0 commit comments

Comments
 (0)