feat: configurable EVM execution limits (#21088)

Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
This commit is contained in:
Rez
2026-01-27 02:27:09 +11:00
committed by GitHub
parent ab685579f0
commit b87cde5479
28 changed files with 458 additions and 366 deletions

5
Cargo.lock generated
View File

@@ -9130,6 +9130,7 @@ dependencies = [
"reth-eth-wire-types",
"reth-ethereum-forks",
"reth-ethereum-primitives",
"reth-evm-ethereum",
"reth-fs-util",
"reth-metrics",
"reth-net-banlist",
@@ -9997,6 +9998,7 @@ dependencies = [
"parking_lot",
"reth-chain-state",
"reth-chainspec",
"reth-evm",
"reth-metrics",
"reth-optimism-chainspec",
"reth-optimism-evm",
@@ -11051,6 +11053,8 @@ dependencies = [
"reth-chainspec",
"reth-eth-wire-types",
"reth-ethereum-primitives",
"reth-evm",
"reth-evm-ethereum",
"reth-execution-types",
"reth-fs-util",
"reth-metrics",
@@ -11059,6 +11063,7 @@ dependencies = [
"reth-storage-api",
"reth-tasks",
"reth-tracing",
"revm",
"revm-interpreter",
"revm-primitives",
"rustc-hash",

View File

@@ -25,6 +25,7 @@ pub use alloy_chains::{Chain, ChainKind, NamedChain};
/// Re-export for convenience
pub use reth_ethereum_forks::*;
pub use alloy_evm::EvmLimitParams;
pub use api::EthChainSpec;
pub use info::ChainInfo;
#[cfg(any(test, feature = "test-utils"))]

View File

@@ -1,14 +1,11 @@
//! Collection of methods for block validation.
use alloy_consensus::{BlockHeader as _, Transaction, EMPTY_OMMER_ROOT_HASH};
use alloy_consensus::{BlockHeader as _, EMPTY_OMMER_ROOT_HASH};
use alloy_eips::{eip4844::DATA_GAS_PER_BLOB, eip7840::BlobParams};
use reth_chainspec::{EthChainSpec, EthereumHardfork, EthereumHardforks};
use reth_consensus::{ConsensusError, TxGasLimitTooHighErr};
use reth_consensus::ConsensusError;
use reth_primitives_traits::{
constants::{
GAS_LIMIT_BOUND_DIVISOR, MAXIMUM_GAS_LIMIT_BLOCK, MAX_TX_GAS_LIMIT_OSAKA, MINIMUM_GAS_LIMIT,
},
transaction::TxHashRef,
constants::{GAS_LIMIT_BOUND_DIVISOR, MAXIMUM_GAS_LIMIT_BLOCK, MINIMUM_GAS_LIMIT},
Block, BlockBody, BlockHeader, GotExpected, SealedBlock, SealedHeader,
};
@@ -146,7 +143,7 @@ pub fn validate_block_pre_execution<B, ChainSpec>(
) -> Result<(), ConsensusError>
where
B: Block,
ChainSpec: EthereumHardforks,
ChainSpec: EthChainSpec + EthereumHardforks,
{
post_merge_hardfork_fields(block, chain_spec)?;
@@ -154,19 +151,6 @@ where
if let Err(error) = block.ensure_transaction_root_valid() {
return Err(ConsensusError::BodyTransactionRootDiff(error.into()))
}
// EIP-7825 validation
if chain_spec.is_osaka_active_at_timestamp(block.timestamp()) {
for tx in block.body().transactions() {
if tx.gas_limit() > MAX_TX_GAS_LIMIT_OSAKA {
return Err(TxGasLimitTooHighErr {
tx_hash: *tx.tx_hash(),
gas_limit: tx.gas_limit(),
max_allowed: MAX_TX_GAS_LIMIT_OSAKA,
}
.into());
}
}
}
Ok(())
}

View File

@@ -59,6 +59,7 @@ std = [
"reth-storage-errors/std",
]
test-utils = [
"std",
"dep:parking_lot",
"dep:derive_more",
"reth-chainspec/test-utils",

View File

@@ -18,7 +18,7 @@ use reth_evm::{
};
use reth_network::{primitives::BasicNetworkPrimitives, NetworkHandle, PeersInfo};
use reth_node_api::{
AddOnsContext, BlockTy, FullNodeComponents, HeaderTy, NodeAddOns, NodePrimitives,
AddOnsContext, FullNodeComponents, HeaderTy, NodeAddOns, NodePrimitives,
PayloadAttributesBuilder, PrimitivesTy, TxTy,
};
use reth_node_builder::{
@@ -53,8 +53,8 @@ use reth_rpc_eth_types::{error::FromEvmError, EthApiError};
use reth_rpc_server_types::RethRpcModule;
use reth_tracing::tracing::{debug, info};
use reth_transaction_pool::{
blobstore::DiskFileBlobStore, EthPooledTransaction, EthTransactionPool, PoolPooledTx,
PoolTransaction, TransactionPool, TransactionValidationTaskExecutor,
blobstore::DiskFileBlobStore, EthTransactionPool, PoolPooledTx, PoolTransaction,
TransactionPool, TransactionValidationTaskExecutor,
};
use revm::context::TxEnv;
use std::{marker::PhantomData, sync::Arc, time::SystemTime};
@@ -456,18 +456,22 @@ pub struct EthereumPoolBuilder {
// TODO add options for txpool args
}
impl<Types, Node> PoolBuilder<Node> for EthereumPoolBuilder
impl<Types, Node, Evm> PoolBuilder<Node, Evm> for EthereumPoolBuilder
where
Types: NodeTypes<
ChainSpec: EthereumHardforks,
Primitives: NodePrimitives<SignedTx = TransactionSigned>,
>,
Node: FullNodeTypes<Types = Types>,
Evm: ConfigureEvm<Primitives = PrimitivesTy<Types>> + Clone + 'static,
{
type Pool =
EthTransactionPool<Node::Provider, DiskFileBlobStore, EthPooledTransaction, BlockTy<Types>>;
type Pool = EthTransactionPool<Node::Provider, DiskFileBlobStore, Evm>;
async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
async fn build_pool(
self,
ctx: &BuilderContext<Node>,
evm_config: Evm,
) -> eyre::Result<Self::Pool> {
let pool_config = ctx.pool_config();
let blobs_disabled = ctx.config().txpool.disable_blobs_support ||
@@ -493,17 +497,17 @@ where
let blob_store =
reth_node_builder::components::create_blob_store_with_cache(ctx, blob_cache_size)?;
let validator = TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone())
.with_head_timestamp(ctx.head().timestamp)
.set_eip4844(!blobs_disabled)
.kzg_settings(ctx.kzg_settings()?)
.with_max_tx_input_bytes(ctx.config().txpool.max_tx_input_bytes)
.with_local_transactions_config(pool_config.local_transactions_config.clone())
.set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap)
.with_max_tx_gas_limit(ctx.config().txpool.max_tx_gas_limit)
.with_minimum_priority_fee(ctx.config().txpool.minimum_priority_fee)
.with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
.build_with_tasks(ctx.task_executor().clone(), blob_store.clone());
let validator =
TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone(), evm_config)
.set_eip4844(!blobs_disabled)
.kzg_settings(ctx.kzg_settings()?)
.with_max_tx_input_bytes(ctx.config().txpool.max_tx_input_bytes)
.with_local_transactions_config(pool_config.local_transactions_config.clone())
.set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap)
.with_max_tx_gas_limit(ctx.config().txpool.max_tx_gas_limit)
.with_minimum_priority_fee(ctx.config().txpool.minimum_priority_fee)
.with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
.build_with_tasks(ctx.task_executor().clone(), blob_store.clone());
if validator.validator().eip4844() {
// initializing the KZG settings can be expensive, this should be done upfront so that

View File

@@ -35,7 +35,7 @@ use reth_execution_errors::BlockExecutionError;
use reth_primitives_traits::{
BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
};
use revm::{context::TxEnv, database::State};
use revm::{context::TxEnv, database::State, primitives::hardfork::SpecId};
pub mod either;
/// EVM environment configuration.
@@ -203,6 +203,7 @@ pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
+ FromRecoveredTx<TxTy<Self::Primitives>>
+ FromTxWithEncoded<TxTy<Self::Primitives>>,
Precompiles = PrecompilesMap,
Spec: Into<SpecId>,
>,
>;

View File

@@ -66,13 +66,17 @@ use tokio::sync::mpsc::{Sender, UnboundedReceiver};
#[non_exhaustive]
pub struct TestPoolBuilder;
impl<Node> PoolBuilder<Node> for TestPoolBuilder
impl<Node, Evm: Send> PoolBuilder<Node, Evm> for TestPoolBuilder
where
Node: FullNodeTypes<Types: NodeTypes<Primitives: NodePrimitives<SignedTx = TransactionSigned>>>,
{
type Pool = TestPool;
async fn build_pool(self, _ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
async fn build_pool(
self,
_ctx: &BuilderContext<Node>,
_evm_config: Evm,
) -> eyre::Result<Self::Pool> {
Ok(testing_pool())
}
}

View File

@@ -14,6 +14,7 @@ workspace = true
[dependencies]
# reth
reth-chainspec.workspace = true
reth-evm-ethereum = { workspace = true, optional = true }
reth-fs-util.workspace = true
reth-primitives-traits.workspace = true
reth-net-banlist.workspace = true
@@ -136,6 +137,8 @@ test-utils = [
"reth-primitives-traits/test-utils",
"reth-provider/test-utils",
"reth-ethereum-primitives/test-utils",
"dep:reth-evm-ethereum",
"reth-evm-ethereum?/test-utils",
]
[[bench]]

View File

@@ -19,6 +19,7 @@ use reth_eth_wire::{
protocol::Protocol, DisconnectReason, EthNetworkPrimitives, HelloMessageWithProtocols,
};
use reth_ethereum_primitives::{PooledTransactionVariant, TransactionSigned};
use reth_evm_ethereum::EthEvmConfig;
use reth_network_api::{
events::{PeerEvent, SessionInfo},
test_utils::{PeersHandle, PeersHandleProvider},
@@ -182,17 +183,20 @@ where
C: ChainSpecProvider<ChainSpec: EthereumHardforks>
+ StateProviderFactory
+ BlockReaderIdExt
+ HeaderProvider
+ HeaderProvider<Header = alloy_consensus::Header>
+ Clone
+ 'static,
Pool: TransactionPool,
{
/// Installs an eth pool on each peer
pub fn with_eth_pool(self) -> Testnet<C, EthTransactionPool<C, InMemoryBlobStore>> {
pub fn with_eth_pool(
self,
) -> Testnet<C, EthTransactionPool<C, InMemoryBlobStore, EthEvmConfig>> {
self.map_pool(|peer| {
let blob_store = InMemoryBlobStore::default();
let pool = TransactionValidationTaskExecutor::eth(
peer.client.clone(),
EthEvmConfig::mainnet(),
blob_store.clone(),
TokioTaskExecutor::default(),
);
@@ -208,7 +212,7 @@ where
pub fn with_eth_pool_config(
self,
tx_manager_config: TransactionsManagerConfig,
) -> Testnet<C, EthTransactionPool<C, InMemoryBlobStore>> {
) -> Testnet<C, EthTransactionPool<C, InMemoryBlobStore, EthEvmConfig>> {
self.with_eth_pool_config_and_policy(tx_manager_config, Default::default())
}
@@ -217,11 +221,12 @@ where
self,
tx_manager_config: TransactionsManagerConfig,
policy: TransactionPropagationKind,
) -> Testnet<C, EthTransactionPool<C, InMemoryBlobStore>> {
) -> Testnet<C, EthTransactionPool<C, InMemoryBlobStore, EthEvmConfig>> {
self.map_pool(|peer| {
let blob_store = InMemoryBlobStore::default();
let pool = TransactionValidationTaskExecutor::eth(
peer.client.clone(),
EthEvmConfig::mainnet(),
blob_store.clone(),
TokioTaskExecutor::default(),
);

View File

@@ -20,6 +20,7 @@ use reth_network_p2p::{
};
use reth_network_peers::{mainnet_nodes, NodeRecord, TrustedPeer};
use reth_network_types::peers::config::PeerBackoffDurations;
use reth_provider::test_utils::MockEthProvider;
use reth_storage_api::noop::NoopProvider;
use reth_tracing::init_test_tracing;
use reth_transaction_pool::test_utils::testing_pool;
@@ -655,7 +656,8 @@ async fn new_random_peer(
async fn test_connect_many() {
reth_tracing::init_test_tracing();
let net = Testnet::create_with(5, NoopProvider::default()).await;
let provider = MockEthProvider::default().with_genesis_block();
let net = Testnet::create_with(5, provider).await;
// install request handlers
let net = net.with_eth_pool();

View File

@@ -22,7 +22,7 @@ use tokio::join;
async fn test_tx_gossip() {
reth_tracing::init_test_tracing();
let provider = MockEthProvider::default();
let provider = MockEthProvider::default().with_genesis_block();
let net = Testnet::create_with(2, provider.clone()).await;
// install request handlers
@@ -61,7 +61,7 @@ async fn test_tx_gossip() {
async fn test_tx_propagation_policy_trusted_only() {
reth_tracing::init_test_tracing();
let provider = MockEthProvider::default();
let provider = MockEthProvider::default().with_genesis_block();
let policy = TransactionPropagationKind::Trusted;
let net = Testnet::create_with(2, provider.clone()).await;
@@ -129,7 +129,7 @@ async fn test_tx_propagation_policy_trusted_only() {
async fn test_tx_ingress_policy_trusted_only() {
reth_tracing::init_test_tracing();
let provider = MockEthProvider::default();
let provider = MockEthProvider::default().with_genesis_block();
let tx_manager_config = TransactionsManagerConfig {
ingress_policy: TransactionIngressPolicy::Trusted,
@@ -195,7 +195,7 @@ async fn test_tx_ingress_policy_trusted_only() {
#[tokio::test(flavor = "multi_thread")]
async fn test_4844_tx_gossip_penalization() {
reth_tracing::init_test_tracing();
let provider = MockEthProvider::default();
let provider = MockEthProvider::default().with_genesis_block();
let net = Testnet::create_with(2, provider.clone()).await;
// install request handlers
@@ -246,7 +246,7 @@ async fn test_4844_tx_gossip_penalization() {
#[tokio::test(flavor = "multi_thread")]
async fn test_sending_invalid_transactions() {
reth_tracing::init_test_tracing();
let provider = MockEthProvider::default();
let provider = MockEthProvider::default().with_genesis_block();
let net = Testnet::create_with(2, provider.clone()).await;
// install request handlers
let net = net.with_eth_pool();

View File

@@ -62,12 +62,12 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
executor_builder,
consensus_builder,
_marker,
} = self;
ComponentsBuilder {
executor_builder: evm_builder,
executor_builder,
pool_builder,
payload_builder,
network_builder,
@@ -149,15 +149,12 @@ where
pub fn pool<PB>(
self,
pool_builder: PB,
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB>
where
PB: PoolBuilder<Node>,
{
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB> {
let Self {
pool_builder: _,
payload_builder,
network_builder,
executor_builder: evm_builder,
executor_builder,
consensus_builder,
_marker,
} = self;
@@ -165,7 +162,7 @@ where
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
executor_builder,
consensus_builder,
_marker,
}
@@ -185,72 +182,6 @@ where
_marker: self._marker,
}
}
}
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
where
Node: FullNodeTypes,
PoolB: PoolBuilder<Node>,
{
/// Configures the network builder.
///
/// This accepts a [`NetworkBuilder`] instance that will be used to create the node's network
/// stack.
pub fn network<NB>(
self,
network_builder: NB,
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB>
where
NB: NetworkBuilder<Node, PoolB::Pool>,
{
let Self {
pool_builder,
payload_builder,
network_builder: _,
executor_builder: evm_builder,
consensus_builder,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
consensus_builder,
_marker,
}
}
/// Configures the payload builder.
///
/// This accepts a [`PayloadServiceBuilder`] instance that will be used to create the node's
/// payload builder service.
pub fn payload<PB>(
self,
payload_builder: PB,
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB>
where
ExecB: ExecutorBuilder<Node>,
PB: PayloadServiceBuilder<Node, PoolB::Pool, ExecB::EVM>,
{
let Self {
pool_builder,
payload_builder: _,
network_builder,
executor_builder: evm_builder,
consensus_builder,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
consensus_builder,
_marker,
}
}
/// Configures the executor builder.
///
@@ -298,7 +229,72 @@ where
network_builder,
executor_builder,
consensus_builder: _,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder,
consensus_builder,
_marker,
}
}
}
impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
where
Node: FullNodeTypes,
ExecB: ExecutorBuilder<Node>,
PoolB: PoolBuilder<Node, ExecB::EVM>,
{
/// Configures the network builder.
///
/// This accepts a [`NetworkBuilder`] instance that will be used to create the node's network
/// stack.
pub fn network<NB>(
self,
network_builder: NB,
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB>
where
NB: NetworkBuilder<Node, PoolB::Pool>,
{
let Self {
pool_builder,
payload_builder,
network_builder: _,
executor_builder,
consensus_builder,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder,
consensus_builder,
_marker,
}
}
/// Configures the payload builder.
///
/// This accepts a [`PayloadServiceBuilder`] instance that will be used to create the node's
/// payload builder service.
pub fn payload<PB>(
self,
payload_builder: PB,
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB>
where
PB: PayloadServiceBuilder<Node, PoolB::Pool, ExecB::EVM>,
{
let Self {
pool_builder,
payload_builder: _,
network_builder,
executor_builder,
consensus_builder,
_marker,
} = self;
ComponentsBuilder {
@@ -358,7 +354,7 @@ impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> NodeComponentsBuilder<Node>
for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
where
Node: FullNodeTypes,
PoolB: PoolBuilder<Node, Pool: TransactionPool>,
PoolB: PoolBuilder<Node, ExecB::EVM, Pool: TransactionPool>,
NetworkB: NetworkBuilder<
Node,
PoolB::Pool,
@@ -384,13 +380,13 @@ where
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
executor_builder,
consensus_builder,
_marker,
} = self;
let evm_config = evm_builder.build_evm(context).await?;
let pool = pool_builder.build_pool(context).await?;
let evm_config = executor_builder.build_evm(context).await?;
let pool = pool_builder.build_pool(context, evm_config.clone()).await?;
let network = network_builder.build_network(context, pool.clone()).await?;
let payload_builder_handle = payload_builder
.spawn_payload_builder_service(context, pool.clone(), evm_config.clone())
@@ -471,14 +467,19 @@ where
#[derive(Debug, Clone)]
pub struct NoopTransactionPoolBuilder<Tx = EthPooledTransaction>(PhantomData<Tx>);
impl<N, Tx> PoolBuilder<N> for NoopTransactionPoolBuilder<Tx>
impl<N, Tx, Evm> PoolBuilder<N, Evm> for NoopTransactionPoolBuilder<Tx>
where
N: FullNodeTypes,
Tx: EthPoolTransaction<Consensus = TxTy<N::Types>> + Unpin,
Evm: Send,
{
type Pool = NoopTransactionPool<Tx>;
async fn build_pool(self, _ctx: &BuilderContext<N>) -> eyre::Result<Self::Pool> {
async fn build_pool(
self,
_ctx: &BuilderContext<N>,
_evm_config: Evm,
) -> eyre::Result<Self::Pool> {
Ok(NoopTransactionPool::<Tx>::new())
}
}

View File

@@ -12,7 +12,7 @@ use reth_transaction_pool::{
use std::{collections::HashSet, future::Future};
/// A type that knows how to build the transaction pool.
pub trait PoolBuilder<Node: FullNodeTypes>: Send {
pub trait PoolBuilder<Node: FullNodeTypes, Evm>: Send {
/// The transaction pool to build.
type Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
+ Unpin
@@ -22,16 +22,17 @@ pub trait PoolBuilder<Node: FullNodeTypes>: Send {
fn build_pool(
self,
ctx: &BuilderContext<Node>,
evm_config: Evm,
) -> impl Future<Output = eyre::Result<Self::Pool>> + Send;
}
impl<Node, F, Fut, Pool> PoolBuilder<Node> for F
impl<Node, F, Fut, Pool, Evm> PoolBuilder<Node, Evm> for F
where
Node: FullNodeTypes,
Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
+ Unpin
+ 'static,
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
F: FnOnce(&BuilderContext<Node>, Evm) -> Fut + Send,
Fut: Future<Output = eyre::Result<Pool>> + Send,
{
type Pool = Pool;
@@ -39,8 +40,9 @@ where
fn build_pool(
self,
ctx: &BuilderContext<Node>,
evm_config: Evm,
) -> impl Future<Output = eyre::Result<Self::Pool>> {
self(ctx)
self(ctx, evm_config)
}
}

View File

@@ -16,7 +16,7 @@ use reth_network::{
PeersInfo,
};
use reth_node_api::{
AddOnsContext, BlockTy, BuildNextEnv, EngineTypes, FullNodeComponents, HeaderTy, NodeAddOns,
AddOnsContext, BuildNextEnv, EngineTypes, FullNodeComponents, HeaderTy, NodeAddOns,
NodePrimitives, PayloadAttributesBuilder, PayloadTypes, PrimitivesTy, TxTy,
};
use reth_node_builder::{
@@ -165,6 +165,7 @@ impl OpNode {
self.args;
ComponentsBuilder::default()
.node_types::<Node>()
.executor(OpExecutorBuilder::default())
.pool(
OpPoolBuilder::default()
.with_enable_tx_conditional(self.args.enable_tx_conditional)
@@ -173,7 +174,6 @@ impl OpNode {
self.args.supervisor_safety_level,
),
)
.executor(OpExecutorBuilder::default())
.payload(BasicPayloadServiceBuilder::new(
OpPayloadBuilder::new(compute_pending_block)
.with_da_config(self.da_config.clone())
@@ -957,14 +957,19 @@ impl<T> OpPoolBuilder<T> {
}
}
impl<Node, T> PoolBuilder<Node> for OpPoolBuilder<T>
impl<Node, T, Evm> PoolBuilder<Node, Evm> for OpPoolBuilder<T>
where
Node: FullNodeTypes<Types: NodeTypes<ChainSpec: OpHardforks>>,
T: EthPoolTransaction<Consensus = TxTy<Node::Types>> + OpPooledTx,
Evm: ConfigureEvm<Primitives = PrimitivesTy<Node::Types>> + Clone + 'static,
{
type Pool = OpTransactionPool<Node::Provider, DiskFileBlobStore, T, BlockTy<Node::Types>>;
type Pool = OpTransactionPool<Node::Provider, DiskFileBlobStore, Evm, T>;
async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
async fn build_pool(
self,
ctx: &BuilderContext<Node>,
evm_config: Evm,
) -> eyre::Result<Self::Pool> {
let Self { pool_config_overrides, .. } = self;
// supervisor used for interop
@@ -982,27 +987,27 @@ where
.await;
let blob_store = reth_node_builder::components::create_blob_store(ctx)?;
let validator = TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone())
.no_eip4844()
.with_head_timestamp(ctx.head().timestamp)
.with_max_tx_input_bytes(ctx.config().txpool.max_tx_input_bytes)
.kzg_settings(ctx.kzg_settings()?)
.set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap)
.with_max_tx_gas_limit(ctx.config().txpool.max_tx_gas_limit)
.with_minimum_priority_fee(ctx.config().txpool.minimum_priority_fee)
.with_additional_tasks(
pool_config_overrides
.additional_validation_tasks
.unwrap_or_else(|| ctx.config().txpool.additional_validation_tasks),
)
.build_with_tasks(ctx.task_executor().clone(), blob_store.clone())
.map(|validator| {
OpTransactionValidator::new(validator)
// In --dev mode we can't require gas fees because we're unable to decode
// the L1 block info
.require_l1_data_gas_fee(!ctx.config().dev.dev)
.with_supervisor(supervisor_client.clone())
});
let validator =
TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone(), evm_config)
.no_eip4844()
.with_max_tx_input_bytes(ctx.config().txpool.max_tx_input_bytes)
.kzg_settings(ctx.kzg_settings()?)
.set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap)
.with_max_tx_gas_limit(ctx.config().txpool.max_tx_gas_limit)
.with_minimum_priority_fee(ctx.config().txpool.minimum_priority_fee)
.with_additional_tasks(
pool_config_overrides
.additional_validation_tasks
.unwrap_or_else(|| ctx.config().txpool.additional_validation_tasks),
)
.build_with_tasks(ctx.task_executor().clone(), blob_store.clone())
.map(|validator| {
OpTransactionValidator::new(validator)
// In --dev mode we can't require gas fees because we're unable to decode
// the L1 block info
.require_l1_data_gas_fee(!ctx.config().dev.dev)
.with_supervisor(supervisor_client.clone())
});
let final_pool_config = pool_config_overrides.apply(ctx.pool_config());

View File

@@ -52,9 +52,9 @@
//! ComponentsBuilder::default()
//! .node_types::<RethFullAdapter<_, OpNode>>()
//! .noop_pool::<OpPooledTransaction>()
//! .noop_network::<OpNetworkPrimitives>()
//! .noop_consensus()
//! .executor(OpExecutorBuilder::default())
//! .noop_consensus()
//! .noop_network::<OpNetworkPrimitives>()
//! .noop_payload(),
//! Box::new(()) as Box<dyn OnComponentInitializedHook<_>>,
//! )

View File

@@ -23,6 +23,7 @@ alloy-serde.workspace = true
# reth
reth-chainspec.workspace = true
reth-evm.workspace = true
reth-primitives-traits.workspace = true
reth-chain-state.workspace = true
reth-storage-api.workspace = true

View File

@@ -9,7 +9,6 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
mod validator;
use op_alloy_consensus::OpBlock;
pub use validator::{OpL1BlockInfo, OpTransactionValidator};
pub mod conditional;
@@ -25,8 +24,8 @@ pub mod estimated_da_size;
use reth_transaction_pool::{CoinbaseTipOrdering, Pool, TransactionValidationTaskExecutor};
/// Type alias for default optimism transaction pool
pub type OpTransactionPool<Client, S, T = OpPooledTransaction, B = OpBlock> = Pool<
TransactionValidationTaskExecutor<OpTransactionValidator<Client, T, B>>,
pub type OpTransactionPool<Client, S, Evm, T = OpPooledTransaction> = Pool<
TransactionValidationTaskExecutor<OpTransactionValidator<Client, T, Evm>>,
CoinbaseTipOrdering<T>,
S,
>;

View File

@@ -316,7 +316,8 @@ mod tests {
use alloy_primitives::{TxKind, U256};
use op_alloy_consensus::TxDeposit;
use reth_optimism_chainspec::OP_MAINNET;
use reth_optimism_primitives::OpTransactionSigned;
use reth_optimism_evm::OpEvmConfig;
use reth_optimism_primitives::{OpPrimitives, OpTransactionSigned};
use reth_provider::test_utils::MockEthProvider;
use reth_transaction_pool::{
blobstore::InMemoryBlobStore, validate::EthTransactionValidatorBuilder, TransactionOrigin,
@@ -324,12 +325,14 @@ mod tests {
};
#[tokio::test]
async fn validate_optimism_transaction() {
let client = MockEthProvider::default().with_chain_spec(OP_MAINNET.clone());
let validator =
EthTransactionValidatorBuilder::new(client)
.no_shanghai()
.no_cancun()
.build::<_, _, reth_optimism_primitives::OpBlock>(InMemoryBlobStore::default());
let client = MockEthProvider::<OpPrimitives>::new()
.with_chain_spec(OP_MAINNET.clone())
.with_genesis_block();
let evm_config = OpEvmConfig::optimism(OP_MAINNET.clone());
let validator = EthTransactionValidatorBuilder::new(client, evm_config)
.no_shanghai()
.no_cancun()
.build(InMemoryBlobStore::default());
let validator = OpTransactionValidator::new(validator);
let origin = TransactionOrigin::External;

View File

@@ -1,13 +1,14 @@
use crate::{supervisor::SupervisorClient, InvalidCrossTx, OpPooledTx};
use alloy_consensus::{BlockHeader, Transaction};
use op_alloy_consensus::OpBlock;
use op_revm::L1BlockInfo;
use parking_lot::RwLock;
use reth_chainspec::ChainSpecProvider;
use reth_evm::ConfigureEvm;
use reth_optimism_evm::RethL1BlockInfo;
use reth_optimism_forks::OpHardforks;
use reth_primitives_traits::{
transaction::error::InvalidTransactionError, Block, BlockBody, GotExpected, SealedBlock,
transaction::error::InvalidTransactionError, Block, BlockBody, BlockTy, GotExpected,
SealedBlock,
};
use reth_storage_api::{AccountInfoReader, BlockReaderIdExt, StateProviderFactory};
use reth_transaction_pool::{
@@ -40,9 +41,9 @@ impl OpL1BlockInfo {
/// Validator for Optimism transactions.
#[derive(Debug, Clone)]
pub struct OpTransactionValidator<Client, Tx, B = OpBlock> {
pub struct OpTransactionValidator<Client, Tx, Evm> {
/// The type that performs the actual validation.
inner: Arc<EthTransactionValidator<Client, Tx, B>>,
inner: Arc<EthTransactionValidator<Client, Tx, Evm>>,
/// Additional block info required for validation.
block_info: Arc<OpL1BlockInfo>,
/// If true, ensure that the transaction's sender has enough balance to cover the L1 gas fee
@@ -55,7 +56,7 @@ pub struct OpTransactionValidator<Client, Tx, B = OpBlock> {
fork_tracker: Arc<OpForkTracker>,
}
impl<Client, Tx, B: Block> OpTransactionValidator<Client, Tx, B> {
impl<Client, Tx, Evm> OpTransactionValidator<Client, Tx, Evm> {
/// Returns the configured chain spec
pub fn chain_spec(&self) -> Arc<Client::ChainSpec>
where
@@ -87,15 +88,15 @@ impl<Client, Tx, B: Block> OpTransactionValidator<Client, Tx, B> {
}
}
impl<Client, Tx, B> OpTransactionValidator<Client, Tx, B>
impl<Client, Tx, Evm> OpTransactionValidator<Client, Tx, Evm>
where
Client:
ChainSpecProvider<ChainSpec: OpHardforks> + StateProviderFactory + BlockReaderIdExt + Sync,
Tx: EthPoolTransaction + OpPooledTx,
B: Block,
Evm: ConfigureEvm,
{
/// Create a new [`OpTransactionValidator`].
pub fn new(inner: EthTransactionValidator<Client, Tx, B>) -> Self {
pub fn new(inner: EthTransactionValidator<Client, Tx, Evm>) -> Self {
let this = Self::with_block_info(inner, OpL1BlockInfo::default());
if let Ok(Some(block)) =
this.inner.client().block_by_number_or_tag(alloy_eips::BlockNumberOrTag::Latest)
@@ -114,7 +115,7 @@ where
/// Create a new [`OpTransactionValidator`] with the given [`OpL1BlockInfo`].
pub fn with_block_info(
inner: EthTransactionValidator<Client, Tx, B>,
inner: EthTransactionValidator<Client, Tx, Evm>,
block_info: OpL1BlockInfo,
) -> Self {
Self {
@@ -290,15 +291,15 @@ where
}
}
impl<Client, Tx, B> TransactionValidator for OpTransactionValidator<Client, Tx, B>
impl<Client, Tx, Evm> TransactionValidator for OpTransactionValidator<Client, Tx, Evm>
where
Client:
ChainSpecProvider<ChainSpec: OpHardforks> + StateProviderFactory + BlockReaderIdExt + Sync,
Tx: EthPoolTransaction + OpPooledTx,
B: Block,
Evm: ConfigureEvm,
{
type Transaction = Tx;
type Block = B;
type Block = BlockTy<Evm::Primitives>;
async fn validate_transaction(
&self,

View File

@@ -188,6 +188,21 @@ impl<T: NodePrimitives, ChainSpec> MockEthProvider<T, ChainSpec> {
prune_modes: self.prune_modes,
}
}
/// Adds the genesis block from the chain spec to the provider.
///
/// This is useful for tests that require a valid latest block (e.g., transaction validation).
pub fn with_genesis_block(self) -> Self
where
ChainSpec: EthChainSpec<Header = <T::Block as Block>::Header>,
<T::Block as Block>::Body: Default,
{
let genesis_hash = self.chain_spec.genesis_hash();
let genesis_header = self.chain_spec.genesis_header().clone();
let genesis_block = T::Block::new(genesis_header, Default::default());
self.add_block(genesis_hash, genesis_block);
self
}
}
impl Default for MockEthProvider {

View File

@@ -17,11 +17,14 @@ reth-chain-state.workspace = true
reth-ethereum-primitives.workspace = true
reth-chainspec.workspace = true
reth-eth-wire-types.workspace = true
reth-evm.workspace = true
reth-evm-ethereum.workspace = true
reth-primitives-traits.workspace = true
reth-execution-types.workspace = true
reth-fs-util.workspace = true
reth-storage-api.workspace = true
reth-tasks.workspace = true
revm.workspace = true
revm-interpreter.workspace = true
revm-primitives.workspace = true
@@ -92,6 +95,7 @@ serde = [
"reth-ethereum-primitives/serde",
"reth-chain-state/serde",
"reth-storage-api/serde",
"revm/serde",
]
test-utils = [
"rand",
@@ -103,6 +107,8 @@ test-utils = [
"reth-primitives-traits/test-utils",
"reth-ethereum-primitives/test-utils",
"alloy-primitives/rand",
"reth-evm/test-utils",
"reth-evm-ethereum/test-utils",
]
arbitrary = [
"proptest",
@@ -118,6 +124,7 @@ arbitrary = [
"revm-interpreter/arbitrary",
"reth-ethereum-primitives/arbitrary",
"revm-primitives/arbitrary",
"revm/arbitrary",
]
[[bench]]

View File

@@ -197,16 +197,22 @@
//!
//! ```
//! use reth_chainspec::MAINNET;
//! use reth_storage_api::StateProviderFactory;
//! use reth_storage_api::{BlockReaderIdExt, StateProviderFactory};
//! use reth_tasks::TokioTaskExecutor;
//! use reth_chainspec::ChainSpecProvider;
//! use reth_transaction_pool::{TransactionValidationTaskExecutor, Pool, TransactionPool};
//! use reth_transaction_pool::blobstore::InMemoryBlobStore;
//! use reth_chainspec::EthereumHardforks;
//! async fn t<C>(client: C) where C: ChainSpecProvider<ChainSpec: EthereumHardforks> + StateProviderFactory + Clone + 'static{
//! use reth_evm::ConfigureEvm;
//! use alloy_consensus::Header;
//! async fn t<C, Evm>(client: C, evm_config: Evm)
//! where
//! C: ChainSpecProvider<ChainSpec: EthereumHardforks> + StateProviderFactory + BlockReaderIdExt<Header = Header> + Clone + 'static,
//! Evm: ConfigureEvm<Primitives: reth_primitives_traits::NodePrimitives<BlockHeader = Header>> + 'static,
//! {
//! let blob_store = InMemoryBlobStore::default();
//! let pool = Pool::eth_pool(
//! TransactionValidationTaskExecutor::eth(client, blob_store.clone(), TokioTaskExecutor::default()),
//! TransactionValidationTaskExecutor::eth(client, evm_config, blob_store.clone(), TokioTaskExecutor::default()),
//! blob_store,
//! Default::default(),
//! );
@@ -235,18 +241,21 @@
//! use reth_transaction_pool::{TransactionValidationTaskExecutor, Pool};
//! use reth_transaction_pool::blobstore::InMemoryBlobStore;
//! use reth_transaction_pool::maintain::{maintain_transaction_pool_future};
//! use reth_evm::ConfigureEvm;
//! use reth_ethereum_primitives::EthPrimitives;
//! use alloy_consensus::Header;
//!
//! async fn t<C, St>(client: C, stream: St)
//! async fn t<C, St, Evm>(client: C, stream: St, evm_config: Evm)
//! where C: StateProviderFactory + BlockReaderIdExt<Header = Header> + ChainSpecProvider<ChainSpec = ChainSpec> + Clone + 'static,
//! St: Stream<Item = CanonStateNotification> + Send + Unpin + 'static,
//! St: Stream<Item = CanonStateNotification<EthPrimitives>> + Send + Unpin + 'static,
//! Evm: ConfigureEvm<Primitives = EthPrimitives> + 'static,
//! {
//! let blob_store = InMemoryBlobStore::default();
//! let rt = tokio::runtime::Runtime::new().unwrap();
//! let manager = TaskManager::new(rt.handle().clone());
//! let executor = manager.executor();
//! let pool = Pool::eth_pool(
//! TransactionValidationTaskExecutor::eth(client.clone(), blob_store.clone(), executor.clone()),
//! TransactionValidationTaskExecutor::eth(client.clone(), evm_config, blob_store.clone(), executor.clone()),
//! blob_store,
//! Default::default(),
//! );
@@ -302,9 +311,11 @@ use alloy_primitives::{Address, TxHash, B256, U256};
use aquamarine as _;
use reth_chainspec::{ChainSpecProvider, EthereumHardforks};
use reth_eth_wire_types::HandleMempoolData;
use reth_evm::ConfigureEvm;
use reth_evm_ethereum::EthEvmConfig;
use reth_execution_types::ChangedAccount;
use reth_primitives_traits::Recovered;
use reth_storage_api::StateProviderFactory;
use reth_primitives_traits::{HeaderTy, Recovered};
use reth_storage_api::{BlockReaderIdExt, StateProviderFactory};
use std::{collections::HashSet, sync::Arc};
use tokio::sync::mpsc::Receiver;
use tracing::{instrument, trace};
@@ -328,13 +339,8 @@ mod traits;
pub mod test_utils;
/// Type alias for default ethereum transaction pool
pub type EthTransactionPool<
Client,
S,
T = EthPooledTransaction,
B = reth_ethereum_primitives::Block,
> = Pool<
TransactionValidationTaskExecutor<EthTransactionValidator<Client, T, B>>,
pub type EthTransactionPool<Client, S, Evm = EthEvmConfig, T = EthPooledTransaction> = Pool<
TransactionValidationTaskExecutor<EthTransactionValidator<Client, T, Evm>>,
CoinbaseTipOrdering<T>,
S,
>;
@@ -415,11 +421,15 @@ where
}
}
impl<Client, S> EthTransactionPool<Client, S>
impl<Client, S, Evm> EthTransactionPool<Client, S, Evm>
where
Client:
ChainSpecProvider<ChainSpec: EthereumHardforks> + StateProviderFactory + Clone + 'static,
Client: ChainSpecProvider<ChainSpec: EthereumHardforks>
+ StateProviderFactory
+ Clone
+ BlockReaderIdExt<Header = HeaderTy<Evm::Primitives>>
+ 'static,
S: BlobStore,
Evm: ConfigureEvm + 'static,
{
/// Returns a new [`Pool`] that uses the default [`TransactionValidationTaskExecutor`] when
/// validating [`EthPooledTransaction`]s and ords via [`CoinbaseTipOrdering`]
@@ -428,18 +438,25 @@ where
///
/// ```
/// use reth_chainspec::MAINNET;
/// use reth_storage_api::StateProviderFactory;
/// use reth_storage_api::{BlockReaderIdExt, StateProviderFactory};
/// use reth_tasks::TokioTaskExecutor;
/// use reth_chainspec::ChainSpecProvider;
/// use reth_transaction_pool::{
/// blobstore::InMemoryBlobStore, Pool, TransactionValidationTaskExecutor,
/// };
/// use reth_chainspec::EthereumHardforks;
/// # fn t<C>(client: C) where C: ChainSpecProvider<ChainSpec: EthereumHardforks> + StateProviderFactory + Clone + 'static {
/// use reth_evm::ConfigureEvm;
/// use alloy_consensus::Header;
/// # fn t<C, Evm>(client: C, evm_config: Evm)
/// # where
/// # C: ChainSpecProvider<ChainSpec: EthereumHardforks> + StateProviderFactory + BlockReaderIdExt<Header = Header> + Clone + 'static,
/// # Evm: ConfigureEvm<Primitives: reth_primitives_traits::NodePrimitives<BlockHeader = Header>> + 'static,
/// # {
/// let blob_store = InMemoryBlobStore::default();
/// let pool = Pool::eth_pool(
/// TransactionValidationTaskExecutor::eth(
/// client,
/// evm_config,
/// blob_store.clone(),
/// TokioTaskExecutor::default(),
/// ),
@@ -450,7 +467,7 @@ where
/// ```
pub fn eth_pool(
validator: TransactionValidationTaskExecutor<
EthTransactionValidator<Client, EthPooledTransaction>,
EthTransactionValidator<Client, EthPooledTransaction, Evm>,
>,
blob_store: S,
config: PoolConfig,

View File

@@ -857,12 +857,12 @@ mod tests {
use super::*;
use crate::{
blobstore::InMemoryBlobStore, validate::EthTransactionValidatorBuilder,
CoinbaseTipOrdering, EthPooledTransaction, EthTransactionValidator, Pool,
TransactionOrigin,
CoinbaseTipOrdering, EthPooledTransaction, Pool, TransactionOrigin,
};
use alloy_eips::eip2718::Decodable2718;
use alloy_primitives::{hex, U256};
use reth_ethereum_primitives::PooledTransactionVariant;
use reth_evm_ethereum::EthEvmConfig;
use reth_fs_util as fs;
use reth_provider::test_utils::{ExtendedAccount, MockEthProvider};
use reth_tasks::TaskManager;
@@ -886,14 +886,14 @@ mod tests {
"02f87201830655c2808505ef61f08482565f94388c818ca8b9251b393131c08a736a67ccb192978801049e39c4b5b1f580c001a01764ace353514e8abdfb92446de356b260e3c1225b73fc4c8876a6258d12a129a04f02294aa61ca7676061cd99f29275491218b4754b46a0248e5e42bc5091f507"
);
let tx = PooledTransactionVariant::decode_2718(&mut &tx_bytes[..]).unwrap();
let provider = MockEthProvider::default();
let provider = MockEthProvider::default().with_genesis_block();
let transaction = EthPooledTransaction::from_pooled(tx.try_into_recovered().unwrap());
let tx_to_cmp = transaction.clone();
let sender = hex!("1f9090aaE28b8a3dCeaDf281B0F12828e676c326").into();
provider.add_account(sender, ExtendedAccount::new(42, U256::MAX));
let blob_store = InMemoryBlobStore::default();
let validator: EthTransactionValidator<_, _, reth_ethereum_primitives::Block> =
EthTransactionValidatorBuilder::new(provider).build(blob_store.clone());
let validator = EthTransactionValidatorBuilder::new(provider, EthEvmConfig::mainnet())
.build(blob_store.clone());
let txpool = Pool::new(
validator,

View File

@@ -10,9 +10,3 @@ pub const TX_SLOT_BYTE_SIZE: usize = 32 * 1024;
/// to validate whether they fit into the pool or not. Default is 4 times [`TX_SLOT_BYTE_SIZE`],
/// which defaults to 32 KiB, so 128 KiB.
pub const DEFAULT_MAX_TX_INPUT_BYTES: usize = 4 * TX_SLOT_BYTE_SIZE; // 128KB
/// Maximum bytecode to permit for a contract.
pub const MAX_CODE_BYTE_SIZE: usize = revm_primitives::eip170::MAX_CODE_SIZE;
/// Maximum initcode to permit in a creation transaction and create instructions.
pub const MAX_INIT_CODE_BYTE_SIZE: usize = revm_primitives::eip3860::MAX_INITCODE_SIZE;

File diff suppressed because one or more lines are too long

View File

@@ -21,9 +21,7 @@ pub use eth::*;
pub use task::{TransactionValidationTaskExecutor, ValidationTask};
/// Validation constants.
pub use constants::{
DEFAULT_MAX_TX_INPUT_BYTES, MAX_CODE_BYTE_SIZE, MAX_INIT_CODE_BYTE_SIZE, TX_SLOT_BYTE_SIZE,
};
pub use constants::{DEFAULT_MAX_TX_INPUT_BYTES, TX_SLOT_BYTE_SIZE};
/// A Result type returned after checking a transaction's validity.
#[derive(Debug)]

View File

@@ -8,7 +8,10 @@ use crate::{
TransactionValidator,
};
use futures_util::{lock::Mutex, StreamExt};
use reth_primitives_traits::SealedBlock;
use reth_chainspec::{ChainSpecProvider, EthereumHardforks};
use reth_evm::ConfigureEvm;
use reth_primitives_traits::{HeaderTy, SealedBlock};
use reth_storage_api::BlockReaderIdExt;
use reth_tasks::TaskSpawner;
use std::{future::Future, pin::Pin, sync::Arc};
use tokio::{
@@ -116,8 +119,16 @@ impl<V> Clone for TransactionValidationTaskExecutor<V> {
impl TransactionValidationTaskExecutor<()> {
/// Convenience method to create a [`EthTransactionValidatorBuilder`]
pub fn eth_builder<Client>(client: Client) -> EthTransactionValidatorBuilder<Client> {
EthTransactionValidatorBuilder::new(client)
pub fn eth_builder<Client, Evm>(
client: Client,
evm_config: Evm,
) -> EthTransactionValidatorBuilder<Client, Evm>
where
Client: ChainSpecProvider<ChainSpec: EthereumHardforks>
+ BlockReaderIdExt<Header = HeaderTy<Evm::Primitives>>,
Evm: ConfigureEvm,
{
EthTransactionValidatorBuilder::new(client, evm_config)
}
}
@@ -139,16 +150,19 @@ impl<V> TransactionValidationTaskExecutor<V> {
}
}
impl<Client, Tx> TransactionValidationTaskExecutor<EthTransactionValidator<Client, Tx>> {
impl<Client, Tx, Evm> TransactionValidationTaskExecutor<EthTransactionValidator<Client, Tx, Evm>> {
/// Creates a new instance for the given client
///
/// This will spawn a single validation tasks that performs the actual validation.
/// See [`TransactionValidationTaskExecutor::eth_with_additional_tasks`]
pub fn eth<T, S: BlobStore>(client: Client, blob_store: S, tasks: T) -> Self
pub fn eth<T, S: BlobStore>(client: Client, evm_config: Evm, blob_store: S, tasks: T) -> Self
where
T: TaskSpawner,
Client: ChainSpecProvider<ChainSpec: EthereumHardforks>
+ BlockReaderIdExt<Header = HeaderTy<Evm::Primitives>>,
Evm: ConfigureEvm,
{
Self::eth_with_additional_tasks(client, blob_store, tasks, 0)
Self::eth_with_additional_tasks(client, evm_config, blob_store, tasks, 0)
}
/// Creates a new instance for the given client
@@ -162,14 +176,18 @@ impl<Client, Tx> TransactionValidationTaskExecutor<EthTransactionValidator<Clien
/// `num_additional_tasks` additional tasks.
pub fn eth_with_additional_tasks<T, S: BlobStore>(
client: Client,
evm_config: Evm,
blob_store: S,
tasks: T,
num_additional_tasks: usize,
) -> Self
where
T: TaskSpawner,
Client: ChainSpecProvider<ChainSpec: EthereumHardforks>
+ BlockReaderIdExt<Header = HeaderTy<Evm::Primitives>>,
Evm: ConfigureEvm,
{
EthTransactionValidatorBuilder::new(client)
EthTransactionValidatorBuilder::new(client, evm_config)
.with_additional_tasks(num_additional_tasks)
.build_with_tasks(tasks, blob_store)
}

View File

@@ -5,15 +5,16 @@
use reth_ethereum::{
chainspec::ChainSpec,
cli::interface::Cli,
evm::EthEvmConfig,
node::{
api::{BlockTy, FullNodeTypes, NodeTypes},
api::{FullNodeTypes, NodeTypes},
builder::{components::PoolBuilder, BuilderContext},
node::EthereumAddOns,
EthereumNode,
},
pool::{
blobstore::InMemoryBlobStore, CoinbaseTipOrdering, EthPooledTransaction,
EthTransactionPool, Pool, PoolConfig, TransactionValidationTaskExecutor,
blobstore::InMemoryBlobStore, CoinbaseTipOrdering, EthTransactionPool, Pool, PoolConfig,
TransactionValidationTaskExecutor,
},
provider::CanonStateSubscriptions,
EthPrimitives,
@@ -49,28 +50,24 @@ pub struct CustomPoolBuilder {
/// Implement the [`PoolBuilder`] trait for the custom pool builder
///
/// This will be used to build the transaction pool and its maintenance tasks during launch.
impl<Node> PoolBuilder<Node> for CustomPoolBuilder
impl<Node> PoolBuilder<Node, EthEvmConfig> for CustomPoolBuilder
where
Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = EthPrimitives>>,
{
type Pool = EthTransactionPool<
Node::Provider,
InMemoryBlobStore,
EthPooledTransaction,
BlockTy<Node::Types>,
>;
type Pool = EthTransactionPool<Node::Provider, InMemoryBlobStore>;
async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
async fn build_pool(
self,
ctx: &BuilderContext<Node>,
evm_config: EthEvmConfig,
) -> eyre::Result<Self::Pool> {
let data_dir = ctx.config().datadir();
let blob_store = InMemoryBlobStore::default();
let validator = TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone())
.with_head_timestamp(ctx.head().timestamp)
.kzg_settings(ctx.kzg_settings()?)
.with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
.build_with_tasks::<_, _, _, BlockTy<Node::Types>>(
ctx.task_executor().clone(),
blob_store.clone(),
);
let validator =
TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone(), evm_config)
.kzg_settings(ctx.kzg_settings()?)
.with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
.build_with_tasks(ctx.task_executor().clone(), blob_store.clone());
let transaction_pool =
Pool::new(validator, CoinbaseTipOrdering::default(), blob_store, self.pool_config);