mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
feat: configurable EVM execution limits (#21088)
Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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"))]
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ std = [
|
||||
"reth-storage-errors/std",
|
||||
]
|
||||
test-utils = [
|
||||
"std",
|
||||
"dep:parking_lot",
|
||||
"dep:derive_more",
|
||||
"reth-chainspec/test-utils",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>,
|
||||
>,
|
||||
>;
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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<_>>,
|
||||
//! )
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user