Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 31 additions & 92 deletions crates/rollup-boost/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
use alloy_rpc_types_engine::JwtSecret;
use clap::Parser;
use eyre::bail;
use jsonrpsee::{RpcModule, server::Server};
use parking_lot::Mutex;
use std::{
net::{IpAddr, SocketAddr},
path::PathBuf,
str::FromStr,
sync::Arc,
};
use std::{net::SocketAddr, path::PathBuf};
use tokio::signal::unix::{SignalKind, signal as unix_signal};
use tracing::{Level, info};

use crate::{
BlockSelectionPolicy, Flashblocks, FlashblocksArgs, ProxyLayer, RollupBoostServer, RpcClient,
BlockSelectionPolicy, ClientArgs, DebugServer, FlashblocksArgs, PayloadSource, ProxyLayer,
RollupBoostServer,
client::rpc::{BuilderArgs, L2ClientArgs},
debug_api::ExecutionMode,
get_version, init_metrics,
payload::PayloadSource,
probe::ProbeLayer,
};
use crate::{FlashblocksService, RpcClient};

#[derive(Clone, Parser, Debug)]
#[clap(author, version = get_version(), about)]
Expand Down Expand Up @@ -112,90 +105,34 @@ impl RollupBoostArgs {
init_metrics(&self)?;

let debug_addr = format!("{}:{}", self.debug_host, self.debug_server_port);
let l2_client_args = self.l2_client;

let l2_auth_jwt = if let Some(secret) = l2_client_args.l2_jwt_token {
secret
} else if let Some(path) = l2_client_args.l2_jwt_path.as_ref() {
JwtSecret::from_file(path)?
} else {
bail!("Missing L2 Client JWT secret");
};
let l2_client_args: ClientArgs = self.l2_client.clone().into();
let l2_http_client = l2_client_args.new_http_client(PayloadSource::L2)?;

let l2_client = RpcClient::new(
l2_client_args.l2_url.clone(),
l2_auth_jwt,
l2_client_args.l2_timeout,
PayloadSource::L2,
)?;

let builder_args = self.builder;
let builder_auth_jwt = if let Some(secret) = builder_args.builder_jwt_token {
secret
} else if let Some(path) = builder_args.builder_jwt_path.as_ref() {
JwtSecret::from_file(path)?
} else {
bail!("Missing Builder JWT secret");
};

let builder_client = RpcClient::new(
builder_args.builder_url.clone(),
builder_auth_jwt,
builder_args.builder_timeout,
PayloadSource::Builder,
)?;
let builder_client_args: ClientArgs = self.builder.clone().into();
let builder_http_client = builder_client_args.new_http_client(PayloadSource::Builder)?;

let (probe_layer, probes) = ProbeLayer::new();
let execution_mode = Arc::new(Mutex::new(self.execution_mode));

let (rpc_module, health_handle): (RpcModule<()>, _) = if self.flashblocks.flashblocks {
let flashblocks_args = self.flashblocks;
let inbound_url = flashblocks_args.flashblocks_builder_url;
let outbound_addr = SocketAddr::new(
IpAddr::from_str(&flashblocks_args.flashblocks_host)?,
flashblocks_args.flashblocks_port,
);

let builder_client = Arc::new(Flashblocks::run(
builder_client.clone(),
inbound_url,
outbound_addr,
flashblocks_args.flashblock_builder_ws_reconnect_ms,
)?);

let rollup_boost = RollupBoostServer::new(
l2_client,
builder_client,
execution_mode.clone(),
self.block_selection_policy,
probes.clone(),
self.external_state_root,
self.ignore_unhealthy_builders,
);

let (health_handle, rpc_module) = if self.flashblocks.flashblocks {
let rollup_boost = RollupBoostServer::<FlashblocksService>::new_from_args(
self.clone(),
probes.clone(),
)?;
let health_handle = rollup_boost
.spawn_health_check(self.health_check_interval, self.max_unsafe_interval);

// Spawn the debug server
rollup_boost.start_debug_server(debug_addr.as_str()).await?;
(rollup_boost.try_into()?, health_handle)
let debug_server = DebugServer::new(rollup_boost.execution_mode.clone());
debug_server.run(&debug_addr).await?;
let rpc_module: RpcModule<()> = rollup_boost.try_into()?;
(health_handle, rpc_module)
} else {
let rollup_boost = RollupBoostServer::new(
l2_client,
Arc::new(builder_client),
execution_mode.clone(),
self.block_selection_policy,
probes.clone(),
self.external_state_root,
self.ignore_unhealthy_builders,
);

let rollup_boost =
RollupBoostServer::<RpcClient>::new_from_args(self.clone(), probes.clone())?;
let health_handle = rollup_boost
.spawn_health_check(self.health_check_interval, self.max_unsafe_interval);

// Spawn the debug server
rollup_boost.start_debug_server(debug_addr.as_str()).await?;
(rollup_boost.try_into()?, health_handle)
let debug_server = DebugServer::new(rollup_boost.execution_mode.clone());
debug_server.run(&debug_addr).await?;
let rpc_module: RpcModule<()> = rollup_boost.try_into()?;
(health_handle, rpc_module)
};

// Build and start the server
Expand All @@ -205,12 +142,8 @@ impl RollupBoostArgs {
tower::ServiceBuilder::new()
.layer(probe_layer)
.layer(ProxyLayer::new(
l2_client_args.l2_url,
l2_auth_jwt,
l2_client_args.l2_timeout,
builder_args.builder_url,
builder_auth_jwt,
builder_args.builder_timeout,
l2_http_client.clone(),
builder_http_client.clone(),
));

let server = Server::builder()
Expand Down Expand Up @@ -247,6 +180,12 @@ impl RollupBoostArgs {
}
}

impl Default for RollupBoostArgs {
fn default() -> Self {
Self::parse_from::<_, &str>(std::iter::empty())
}
}

#[derive(Clone, Debug)]
pub enum LogFormat {
Json,
Expand Down
69 changes: 66 additions & 3 deletions crates/rollup-boost/src/client/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::EngineApiExt;
use crate::client::auth::AuthLayer;
use crate::client::http::HttpClient as RollupBoostHttpClient;
use crate::payload::{NewPayload, OpExecutionPayloadEnvelope, PayloadSource, PayloadVersion};
use crate::server::EngineApiClient;
use crate::version::{CARGO_PKG_VERSION, VERGEN_GIT_SHA};
Expand All @@ -10,6 +11,7 @@ use alloy_rpc_types_engine::{
};
use alloy_rpc_types_eth::{Block, BlockNumberOrTag};
use clap::{Parser, arg};
use eyre::bail;
use http::{HeaderMap, Uri};
use jsonrpsee::core::async_trait;
use jsonrpsee::core::middleware::layer::RpcLogger;
Expand Down Expand Up @@ -101,7 +103,7 @@ impl From<RpcClientError> for ErrorObjectOwned {
///
/// - **Engine API** calls are faciliated via the `auth_client` (requires JWT authentication).
///
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct RpcClient {
/// Handles requests to the authenticated Engine API (requires JWT authentication)
auth_client: RpcClientService,
Expand Down Expand Up @@ -376,8 +378,57 @@ impl EngineApiExt for RpcClient {
}
}

#[derive(Debug, Clone)]
pub struct ClientArgs {
/// Auth server address
pub url: Uri,

/// Hex encoded JWT secret to use for the authenticated engine-API RPC server.
pub jwt_token: Option<JwtSecret>,

/// Path to a JWT secret to use for the authenticated engine-API RPC server.
pub jwt_path: Option<PathBuf>,

/// Timeout for http calls in milliseconds
pub timeout: u64,
}

impl ClientArgs {
fn get_auth_jwt(&self) -> eyre::Result<JwtSecret> {
if let Some(secret) = self.jwt_token {
Ok(secret)
} else if let Some(path) = self.jwt_path.as_ref() {
Ok(JwtSecret::from_file(path)?)
} else {
bail!("Missing Client JWT secret");
}
}

pub fn new_rpc_client(&self, payload_source: PayloadSource) -> eyre::Result<RpcClient> {
RpcClient::new(
self.url.clone(),
self.get_auth_jwt()?,
self.timeout,
payload_source,
)
.map_err(eyre::Report::from)
}

pub fn new_http_client(
&self,
payload_source: PayloadSource,
) -> eyre::Result<RollupBoostHttpClient> {
Ok(RollupBoostHttpClient::new(
self.url.clone(),
self.get_auth_jwt()?,
payload_source,
self.timeout,
))
}
}

/// Generates Clap argument structs with a prefix to create a unique namespace when specifying RPC client config via the CLI.
macro_rules! define_rpc_args {
macro_rules! define_client_args {
($(($name:ident, $prefix:ident)),*) => {
$(
paste! {
Expand All @@ -399,12 +450,24 @@ macro_rules! define_rpc_args {
#[arg(long, env, default_value_t = 1000)]
pub [<$prefix _timeout>]: u64,
}


impl From<$name> for ClientArgs {
fn from(args: $name) -> Self {
ClientArgs {
url: args.[<$prefix _url>].clone(),
jwt_token: args.[<$prefix _jwt_token>].clone(),
jwt_path: args.[<$prefix _jwt_path>],
timeout: args.[<$prefix _timeout>],
}
}
}
}
)*
};
}

define_rpc_args!((BuilderArgs, builder), (L2ClientArgs, l2));
define_client_args!((BuilderArgs, builder), (L2ClientArgs, l2));

#[cfg(test)]
pub mod tests {
Expand Down
2 changes: 1 addition & 1 deletion crates/rollup-boost/src/flashblocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ pub use launcher::*;

mod primitives;
mod service;
pub use service::*;

pub use primitives::*;
pub use service::*;

mod inbound;
mod outbound;
Expand Down
2 changes: 1 addition & 1 deletion crates/rollup-boost/src/flashblocks/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl FlashblockBuilder {
}
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct FlashblocksService {
client: RpcClient,

Expand Down
1 change: 1 addition & 0 deletions crates/rollup-boost/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ pub struct PayloadTrace {
pub trace_id: Option<tracing::Id>,
}

#[derive(Debug)]
pub struct PayloadTraceContext {
block_hash_to_payload_ids: Cache<B256, Vec<PayloadId>>,
payload_id: Cache<PayloadId, PayloadTrace>,
Expand Down
2 changes: 1 addition & 1 deletion crates/rollup-boost/src/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub struct ProbeLayer {
}

impl ProbeLayer {
pub(crate) fn new() -> (Self, Arc<Probes>) {
pub fn new() -> (Self, Arc<Probes>) {
let probes = Arc::new(Probes::default());
(
Self {
Expand Down
Loading
Loading