From 072a6c56d3d3125bcdd1e644b6afdb646e74acfb Mon Sep 17 00:00:00 2001 From: "Kim, JinSan" Date: Sat, 28 Jan 2023 05:53:24 +0900 Subject: [PATCH] chore(txpool): implement ensure_max_init_code_size() (#1062) Co-authored-by: Matthias Seitz --- crates/transaction-pool/src/error.rs | 5 ++++ .../transaction-pool/src/test_utils/mock.rs | 15 ++++++++++- crates/transaction-pool/src/traits.rs | 12 ++++++++- crates/transaction-pool/src/validate.rs | 26 ++++++++++++++++++- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/crates/transaction-pool/src/error.rs b/crates/transaction-pool/src/error.rs index fda5007fd73f..ee8133787aaa 100644 --- a/crates/transaction-pool/src/error.rs +++ b/crates/transaction-pool/src/error.rs @@ -25,6 +25,10 @@ pub enum PoolError { /// respect the size limits of the pool. #[error("[{0:?}] Transaction's gas limit {1} exceeds block's gas limit {2}.")] TxExceedsGasLimit(TxHash, u64, u64), + /// Thrown when a new transaction is added to the pool, but then immediately discarded to + /// respect the max_init_code_size. + #[error("[{0:?}] Transaction's size {1} exceeds max_init_code_size {2}.")] + TxExceedsMaxInitCodeSize(TxHash, usize, usize), } // === impl PoolError === @@ -38,6 +42,7 @@ impl PoolError { PoolError::SpammerExceededCapacity(_, hash) => hash, PoolError::DiscardedOnInsert(hash) => hash, PoolError::TxExceedsGasLimit(hash, _, _) => hash, + PoolError::TxExceedsMaxInitCodeSize(hash, _, _) => hash, } } } diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index 051433084c22..ba88d15ebdb4 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -12,7 +12,7 @@ use rand::{ prelude::Distribution, }; use reth_primitives::{ - Address, FromRecoveredTransaction, IntoRecoveredTransaction, Transaction, + Address, FromRecoveredTransaction, IntoRecoveredTransaction, Transaction, TransactionKind, TransactionSignedEcRecovered, TxEip1559, TxHash, TxLegacy, H256, U128, U256, }; use std::{ops::Range, sync::Arc, time::Instant}; @@ -85,6 +85,7 @@ pub enum MockTransaction { nonce: u64, gas_price: u128, gas_limit: u64, + to: TransactionKind, value: U256, }, Eip1559 { @@ -94,6 +95,7 @@ pub enum MockTransaction { max_fee_per_gas: u128, max_priority_fee_per_gas: u128, gas_limit: u64, + to: TransactionKind, value: U256, }, } @@ -117,6 +119,7 @@ impl MockTransaction { nonce: 0, gas_price: 0, gas_limit: 0, + to: TransactionKind::Call(Address::random()), value: Default::default(), } } @@ -130,6 +133,7 @@ impl MockTransaction { max_fee_per_gas: MIN_PROTOCOL_BASE_FEE, max_priority_fee_per_gas: MIN_PROTOCOL_BASE_FEE, gas_limit: 0, + to: TransactionKind::Call(Address::random()), value: Default::default(), } } @@ -331,6 +335,13 @@ impl PoolTransaction for MockTransaction { } } + fn kind(&self) -> &TransactionKind { + match self { + MockTransaction::Legacy { to, .. } => to, + MockTransaction::Eip1559 { to, .. } => to, + } + } + fn size(&self) -> usize { 0 } @@ -356,6 +367,7 @@ impl FromRecoveredTransaction for MockTransaction { nonce, gas_price, gas_limit, + to, value: U256::from(value), }, Transaction::Eip1559(TxEip1559 { @@ -375,6 +387,7 @@ impl FromRecoveredTransaction for MockTransaction { max_fee_per_gas, max_priority_fee_per_gas, gas_limit, + to, value: U256::from(value), }, Transaction::Eip2930 { .. } => { diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index f1a3bfe78305..ad351417cf8e 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -1,7 +1,7 @@ use crate::{error::PoolResult, pool::state::SubPool, validate::ValidPoolTransaction}; use reth_primitives::{ Address, FromRecoveredTransaction, IntoRecoveredTransaction, PeerId, Transaction, - TransactionSignedEcRecovered, TxHash, H256, U256, + TransactionKind, TransactionSignedEcRecovered, TxHash, H256, U256, }; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt, sync::Arc}; @@ -271,6 +271,10 @@ pub trait PoolTransaction: fmt::Debug + Send + Sync + FromRecoveredTransaction { /// This will return `None` for non-EIP1559 transactions fn max_priority_fee_per_gas(&self) -> Option; + /// Returns the transaction's [`TransactionKind`], which is the address of the recipient or + /// [`TransactionKind::Create`] if the transaction is a contract creation. + fn kind(&self) -> &TransactionKind; + /// Returns a measurement of the heap usage of this type and all its internals. fn size(&self) -> usize; } @@ -348,6 +352,12 @@ impl PoolTransaction for PooledTransaction { } } + /// Returns the transaction's [`TransactionKind`], which is the address of the recipient or + /// [`TransactionKind::Create`] if the transaction is a contract creation. + fn kind(&self) -> &TransactionKind { + self.transaction.kind() + } + /// Returns a measurement of the heap usage of this type and all its internals. fn size(&self) -> usize { self.transaction.transaction.input().len() diff --git a/crates/transaction-pool/src/validate.rs b/crates/transaction-pool/src/validate.rs index 1b80a7cceb37..5fcdf2340a0f 100644 --- a/crates/transaction-pool/src/validate.rs +++ b/crates/transaction-pool/src/validate.rs @@ -5,7 +5,7 @@ use crate::{ identifier::{SenderId, TransactionId}, traits::{PoolTransaction, TransactionOrigin}, }; -use reth_primitives::{Address, TxHash, U256}; +use reth_primitives::{Address, TransactionKind, TxHash, U256}; use std::{fmt, time::Instant}; /// A Result type returned after checking a transaction's validity. @@ -54,6 +54,30 @@ pub trait TransactionValidator: Send + Sync { origin: TransactionOrigin, transaction: Self::Transaction, ) -> TransactionValidationOutcome; + + /// Ensure that the code size is not greater than `max_init_code_size`. + /// `max_init_code_size` should be configurable so this will take it as an argument. + fn ensure_max_init_code_size( + &self, + transaction: Self::Transaction, + max_init_code_size: usize, + ) -> Result<(), PoolError> { + // TODO check whether we are in the Shanghai stage. + // if !self.shanghai { + // return Ok(()) + // } + + if *transaction.kind() == TransactionKind::Create && transaction.size() > max_init_code_size + { + Err(PoolError::TxExceedsMaxInitCodeSize( + *transaction.hash(), + transaction.size(), + max_init_code_size, + )) + } else { + Ok(()) + } + } } /// A valid transaction in the pool.