Skip to content

Commit 36c1ebc

Browse files
mablrmattsse
andauthored
feat(rpc): Add support for custom Tokio runtime configuration in EthereumAddOns (#17693)
Co-authored-by: Matthias Seitz <[email protected]>
1 parent 8e3068f commit 36c1ebc

File tree

7 files changed

+119
-6
lines changed

7 files changed

+119
-6
lines changed

crates/ethereum/node/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ alloy-network.workspace = true
4545
alloy-rpc-types-eth.workspace = true
4646
alloy-rpc-types-engine.workspace = true
4747

48+
# async
49+
tokio.workspace = true
50+
4851
# revm with required ethereum features
4952
# Note: this must be kept to ensure all features are properly enabled/forwarded
5053
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }

crates/ethereum/node/src/node.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,14 @@ where
254254
let Self { inner } = self;
255255
EthereumAddOns::new(inner.with_rpc_middleware(rpc_middleware))
256256
}
257+
258+
/// Sets the tokio runtime for the RPC servers.
259+
///
260+
/// Caution: This runtime must not be created from within asynchronous context.
261+
pub fn with_tokio_runtime(self, tokio_runtime: Option<tokio::runtime::Handle>) -> Self {
262+
let Self { inner } = self;
263+
Self { inner: inner.with_tokio_runtime(tokio_runtime) }
264+
}
257265
}
258266

259267
impl<N, EthB, PVB, EB, EVB, RpcMiddleware> NodeAddOns<N>

crates/ethereum/node/tests/it/builder.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,44 @@ async fn test_eth_launcher() {
7272
});
7373
}
7474

75+
#[test]
76+
fn test_eth_launcher_with_tokio_runtime() {
77+
// #[tokio::test] can not be used here because we need to create a custom tokio runtime
78+
// and it would be dropped before the test is finished, resulting in a panic.
79+
let main_rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
80+
81+
let custom_rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
82+
83+
main_rt.block_on(async {
84+
let tasks = TaskManager::current();
85+
let config = NodeConfig::test();
86+
let db = create_test_rw_db();
87+
let _builder =
88+
NodeBuilder::new(config)
89+
.with_database(db)
90+
.with_launch_context(tasks.executor())
91+
.with_types_and_provider::<EthereumNode, BlockchainProvider<
92+
NodeTypesWithDBAdapter<EthereumNode, Arc<TempDatabase<DatabaseEnv>>>,
93+
>>()
94+
.with_components(EthereumNode::components())
95+
.with_add_ons(
96+
EthereumAddOns::default().with_tokio_runtime(Some(custom_rt.handle().clone())),
97+
)
98+
.apply(|builder| {
99+
let _ = builder.db();
100+
builder
101+
})
102+
.launch_with_fn(|builder| {
103+
let launcher = EngineNodeLauncher::new(
104+
tasks.executor(),
105+
builder.config().datadir(),
106+
Default::default(),
107+
);
108+
builder.launch_with(launcher)
109+
});
110+
});
111+
}
112+
75113
#[test]
76114
fn test_node_setup() {
77115
let config = NodeConfig::test();

crates/node/builder/src/rpc.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,8 @@ pub struct RpcAddOns<
445445
/// This middleware is applied to all RPC requests across all transports (HTTP, WS, IPC).
446446
/// See [`RpcAddOns::with_rpc_middleware`] for more details.
447447
rpc_middleware: RpcMiddleware,
448+
/// Optional custom tokio runtime for the RPC server.
449+
tokio_runtime: Option<tokio::runtime::Handle>,
448450
}
449451

450452
impl<Node, EthB, PVB, EB, EVB, RpcMiddleware> Debug
@@ -488,6 +490,7 @@ where
488490
engine_api_builder,
489491
engine_validator_builder,
490492
rpc_middleware,
493+
tokio_runtime: None,
491494
}
492495
}
493496

@@ -502,6 +505,7 @@ where
502505
payload_validator_builder,
503506
engine_validator_builder,
504507
rpc_middleware,
508+
tokio_runtime,
505509
..
506510
} = self;
507511
RpcAddOns {
@@ -511,6 +515,7 @@ where
511515
engine_api_builder,
512516
engine_validator_builder,
513517
rpc_middleware,
518+
tokio_runtime,
514519
}
515520
}
516521

@@ -525,6 +530,7 @@ where
525530
engine_api_builder,
526531
engine_validator_builder,
527532
rpc_middleware,
533+
tokio_runtime,
528534
..
529535
} = self;
530536
RpcAddOns {
@@ -534,6 +540,7 @@ where
534540
engine_api_builder,
535541
engine_validator_builder,
536542
rpc_middleware,
543+
tokio_runtime,
537544
}
538545
}
539546

