mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(op, cli): add cli option to enable tx conditional (#14421)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -8525,6 +8525,7 @@ dependencies = [
|
|||||||
"reth-primitives-traits",
|
"reth-primitives-traits",
|
||||||
"reth-provider",
|
"reth-provider",
|
||||||
"reth-revm",
|
"reth-revm",
|
||||||
|
"reth-rpc-eth-api",
|
||||||
"reth-rpc-eth-types",
|
"reth-rpc-eth-types",
|
||||||
"reth-rpc-server-types",
|
"reth-rpc-server-types",
|
||||||
"reth-tasks",
|
"reth-tasks",
|
||||||
|
|||||||
@ -31,6 +31,7 @@ reth-evm.workspace = true
|
|||||||
reth-revm = { workspace = true, features = ["std"] }
|
reth-revm = { workspace = true, features = ["std"] }
|
||||||
reth-trie-db.workspace = true
|
reth-trie-db.workspace = true
|
||||||
reth-rpc-server-types.workspace = true
|
reth-rpc-server-types.workspace = true
|
||||||
|
reth-rpc-eth-api.workspace = true
|
||||||
reth-rpc-eth-types.workspace = true
|
reth-rpc-eth-types.workspace = true
|
||||||
reth-tasks = { workspace = true, optional = true }
|
reth-tasks = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,10 @@ pub struct RollupArgs {
|
|||||||
/// enables discovery v4 if provided
|
/// enables discovery v4 if provided
|
||||||
#[arg(long = "rollup.discovery.v4", default_value = "false")]
|
#[arg(long = "rollup.discovery.v4", default_value = "false")]
|
||||||
pub discovery_v4: bool,
|
pub discovery_v4: bool,
|
||||||
|
|
||||||
|
/// Enable transaction conditional support on sequencer
|
||||||
|
#[arg(long = "rollup.enable-tx-conditional", default_value = "false")]
|
||||||
|
pub enable_tx_conditional: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::derivable_impls)]
|
#[allow(clippy::derivable_impls)]
|
||||||
@ -44,6 +48,7 @@ impl Default for RollupArgs {
|
|||||||
enable_genesis_walkback: false,
|
enable_genesis_walkback: false,
|
||||||
compute_pending_block: false,
|
compute_pending_block: false,
|
||||||
discovery_v4: false,
|
discovery_v4: false,
|
||||||
|
enable_tx_conditional: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,12 +119,22 @@ mod tests {
|
|||||||
assert_eq!(args, expected_args);
|
assert_eq!(args, expected_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_optimism_enable_tx_conditional() {
|
||||||
|
let expected_args = RollupArgs { enable_tx_conditional: true, ..Default::default() };
|
||||||
|
let args =
|
||||||
|
CommandParser::<RollupArgs>::parse_from(["reth", "--rollup.enable-tx-conditional"])
|
||||||
|
.args;
|
||||||
|
assert_eq!(args, expected_args);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_optimism_many_args() {
|
fn test_parse_optimism_many_args() {
|
||||||
let expected_args = RollupArgs {
|
let expected_args = RollupArgs {
|
||||||
disable_txpool_gossip: true,
|
disable_txpool_gossip: true,
|
||||||
compute_pending_block: true,
|
compute_pending_block: true,
|
||||||
enable_genesis_walkback: true,
|
enable_genesis_walkback: true,
|
||||||
|
enable_tx_conditional: true,
|
||||||
sequencer_http: Some("http://host:port".into()),
|
sequencer_http: Some("http://host:port".into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -128,6 +143,7 @@ mod tests {
|
|||||||
"--rollup.disable-tx-pool-gossip",
|
"--rollup.disable-tx-pool-gossip",
|
||||||
"--rollup.compute-pending-block",
|
"--rollup.compute-pending-block",
|
||||||
"--rollup.enable-genesis-walkback",
|
"--rollup.enable-genesis-walkback",
|
||||||
|
"--rollup.enable-tx-conditional",
|
||||||
"--rollup.sequencer-http",
|
"--rollup.sequencer-http",
|
||||||
"http://host:port",
|
"http://host:port",
|
||||||
])
|
])
|
||||||
|
|||||||
@ -34,11 +34,14 @@ use reth_optimism_payload_builder::{
|
|||||||
};
|
};
|
||||||
use reth_optimism_primitives::{DepositReceipt, OpPrimitives, OpReceipt, OpTransactionSigned};
|
use reth_optimism_primitives::{DepositReceipt, OpPrimitives, OpReceipt, OpTransactionSigned};
|
||||||
use reth_optimism_rpc::{
|
use reth_optimism_rpc::{
|
||||||
|
eth::ext::OpEthExtApi,
|
||||||
miner::{MinerApiExtServer, OpMinerExtApi},
|
miner::{MinerApiExtServer, OpMinerExtApi},
|
||||||
witness::{DebugExecutionWitnessApiServer, OpDebugWitnessApi},
|
witness::{DebugExecutionWitnessApiServer, OpDebugWitnessApi},
|
||||||
OpEthApi, OpEthApiError, SequencerClient,
|
OpEthApi, OpEthApiError, SequencerClient,
|
||||||
};
|
};
|
||||||
|
use reth_optimism_txpool::conditional::MaybeConditionalTransaction;
|
||||||
use reth_provider::{providers::ProviderFactoryBuilder, CanonStateSubscriptions, EthStorage};
|
use reth_provider::{providers::ProviderFactoryBuilder, CanonStateSubscriptions, EthStorage};
|
||||||
|
use reth_rpc_eth_api::ext::L2EthApiExtServer;
|
||||||
use reth_rpc_eth_types::error::FromEvmError;
|
use reth_rpc_eth_types::error::FromEvmError;
|
||||||
use reth_rpc_server_types::RethRpcModule;
|
use reth_rpc_server_types::RethRpcModule;
|
||||||
use reth_tracing::tracing::{debug, info};
|
use reth_tracing::tracing::{debug, info};
|
||||||
@ -182,6 +185,7 @@ where
|
|||||||
Self::AddOns::builder()
|
Self::AddOns::builder()
|
||||||
.with_sequencer(self.args.sequencer_http.clone())
|
.with_sequencer(self.args.sequencer_http.clone())
|
||||||
.with_da_config(self.da_config.clone())
|
.with_da_config(self.da_config.clone())
|
||||||
|
.with_enable_tx_conditional(self.args.enable_tx_conditional)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,6 +214,11 @@ pub struct OpAddOns<N: FullNodeComponents> {
|
|||||||
>,
|
>,
|
||||||
/// Data availability configuration for the OP builder.
|
/// Data availability configuration for the OP builder.
|
||||||
pub da_config: OpDAConfig,
|
pub da_config: OpDAConfig,
|
||||||
|
/// Sequencer client, configured to forward submitted transactions to sequencer of given OP
|
||||||
|
/// network.
|
||||||
|
pub sequencer_client: Option<SequencerClient>,
|
||||||
|
/// Enable transaction conditionals.
|
||||||
|
enable_tx_conditional: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>> Default for OpAddOns<N> {
|
impl<N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>> Default for OpAddOns<N> {
|
||||||
@ -237,6 +246,7 @@ where
|
|||||||
Evm: ConfigureEvmEnv<TxEnv = TxEnv>,
|
Evm: ConfigureEvmEnv<TxEnv = TxEnv>,
|
||||||
>,
|
>,
|
||||||
OpEthApiError: FromEvmError<N::Evm>,
|
OpEthApiError: FromEvmError<N::Evm>,
|
||||||
|
<<N as FullNodeComponents>::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction,
|
||||||
{
|
{
|
||||||
type Handle = RpcHandle<N, OpEthApi<N>>;
|
type Handle = RpcHandle<N, OpEthApi<N>>;
|
||||||
|
|
||||||
@ -244,7 +254,7 @@ where
|
|||||||
self,
|
self,
|
||||||
ctx: reth_node_api::AddOnsContext<'_, N>,
|
ctx: reth_node_api::AddOnsContext<'_, N>,
|
||||||
) -> eyre::Result<Self::Handle> {
|
) -> eyre::Result<Self::Handle> {
|
||||||
let Self { rpc_add_ons, da_config } = self;
|
let Self { rpc_add_ons, da_config, sequencer_client, enable_tx_conditional } = self;
|
||||||
|
|
||||||
let builder = reth_optimism_payload_builder::OpPayloadBuilder::new(
|
let builder = reth_optimism_payload_builder::OpPayloadBuilder::new(
|
||||||
ctx.node.pool().clone(),
|
ctx.node.pool().clone(),
|
||||||
@ -260,6 +270,11 @@ where
|
|||||||
);
|
);
|
||||||
let miner_ext = OpMinerExtApi::new(da_config);
|
let miner_ext = OpMinerExtApi::new(da_config);
|
||||||
|
|
||||||
|
let tx_conditional_ext: OpEthExtApi<N::Pool, N::Provider> = OpEthExtApi::new(
|
||||||
|
sequencer_client,
|
||||||
|
ctx.node.pool().clone(),
|
||||||
|
ctx.node.provider().clone(),
|
||||||
|
);
|
||||||
rpc_add_ons
|
rpc_add_ons
|
||||||
.launch_add_ons_with(ctx, move |modules, auth_modules| {
|
.launch_add_ons_with(ctx, move |modules, auth_modules| {
|
||||||
debug!(target: "reth::cli", "Installing debug payload witness rpc endpoint");
|
debug!(target: "reth::cli", "Installing debug payload witness rpc endpoint");
|
||||||
@ -277,6 +292,14 @@ where
|
|||||||
auth_modules.merge_auth_methods(miner_ext.into_rpc())?;
|
auth_modules.merge_auth_methods(miner_ext.into_rpc())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if enable_tx_conditional {
|
||||||
|
// extend the eth namespace if configured in the regular http server
|
||||||
|
modules.merge_if_module_configured(
|
||||||
|
RethRpcModule::Eth,
|
||||||
|
tx_conditional_ext.into_rpc(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -295,6 +318,7 @@ where
|
|||||||
Evm: ConfigureEvm<TxEnv = TxEnv>,
|
Evm: ConfigureEvm<TxEnv = TxEnv>,
|
||||||
>,
|
>,
|
||||||
OpEthApiError: FromEvmError<N::Evm>,
|
OpEthApiError: FromEvmError<N::Evm>,
|
||||||
|
<<N as FullNodeComponents>::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction,
|
||||||
{
|
{
|
||||||
type EthApi = OpEthApi<N>;
|
type EthApi = OpEthApi<N>;
|
||||||
|
|
||||||
@ -329,6 +353,8 @@ pub struct OpAddOnsBuilder {
|
|||||||
sequencer_client: Option<SequencerClient>,
|
sequencer_client: Option<SequencerClient>,
|
||||||
/// Data availability configuration for the OP builder.
|
/// Data availability configuration for the OP builder.
|
||||||
da_config: Option<OpDAConfig>,
|
da_config: Option<OpDAConfig>,
|
||||||
|
/// Enable transaction conditionals.
|
||||||
|
enable_tx_conditional: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpAddOnsBuilder {
|
impl OpAddOnsBuilder {
|
||||||
@ -343,6 +369,12 @@ impl OpAddOnsBuilder {
|
|||||||
self.da_config = Some(da_config);
|
self.da_config = Some(da_config);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configure if transaction conditional should be enabled.
|
||||||
|
pub fn with_enable_tx_conditional(mut self, enable_tx_conditional: bool) -> Self {
|
||||||
|
self.enable_tx_conditional = enable_tx_conditional;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpAddOnsBuilder {
|
impl OpAddOnsBuilder {
|
||||||
@ -351,15 +383,20 @@ impl OpAddOnsBuilder {
|
|||||||
where
|
where
|
||||||
N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>,
|
N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>,
|
||||||
{
|
{
|
||||||
let Self { sequencer_client, da_config } = self;
|
let Self { sequencer_client, da_config, enable_tx_conditional } = self;
|
||||||
|
|
||||||
|
let sequencer_client_clone = sequencer_client.clone();
|
||||||
OpAddOns {
|
OpAddOns {
|
||||||
rpc_add_ons: RpcAddOns::new(
|
rpc_add_ons: RpcAddOns::new(
|
||||||
move |ctx| OpEthApi::<N>::builder().with_sequencer(sequencer_client).build(ctx),
|
move |ctx| {
|
||||||
|
OpEthApi::<N>::builder().with_sequencer(sequencer_client_clone).build(ctx)
|
||||||
|
},
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
),
|
),
|
||||||
da_config: da_config.unwrap_or_default(),
|
da_config: da_config.unwrap_or_default(),
|
||||||
|
sequencer_client,
|
||||||
|
enable_tx_conditional,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use super::{OpEthApiInner, OpNodeCore};
|
//! Eth API extension.
|
||||||
|
|
||||||
use crate::{error::TxConditionalErr, OpEthApiError, SequencerClient};
|
use crate::{error::TxConditionalErr, OpEthApiError, SequencerClient};
|
||||||
use alloy_consensus::BlockHeader;
|
use alloy_consensus::BlockHeader;
|
||||||
use alloy_eips::BlockNumberOrTag;
|
use alloy_eips::BlockNumberOrTag;
|
||||||
@ -15,42 +16,73 @@ use std::sync::Arc;
|
|||||||
/// Maximum execution const for conditional transactions.
|
/// Maximum execution const for conditional transactions.
|
||||||
const MAX_CONDITIONAL_EXECUTION_COST: u64 = 5000;
|
const MAX_CONDITIONAL_EXECUTION_COST: u64 = 5000;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct OpEthExtApiInner<Pool, Provider> {
|
||||||
|
/// The transaction pool of the node.
|
||||||
|
pool: Pool,
|
||||||
|
/// The provider type used to interact with the node.
|
||||||
|
provider: Provider,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Pool, Provider> OpEthExtApiInner<Pool, Provider> {
|
||||||
|
fn new(pool: Pool, provider: Provider) -> Self {
|
||||||
|
Self { pool, provider }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pool(&self) -> &Pool {
|
||||||
|
&self.pool
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn provider(&self) -> &Provider {
|
||||||
|
&self.provider
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// OP-Reth `Eth` API extensions implementation.
|
/// OP-Reth `Eth` API extensions implementation.
|
||||||
///
|
///
|
||||||
/// Separate from [`super::OpEthApi`] to allow to enable it conditionally,
|
/// Separate from [`super::OpEthApi`] to allow to enable it conditionally,
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) struct OpEthApiExt<N: OpNodeCore> {
|
pub struct OpEthExtApi<Pool, Provider> {
|
||||||
/// Gateway to node's core components.
|
/// Sequencer client, configured to forward submitted transactions to sequencer of given OP
|
||||||
inner: Arc<OpEthApiInner<N>>,
|
/// network.
|
||||||
|
sequencer_client: Option<SequencerClient>,
|
||||||
|
inner: Arc<OpEthExtApiInner<Pool, Provider>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N> OpEthApiExt<N>
|
impl<Pool, Provider> OpEthExtApi<Pool, Provider>
|
||||||
where
|
where
|
||||||
N: OpNodeCore<Provider: BlockReaderIdExt + Clone + 'static>,
|
Provider: BlockReaderIdExt + Clone + 'static,
|
||||||
{
|
{
|
||||||
|
/// Creates a new [`OpEthExtApi`].
|
||||||
|
pub fn new(sequencer_client: Option<SequencerClient>, pool: Pool, provider: Provider) -> Self {
|
||||||
|
let inner = Arc::new(OpEthExtApiInner::new(pool, provider));
|
||||||
|
Self { sequencer_client, inner }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the configured sequencer client, if any.
|
/// Returns the configured sequencer client, if any.
|
||||||
pub(crate) fn sequencer_client(&self) -> Option<&SequencerClient> {
|
fn sequencer_client(&self) -> Option<&SequencerClient> {
|
||||||
self.inner.sequencer_client()
|
self.sequencer_client.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pool(&self) -> &N::Pool {
|
fn pool(&self) -> &Pool {
|
||||||
self.inner.eth_api.pool()
|
self.inner.pool()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn provider(&self) -> &N::Provider {
|
fn provider(&self) -> &Provider {
|
||||||
self.inner.eth_api.provider()
|
self.inner.provider()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl<N> L2EthApiExtServer for OpEthApiExt<N>
|
impl<Pool, Provider> L2EthApiExtServer for OpEthExtApi<Pool, Provider>
|
||||||
where
|
where
|
||||||
N: OpNodeCore + 'static,
|
Provider: BlockReaderIdExt + StateProviderFactory + Clone + 'static,
|
||||||
N::Provider: BlockReaderIdExt + StateProviderFactory,
|
Pool: TransactionPool<Transaction: MaybeConditionalTransaction> + 'static,
|
||||||
N::Pool: TransactionPool<Transaction: MaybeConditionalTransaction>,
|
|
||||||
{
|
{
|
||||||
async fn send_raw_transaction_conditional(
|
async fn send_raw_transaction_conditional(
|
||||||
&self,
|
&self,
|
||||||
@ -67,7 +99,7 @@ where
|
|||||||
OpEthApiError::Eth(reth_rpc_eth_types::EthApiError::FailedToDecodeSignedTransaction)
|
OpEthApiError::Eth(reth_rpc_eth_types::EthApiError::FailedToDecodeSignedTransaction)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut tx = <N::Pool as TransactionPool>::Transaction::from_pooled(recovered_tx);
|
let mut tx = <Pool as TransactionPool>::Transaction::from_pooled(recovered_tx);
|
||||||
|
|
||||||
// get current header
|
// get current header
|
||||||
let header_not_found = || {
|
let header_not_found = || {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
//! OP-Reth `eth_` endpoint implementation.
|
//! OP-Reth `eth_` endpoint implementation.
|
||||||
|
|
||||||
|
pub mod ext;
|
||||||
pub mod receipt;
|
pub mod receipt;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
|
|
||||||
mod block;
|
mod block;
|
||||||
mod call;
|
mod call;
|
||||||
mod ext;
|
|
||||||
mod pending_block;
|
mod pending_block;
|
||||||
|
|
||||||
pub use receipt::{OpReceiptBuilder, OpReceiptFieldsBuilder};
|
pub use receipt::{OpReceiptBuilder, OpReceiptFieldsBuilder};
|
||||||
|
|||||||
Reference in New Issue
Block a user