From 1b376f6fe3e86717f1655fc836c91e8366dfd3a9 Mon Sep 17 00:00:00 2001 From: Francis Li Date: Wed, 19 Nov 2025 20:52:32 -0800 Subject: [PATCH 1/4] Update to use op-alloy flashblock types --- crates/rollup-boost/src/flashblocks/inbound.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/rollup-boost/src/flashblocks/inbound.rs b/crates/rollup-boost/src/flashblocks/inbound.rs index e2a28e7a..1ab0cdf5 100644 --- a/crates/rollup-boost/src/flashblocks/inbound.rs +++ b/crates/rollup-boost/src/flashblocks/inbound.rs @@ -7,6 +7,7 @@ use futures::{SinkExt, StreamExt}; use lru::LruCache; use op_alloy_rpc_types_engine::OpFlashblockPayload; use std::io::ErrorKind::TimedOut; +use op_alloy_rpc_types_engine::OpFlashblockPayload; use std::num::NonZeroUsize; use std::sync::Arc; use std::sync::Mutex; From d11fb0d9988d5b85dc1734c4b6bdc6ab1cd0edc7 Mon Sep 17 00:00:00 2001 From: Francis Li Date: Thu, 4 Dec 2025 13:23:13 -0800 Subject: [PATCH 2/4] Rebase to resolve conflict --- crates/rollup-boost/src/flashblocks/inbound.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/rollup-boost/src/flashblocks/inbound.rs b/crates/rollup-boost/src/flashblocks/inbound.rs index 1ab0cdf5..e2a28e7a 100644 --- a/crates/rollup-boost/src/flashblocks/inbound.rs +++ b/crates/rollup-boost/src/flashblocks/inbound.rs @@ -7,7 +7,6 @@ use futures::{SinkExt, StreamExt}; use lru::LruCache; use op_alloy_rpc_types_engine::OpFlashblockPayload; use std::io::ErrorKind::TimedOut; -use op_alloy_rpc_types_engine::OpFlashblockPayload; use std::num::NonZeroUsize; use std::sync::Arc; use std::sync::Mutex; From e32587dbd0b537625ed9439dd2b79b47741563ce Mon Sep 17 00:00:00 2001 From: avalonche Date: Fri, 19 Dec 2025 07:08:24 +1100 Subject: [PATCH 3/4] Add optional shadow builder to args --- crates/rollup-boost/src/cli.rs | 16 +++++++++++--- crates/rollup-boost/src/client/rpc.rs | 6 +++++- crates/rollup-boost/src/proxy.rs | 31 ++++++++++++++++++++++++--- crates/rollup-boost/src/server.rs | 2 +- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/crates/rollup-boost/src/cli.rs b/crates/rollup-boost/src/cli.rs index c4a082af..ca1a63df 100644 --- a/crates/rollup-boost/src/cli.rs +++ b/crates/rollup-boost/src/cli.rs @@ -12,13 +12,16 @@ use crate::{ get_version, init_metrics, probe::ProbeLayer, }; -use crate::{FlashblocksService, RpcClient}; +use crate::{FlashblocksService, RpcClient, ShadowBuilderArgs}; #[derive(Clone, Debug, clap::Args)] pub struct RollupBoostLibArgs { #[clap(flatten)] pub builder: BuilderArgs, + #[clap(flatten)] + pub shadow_builder: Option, + #[clap(flatten)] pub l2_client: L2ClientArgs, @@ -117,6 +120,12 @@ impl RollupBoostServiceArgs { let builder_client_args: ClientArgs = self.lib.builder.clone().into(); let builder_http_client = builder_client_args.new_http_client(PayloadSource::Builder)?; + let shadow_builder_client_args: Option = + self.lib.shadow_builder.clone().map(Into::into); + let shadow_builder_http_client = shadow_builder_client_args + .map(|client| client.new_http_client(PayloadSource::Builder)) + .transpose()?; + let (probe_layer, probes) = ProbeLayer::new(); let (health_handle, rpc_module) = if self.lib.flashblocks.flashblocks { @@ -148,8 +157,9 @@ impl RollupBoostServiceArgs { tower::ServiceBuilder::new() .layer(probe_layer) .layer(ProxyLayer::new( - l2_http_client.clone(), - builder_http_client.clone(), + l2_http_client, + builder_http_client, + shadow_builder_http_client, )); let server = Server::builder() diff --git a/crates/rollup-boost/src/client/rpc.rs b/crates/rollup-boost/src/client/rpc.rs index 511eaaab..6ba03147 100644 --- a/crates/rollup-boost/src/client/rpc.rs +++ b/crates/rollup-boost/src/client/rpc.rs @@ -467,7 +467,11 @@ macro_rules! define_client_args { }; } -define_client_args!((BuilderArgs, builder), (L2ClientArgs, l2)); +define_client_args!( + (BuilderArgs, builder), + (L2ClientArgs, l2), + (ShadowBuilderArgs, shadow_builder) +); #[cfg(test)] pub mod tests { diff --git a/crates/rollup-boost/src/proxy.rs b/crates/rollup-boost/src/proxy.rs index fc1e3c35..d7924688 100644 --- a/crates/rollup-boost/src/proxy.rs +++ b/crates/rollup-boost/src/proxy.rs @@ -6,7 +6,7 @@ use jsonrpsee::server::HttpBody; use std::task::{Context, Poll}; use std::{future::Future, pin::Pin}; use tower::{Layer, Service}; -use tracing::info; +use tracing::{debug, info}; const ENGINE_METHOD: &str = "engine_"; @@ -24,13 +24,19 @@ const FORWARD_REQUESTS: [&str; 6] = [ pub struct ProxyLayer { l2_client: HttpClient, builder_client: HttpClient, + shadow_builder_client: Option, } impl ProxyLayer { - pub fn new(l2_client: HttpClient, builder_client: HttpClient) -> Self { + pub fn new( + l2_client: HttpClient, + builder_client: HttpClient, + shadow_builder_client: Option, + ) -> Self { ProxyLayer { l2_client, builder_client, + shadow_builder_client, } } } @@ -43,6 +49,7 @@ impl Layer for ProxyLayer { inner, l2_client: self.l2_client.clone(), builder_client: self.builder_client.clone(), + shadow_builder_client: self.shadow_builder_client.clone(), } } } @@ -52,6 +59,7 @@ pub struct ProxyService { inner: S, l2_client: HttpClient, builder_client: HttpClient, + shadow_builder_client: Option, } // Consider using `RpcServiceT` when https://github.com/paritytech/jsonrpsee/pull/1521 is merged @@ -108,13 +116,26 @@ where let method_clone = method.clone(); let buffered_clone = buffered.clone(); let mut builder_client = service.builder_client.clone(); - + debug!(target: "proxy::call", message = "forwarding request to builder", ?method); // Fire and forget the builder request tokio::spawn(async move { let _ = builder_client.forward(buffered_clone, method_clone).await; }); } + // If the shadow builder is enabled, forward the request to the shadow builder + if let Some(shadow_builder_client) = service.shadow_builder_client.clone() { + let method_clone = method.clone(); + let buffered_clone = buffered.clone(); + let mut shadow_builder_client = shadow_builder_client.clone(); + debug!(target: "proxy::call", message = "proxying request to shadow builder", ?method); + tokio::spawn(async move { + let _ = shadow_builder_client + .forward(buffered_clone, method_clone) + .await; + }); + } + // Return the response from the L2 client service .l2_client @@ -196,6 +217,7 @@ mod tests { timeout: 1, } .new_http_client(PayloadSource::Builder)?, + None, )); let temp_listener = TcpListener::bind("127.0.0.1:0").await?; @@ -512,6 +534,7 @@ mod tests { } .new_http_client(PayloadSource::Builder) .unwrap(), + None, ); // Create a layered server @@ -825,6 +848,7 @@ mod tests { timeout: 200, } .new_http_client(PayloadSource::Builder)?, + None, ); // Start proxy server @@ -926,6 +950,7 @@ mod tests { timeout: 200, } .new_http_client(PayloadSource::Builder)?, + None, ); // Start proxy on dynamic port diff --git a/crates/rollup-boost/src/server.rs b/crates/rollup-boost/src/server.rs index ae7c7a56..f81c611f 100644 --- a/crates/rollup-boost/src/server.rs +++ b/crates/rollup-boost/src/server.rs @@ -909,7 +909,7 @@ pub mod tests { let http_middleware = tower::ServiceBuilder::new() .layer(probe_layer) - .layer(ProxyLayer::new(l2_http_client, builder_http_client)); + .layer(ProxyLayer::new(l2_http_client, builder_http_client, None)); let server = Server::builder() .set_http_middleware(http_middleware) From 5c1ec296742e42aaa67370a8eb05ad752a01165f Mon Sep 17 00:00:00 2001 From: Solar Mithril Date: Fri, 19 Dec 2025 18:46:50 +0400 Subject: [PATCH 4/4] move shadow builder into FORWARD_REQUESTS --- crates/rollup-boost/src/proxy.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/crates/rollup-boost/src/proxy.rs b/crates/rollup-boost/src/proxy.rs index d7924688..7f244222 100644 --- a/crates/rollup-boost/src/proxy.rs +++ b/crates/rollup-boost/src/proxy.rs @@ -121,19 +121,18 @@ where tokio::spawn(async move { let _ = builder_client.forward(buffered_clone, method_clone).await; }); - } - - // If the shadow builder is enabled, forward the request to the shadow builder - if let Some(shadow_builder_client) = service.shadow_builder_client.clone() { - let method_clone = method.clone(); - let buffered_clone = buffered.clone(); - let mut shadow_builder_client = shadow_builder_client.clone(); - debug!(target: "proxy::call", message = "proxying request to shadow builder", ?method); - tokio::spawn(async move { - let _ = shadow_builder_client - .forward(buffered_clone, method_clone) - .await; - }); + // If the shadow builder is enabled, forward the request to the shadow builder + if let Some(shadow_builder_client) = service.shadow_builder_client.clone() { + let method_clone = method.clone(); + let buffered_clone = buffered.clone(); + let mut shadow_builder_client = shadow_builder_client.clone(); + debug!(target: "proxy::call", message = "proxying request to shadow builder", ?method); + tokio::spawn(async move { + let _ = shadow_builder_client + .forward(buffered_clone, method_clone) + .await; + }); + } } // Return the response from the L2 client