@@ -548,6 +555,7 @@ where
548555
payload_validator_builder,
549556
engine_api_builder,
550557
rpc_middleware,
558+
tokio_runtime,
551559
..
552560
} = self;
553561
RpcAddOns {
@@ -557,6 +565,7 @@ where
557565
engine_api_builder,
558566
engine_validator_builder,
559567
rpc_middleware,
568+
tokio_runtime,
560569
}
561570
}
562571

@@ -608,6 +617,7 @@ where
608617
payload_validator_builder,
609618
engine_api_builder,
610619
engine_validator_builder,
620+
tokio_runtime,
611621
..
612622
} = self;
613623
RpcAddOns {
@@ -617,6 +627,31 @@ where
617627
engine_api_builder,
618628
engine_validator_builder,
619629
rpc_middleware,
630+
tokio_runtime,
631+
}
632+
}
633+
634+
/// Sets the tokio runtime for the RPC servers.
635+
///
636+
/// Caution: This runtime must not be created from within asynchronous context.
637+
pub fn with_tokio_runtime(self, tokio_runtime: Option<tokio::runtime::Handle>) -> Self {
638+
let Self {
639+
hooks,
640+
eth_api_builder,
641+
payload_validator_builder,
642+
engine_validator_builder,
643+
engine_api_builder,
644+
rpc_middleware,
645+
..
646+
} = self;
647+
Self {
648+
hooks,
649+
eth_api_builder,
650+
payload_validator_builder,
651+
engine_validator_builder,
652+
engine_api_builder,
653+
rpc_middleware,
654+
tokio_runtime,
620655
}
621656
}
622657

@@ -632,6 +667,7 @@ where
632667
engine_api_builder,
633668
engine_validator_builder,
634669
rpc_middleware,
670+
tokio_runtime,
635671
} = self;
636672
let rpc_middleware = Stack::new(rpc_middleware, layer);
637673
RpcAddOns {
@@ -641,6 +677,7 @@ where
641677
engine_api_builder,
642678
engine_validator_builder,
643679
rpc_middleware,
680+
tokio_runtime,
644681
}
645682
}
646683

