From 30800af6ec81521625db40cd6d3881f0e2d3f9e6 Mon Sep 17 00:00:00 2001 From: Hai | RISE <150876604+hai-rise@users.noreply.github.com> Date: Mon, 2 Dec 2024 23:28:47 +0700 Subject: [PATCH] perf(validate-tx-pool): fast non-allocating `is_create` (#13063) --- crates/transaction-pool/src/test_utils/mock.rs | 10 ++++++++++ crates/transaction-pool/src/traits.rs | 12 +++++++++++- crates/transaction-pool/src/validate/eth.rs | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index afa1638c8516..78982cb46575 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -719,6 +719,16 @@ impl PoolTransaction for MockTransaction { } } + /// Returns true if the transaction is a contract creation. + fn is_create(&self) -> bool { + match self { + Self::Legacy { to, .. } | Self::Eip1559 { to, .. } | Self::Eip2930 { to, .. } => { + to.is_create() + } + Self::Eip4844 { .. } => false, + } + } + /// Returns the input data associated with the transaction. fn input(&self) -> &[u8] { self.get_input() diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 6adb81729e17..11c8db225b0a 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -1061,6 +1061,11 @@ pub trait PoolTransaction: fmt::Debug + Send + Sync + Clone { /// [`TxKind::Create`] if the transaction is a contract creation. fn kind(&self) -> TxKind; + /// Returns true if the transaction is a contract creation. + /// We don't provide a default implementation via `kind` as it copies the 21-byte + /// [`TxKind`] for this simple check. A proper implementation shouldn't allocate. + fn is_create(&self) -> bool; + /// Returns the recipient of the transaction if it is not a [`TxKind::Create`] /// transaction. fn to(&self) -> Option
{ @@ -1109,7 +1114,7 @@ pub trait PoolTransaction: fmt::Debug + Send + Sync + Clone { &self, max_init_code_size: usize, ) -> Result<(), InvalidPoolTransactionError> { - if self.kind().is_create() && self.input().len() > max_init_code_size { + if self.is_create() && self.input().len() > max_init_code_size { Err(InvalidPoolTransactionError::ExceedsMaxInitCodeSize( self.size(), max_init_code_size, @@ -1328,6 +1333,11 @@ impl PoolTransaction for EthPooledTransaction { self.transaction.kind() } + /// Returns true if the transaction is a contract creation. + fn is_create(&self) -> bool { + self.transaction.is_create() + } + fn input(&self) -> &[u8] { self.transaction.input() } diff --git a/crates/transaction-pool/src/validate/eth.rs b/crates/transaction-pool/src/validate/eth.rs index ca7452225755..5249c1befa2c 100644 --- a/crates/transaction-pool/src/validate/eth.rs +++ b/crates/transaction-pool/src/validate/eth.rs @@ -815,7 +815,7 @@ pub fn ensure_intrinsic_gas( let gas_after_merge = validate_initial_tx_gas( spec_id, transaction.input(), - transaction.kind().is_create(), + transaction.is_create(), transaction.access_list().map(|list| list.0.as_slice()).unwrap_or(&[]), transaction.authorization_count() as u64, );