diff --git a/Cargo.lock b/Cargo.lock index d645996b5..306e6a992 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5418,6 +5418,19 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "op-alloy-rpc-jsonrpsee" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98debc5266443e64e03195cd1a3b6cdbe8d8679e9d8c4b76a3670d24b2e267a" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "jsonrpsee", + "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", +] + [[package]] name = "op-alloy-rpc-types" version = "0.7.3" @@ -8512,6 +8525,7 @@ dependencies = [ "jsonrpsee-types", "op-alloy-consensus", "op-alloy-network", + "op-alloy-rpc-jsonrpsee", "op-alloy-rpc-types", "op-alloy-rpc-types-engine", "parking_lot", diff --git a/Cargo.toml b/Cargo.toml index 18b2ab655..f9fc6f2ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -472,6 +472,7 @@ alloy-transport-ws = { version = "0.7.2", default-features = false } # op op-alloy-rpc-types = "0.7.3" op-alloy-rpc-types-engine = "0.7.3" +op-alloy-rpc-jsonrpsee = "0.7.3" op-alloy-network = "0.7.3" op-alloy-consensus = "0.7.3" diff --git a/crates/node/builder/src/rpc.rs b/crates/node/builder/src/rpc.rs index 24b7db77d..edc10fecc 100644 --- a/crates/node/builder/src/rpc.rs +++ b/crates/node/builder/src/rpc.rs @@ -419,7 +419,7 @@ where ext: F, ) -> eyre::Result> where - F: FnOnce(&mut TransportRpcModules) -> eyre::Result<()>, + F: FnOnce(&mut TransportRpcModules, &mut AuthRpcModule) -> eyre::Result<()>, { let Self { eth_api_builder, engine_validator_builder, hooks, _pd: _ } = self; @@ -477,7 +477,7 @@ where let RpcHooks { on_rpc_started, extend_rpc_modules } = hooks; - ext(ctx.modules)?; + ext(ctx.modules, ctx.auth_module)?; extend_rpc_modules.extend_rpc_modules(ctx)?; let server_config = config.rpc.rpc_server_config(); @@ -537,7 +537,7 @@ where type Handle = RpcHandle; async fn launch_add_ons(self, ctx: AddOnsContext<'_, N>) -> eyre::Result { - self.launch_add_ons_with(ctx, |_| Ok(())).await + self.launch_add_ons_with(ctx, |_, _| Ok(())).await } } diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index b2203331d..c75521352 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -27,9 +27,10 @@ use reth_node_builder::{ use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::OpBeaconConsensus; use reth_optimism_evm::{OpEvmConfig, OpExecutionStrategyFactory}; -use reth_optimism_payload_builder::builder::OpPayloadTransactions; +use reth_optimism_payload_builder::{builder::OpPayloadTransactions, config::OpDAConfig}; use reth_optimism_primitives::OpPrimitives; use reth_optimism_rpc::{ + miner::{MinerApiExtServer, OpMinerExtApi}, witness::{DebugExecutionWitnessApiServer, OpDebugWitnessApi}, OpEthApi, SequencerClient, }; @@ -112,12 +113,25 @@ impl ChainStorage for OpStorage { pub struct OpNode { /// Additional Optimism args pub args: RollupArgs, + /// Data availability configuration for the OP builder. + /// + /// Used to throttle the size of the data availability payloads (configured by the batcher via + /// the `miner_` api). + /// + /// By default no throttling is applied. + pub da_config: OpDAConfig, } impl OpNode { /// Creates a new instance of the Optimism node type. - pub const fn new(args: RollupArgs) -> Self { - Self { args } + pub fn new(args: RollupArgs) -> Self { + Self { args, da_config: OpDAConfig::default() } + } + + /// Configure the data availability configuration for the OP builder. + pub fn with_da_config(mut self, da_config: OpDAConfig) -> Self { + self.da_config = da_config; + self } /// Returns the components for the given [`RollupArgs`]. @@ -182,7 +196,10 @@ where } fn add_ons(&self) -> Self::AddOns { - Self::AddOns::builder().with_sequencer(self.args.sequencer_http.clone()).build() + Self::AddOns::builder() + .with_sequencer(self.args.sequencer_http.clone()) + .with_da_config(self.da_config.clone()) + .build() } } @@ -199,7 +216,13 @@ impl NodeTypesWithEngine for OpNode { /// Add-ons w.r.t. optimism. #[derive(Debug)] -pub struct OpAddOns(pub RpcAddOns, OpEngineValidatorBuilder>); +pub struct OpAddOns { + /// Rpc add-ons responsible for launching the RPC servers and instantiating the RPC handlers + /// and eth-api. + pub rpc_add_ons: RpcAddOns, OpEngineValidatorBuilder>, + /// Data availability configuration for the OP builder. + pub da_config: OpDAConfig, +} impl>> Default for OpAddOns { fn default() -> Self { @@ -228,14 +251,29 @@ where self, ctx: reth_node_api::AddOnsContext<'_, N>, ) -> eyre::Result { + let Self { rpc_add_ons, da_config } = self; // install additional OP specific rpc methods let debug_ext = OpDebugWitnessApi::new(ctx.node.provider().clone(), ctx.node.evm_config().clone()); + let miner_ext = OpMinerExtApi::new(da_config); - self.0 - .launch_add_ons_with(ctx, move |modules| { + rpc_add_ons + .launch_add_ons_with(ctx, move |modules, auth_modules| { debug!(target: "reth::cli", "Installing debug payload witness rpc endpoint"); modules.merge_if_module_configured(RethRpcModule::Debug, debug_ext.into_rpc())?; + + // extend the miner namespace if configured in the regular http server + modules.merge_if_module_configured( + RethRpcModule::Miner, + miner_ext.clone().into_rpc(), + )?; + + // install the miner extension in the authenticated if configured + if modules.module_config().contains_any(&RethRpcModule::Miner) { + debug!(target: "reth::cli", "Installing miner DA rpc enddpoint"); + auth_modules.merge_auth_methods(miner_ext.into_rpc())?; + } + Ok(()) }) .await @@ -253,7 +291,7 @@ where type EthApi = OpEthApi; fn hooks_mut(&mut self) -> &mut reth_node_builder::rpc::RpcHooks { - self.0.hooks_mut() + self.rpc_add_ons.hooks_mut() } } @@ -276,6 +314,8 @@ pub struct OpAddOnsBuilder { /// Sequencer client, configured to forward submitted transactions to sequencer of given OP /// network. sequencer_client: Option, + /// Data availability configuration for the OP builder. + da_config: Option, } impl OpAddOnsBuilder { @@ -284,6 +324,12 @@ impl OpAddOnsBuilder { self.sequencer_client = sequencer_client.map(SequencerClient::new); self } + + /// Configure the data availability configuration for the OP builder. + pub fn with_da_config(mut self, da_config: OpDAConfig) -> Self { + self.da_config = Some(da_config); + self + } } impl OpAddOnsBuilder { @@ -292,12 +338,15 @@ impl OpAddOnsBuilder { where N: FullNodeComponents>, { - let Self { sequencer_client, .. } = self; + let Self { sequencer_client, da_config } = self; - OpAddOns(RpcAddOns::new( - move |ctx| OpEthApi::::builder().with_sequencer(sequencer_client).build(ctx), - Default::default(), - )) + OpAddOns { + rpc_add_ons: RpcAddOns::new( + move |ctx| OpEthApi::::builder().with_sequencer(sequencer_client).build(ctx), + Default::default(), + ), + da_config: da_config.unwrap_or_default(), + } } } diff --git a/crates/optimism/rpc/Cargo.toml b/crates/optimism/rpc/Cargo.toml index 968beaf9e..d4a0b1fce 100644 --- a/crates/optimism/rpc/Cargo.toml +++ b/crates/optimism/rpc/Cargo.toml @@ -45,6 +45,7 @@ alloy-consensus.workspace = true op-alloy-network.workspace = true op-alloy-rpc-types.workspace = true op-alloy-rpc-types-engine.workspace = true +op-alloy-rpc-jsonrpsee.workspace = true op-alloy-consensus.workspace = true revm.workspace = true diff --git a/crates/optimism/rpc/src/lib.rs b/crates/optimism/rpc/src/lib.rs index 0fa0debdf..b76058ce5 100644 --- a/crates/optimism/rpc/src/lib.rs +++ b/crates/optimism/rpc/src/lib.rs @@ -12,6 +12,7 @@ pub mod error; pub mod eth; +pub mod miner; pub mod sequencer; pub mod witness; diff --git a/crates/optimism/rpc/src/miner.rs b/crates/optimism/rpc/src/miner.rs new file mode 100644 index 000000000..bfdee4676 --- /dev/null +++ b/crates/optimism/rpc/src/miner.rs @@ -0,0 +1,32 @@ +//! Miner API extension for OP. + +use alloy_primitives::U64; +use jsonrpsee_core::{async_trait, RpcResult}; +pub use op_alloy_rpc_jsonrpsee::traits::MinerApiExtServer; +use reth_optimism_payload_builder::config::OpDAConfig; +use tracing::debug; + +/// Miner API extension for OP, exposes settings for the data availability configuration via the +/// `miner_` API. +#[derive(Debug, Clone)] +pub struct OpMinerExtApi { + da_config: OpDAConfig, +} + +impl OpMinerExtApi { + /// Instantiate the miner API extension with the given, sharable data availability + /// configuration. + pub const fn new(da_config: OpDAConfig) -> Self { + Self { da_config } + } +} + +#[async_trait] +impl MinerApiExtServer for OpMinerExtApi { + /// Handler for `miner_setMaxDASize` RPC method. + async fn set_max_da_size(&self, max_tx_size: U64, max_block_size: U64) -> RpcResult<()> { + debug!(target: "rpc", "Setting max DA size: tx={}, block={}", max_tx_size, max_block_size); + self.da_config.set_max_da_size(max_tx_size.to(), max_block_size.to()); + Ok(()) + } +}