@@ -717,6 +754,7 @@ where
717754
F: FnOnce(RpcModuleContainer<'_, N, EthB::EthApi>) -> eyre::Result<()>,
718755
{
719756
let rpc_middleware = self.rpc_middleware.clone();
757+
let tokio_runtime = self.tokio_runtime.clone();
720758
let setup_ctx = self.setup_rpc_components(ctx, ext).await?;
721759
let RpcSetupContext {
722760
node,
@@ -730,7 +768,11 @@ where
730768
engine_handle,
731769
} = setup_ctx;
732770

733-
let server_config = config.rpc.rpc_server_config().set_rpc_middleware(rpc_middleware);
771+
let server_config = config
772+
.rpc
773+
.rpc_server_config()
774+
.set_rpc_middleware(rpc_middleware)
775+
.with_tokio_runtime(tokio_runtime);
734776
let rpc_server_handle = Self::launch_rpc_server_internal(server_config, &modules).await?;
735777

736778
let handles =
@@ -783,6 +825,7 @@ where
783825
F: FnOnce(RpcModuleContainer<'_, N, EthB::EthApi>) -> eyre::Result<()>,
784826
{
785827
let rpc_middleware = self.rpc_middleware.clone();
828+
let tokio_runtime = self.tokio_runtime.clone();
786829
let setup_ctx = self.setup_rpc_components(ctx, ext).await?;
787830
let RpcSetupContext {
788831
node,
@@ -796,7 +839,11 @@ where
796839
engine_handle,
797840
} = setup_ctx;
798841

799-
let server_config = config.rpc.rpc_server_config().set_rpc_middleware(rpc_middleware);
842+
let server_config = config
843+
.rpc
844+
.rpc_server_config()
845+
.set_rpc_middleware(rpc_middleware)
846+
.with_tokio_runtime(tokio_runtime);
800847

801848
let (rpc, auth) = if disable_auth {
802849
// Only launch the RPC server, use a noop auth handle

crates/optimism/node/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ alloy-rpc-types-engine.workspace = true
5757
alloy-rpc-types-eth.workspace = true
5858
alloy-consensus.workspace = true
5959

60+
# async
61+
tokio.workspace = true
62+
6063
# misc
6164
clap.workspace = true
6265
serde.workspace = true
@@ -65,7 +68,6 @@ eyre.workspace = true
6568
# test-utils dependencies
6669
reth-e2e-test-utils = { workspace = true, optional = true }
6770
alloy-genesis = { workspace = true, optional = true }
68-
tokio = { workspace = true, optional = true }
6971
serde_json = { workspace = true, optional = true }
7072

7173
[dev-dependencies]
@@ -99,7 +101,6 @@ test-utils = [
99101
"reth-tasks",
100102
"reth-e2e-test-utils",
101103
"alloy-genesis",
102-
"tokio",
103104
"serde_json",
104105
"reth-node-builder/test-utils",
105106
"reth-chainspec/test-utils",

crates/optimism/node/src/node.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,8 @@ pub struct OpAddOnsBuilder<NetworkT, RpcMiddleware = Identity> {
658658
min_suggested_priority_fee: u64,
659659
/// RPC middleware to use
660660
rpc_middleware: RpcMiddleware,
661+
/// Optional tokio runtime to use for the RPC server.
662+
tokio_runtime: Option<tokio::runtime::Handle>,
661663
}
662664

663665
impl<NetworkT> Default for OpAddOnsBuilder<NetworkT> {
@@ -671,6 +673,7 @@ impl<NetworkT> Default for OpAddOnsBuilder<NetworkT> {
671673
min_suggested_priority_fee: 1_000_000,
672674
_nt: PhantomData,
673675
rpc_middleware: Identity::new(),
676+
tokio_runtime: None,
674677
}
675678
}
676679
}
@@ -712,6 +715,14 @@ impl<NetworkT, RpcMiddleware> OpAddOnsBuilder<NetworkT, RpcMiddleware> {
712715
self
713716
}
714717

718+
/// Configures a custom tokio runtime for the RPC server.
719+
///
720+
/// Caution: This runtime must not be created from within asynchronous context.
721+
pub fn with_tokio_runtime(mut self, tokio_runtime: Option<tokio::runtime::Handle>) -> Self {
722+
self.tokio_runtime = tokio_runtime;
723+
self
724+
}
725+
715726
/// Configure the RPC middleware to use
716727
pub fn with_rpc_middleware<T>(self, rpc_middleware: T) -> OpAddOnsBuilder<NetworkT, T> {
717728
let Self {
@@ -721,6 +732,7 @@ impl<NetworkT, RpcMiddleware> OpAddOnsBuilder<NetworkT, RpcMiddleware> {
721732
da_config,
722733
enable_tx_conditional,
723734
min_suggested_priority_fee,
735+
tokio_runtime,
724736
_nt,
725737
..
726738
} = self;
@@ -733,6 +745,7 @@ impl<NetworkT, RpcMiddleware> OpAddOnsBuilder<NetworkT, RpcMiddleware> {
733745
min_suggested_priority_fee,
734746
_nt,
735747
rpc_middleware,
748+
tokio_runtime,
736749
}
737750
}
738751
}
@@ -757,6 +770,7 @@ impl<NetworkT, RpcMiddleware> OpAddOnsBuilder<NetworkT, RpcMiddleware> {
757770
min_suggested_priority_fee,
758771
historical_rpc,
759772
rpc_middleware,
773+
tokio_runtime,
760774
..
761775
} = self;
762776

@@ -770,7 +784,8 @@ impl<NetworkT, RpcMiddleware> OpAddOnsBuilder<NetworkT, RpcMiddleware> {
770784
EB::default(),
771785
EVB::default(),
772786
rpc_middleware,
773-
),
787+
)
788+
.with_tokio_runtime(tokio_runtime),
774789
da_config.unwrap_or_default(),
775790
sequencer_url,
776791
sequencer_headers,

crates/rpc/rpc-builder/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,8 @@ impl<RpcMiddleware> RpcServerConfig<RpcMiddleware> {
11921192
}
11931193

11941194
/// Configures a custom tokio runtime for the rpc server.
1195-
pub fn with_tokio_runtime(mut self, tokio_runtime: tokio::runtime::Handle) -> Self {
1195+
pub fn with_tokio_runtime(mut self, tokio_runtime: Option<tokio::runtime::Handle>) -> Self {
1196+
let Some(tokio_runtime) = tokio_runtime else { return self };
11961197
if let Some(http_server_config) = self.http_server_config {
11971198
self.http_server_config =
11981199
Some(http_server_config.custom_tokio_runtime(tokio_runtime.clone()));

0 commit comments

Comments
 (0)