feat(pool): make mock transaction validator eth-compatible (#8034)

This commit is contained in:
Alexey Shekhirin
2024-05-01 19:44:55 +01:00
committed by GitHub
parent 1c1cbe9231
commit 9ae9af484d
4 changed files with 77 additions and 42 deletions

View File

@ -11,10 +11,10 @@ use crate::{
TransactionListenerKind,
},
validate::ValidTransaction,
AllPoolTransactions, AllTransactionsEvents, BestTransactions, BlockInfo, EthPooledTransaction,
NewTransactionEvent, PoolResult, PoolSize, PoolTransaction, PooledTransactionsElement,
PropagatedTransactions, TransactionEvents, TransactionOrigin, TransactionPool,
TransactionValidationOutcome, TransactionValidator, ValidPoolTransaction,
AllPoolTransactions, AllTransactionsEvents, BestTransactions, BlockInfo, EthPoolTransaction,
EthPooledTransaction, NewTransactionEvent, PoolResult, PoolSize, PoolTransaction,
PooledTransactionsElement, PropagatedTransactions, TransactionEvents, TransactionOrigin,
TransactionPool, TransactionValidationOutcome, TransactionValidator, ValidPoolTransaction,
};
use reth_eth_wire::HandleMempoolData;
use reth_primitives::{Address, BlobTransactionSidecar, TxHash, U256};
@ -252,20 +252,21 @@ pub struct MockTransactionValidator<T> {
_marker: PhantomData<T>,
}
impl<T: PoolTransaction> TransactionValidator for MockTransactionValidator<T> {
impl<T: EthPoolTransaction> TransactionValidator for MockTransactionValidator<T> {
type Transaction = T;
async fn validate_transaction(
&self,
origin: TransactionOrigin,
transaction: Self::Transaction,
mut transaction: Self::Transaction,
) -> TransactionValidationOutcome<Self::Transaction> {
let maybe_sidecar = transaction.take_blob().maybe_sidecar().cloned();
// we return `balance: U256::MAX` to simulate a valid transaction which will never go into
// overdraft
TransactionValidationOutcome::Valid {
balance: U256::MAX,
state_nonce: 0,
transaction: ValidTransaction::Valid(transaction),
transaction: ValidTransaction::new(transaction, maybe_sidecar),
propagate: match origin {
TransactionOrigin::External => true,
TransactionOrigin::Local => self.propagate_local,
@ -285,7 +286,7 @@ impl<T> MockTransactionValidator<T> {
impl<T> Default for MockTransactionValidator<T> {
fn default() -> Self {
MockTransactionValidator { propagate_local: true, _marker: Default::default() }
Self { propagate_local: true, _marker: Default::default() }
}
}

View File

@ -4,7 +4,8 @@ use crate::{
identifier::{SenderIdentifiers, TransactionId},
pool::txpool::TxPool,
traits::TransactionOrigin,
CoinbaseTipOrdering, PoolTransaction, ValidPoolTransaction,
CoinbaseTipOrdering, EthBlobTransactionSidecar, EthPoolTransaction, PoolTransaction,
ValidPoolTransaction,
};
use paste::paste;
use rand::{
@ -15,11 +16,11 @@ use reth_primitives::{
constants::{eip4844::DATA_GAS_PER_BLOB, MIN_PROTOCOL_BASE_FEE},
eip4844::kzg_to_versioned_hash,
transaction::TryFromRecoveredTransactionError,
AccessList, Address, BlobTransactionSidecar, Bytes, ChainId, FromRecoveredPooledTransaction,
IntoRecoveredTransaction, PooledTransactionsElementEcRecovered, Signature, Transaction,
TransactionSigned, TransactionSignedEcRecovered, TryFromRecoveredTransaction, TxEip1559,
TxEip2930, TxEip4844, TxHash, TxKind, TxLegacy, TxType, B256, EIP1559_TX_TYPE_ID,
EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, U256,
AccessList, Address, BlobTransactionSidecar, BlobTransactionValidationError, Bytes, ChainId,
FromRecoveredPooledTransaction, IntoRecoveredTransaction, PooledTransactionsElementEcRecovered,
Signature, Transaction, TransactionSigned, TransactionSignedEcRecovered,
TryFromRecoveredTransaction, TxEip1559, TxEip2930, TxEip4844, TxHash, TxKind, TxLegacy, TxType,
B256, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, U256,
};
use std::{ops::Range, sync::Arc, time::Instant, vec::IntoIter};
@ -730,7 +731,40 @@ impl PoolTransaction for MockTransaction {
/// Returns the chain ID associated with the transaction.
fn chain_id(&self) -> Option<u64> {
Some(1)
match self {
MockTransaction::Legacy { chain_id, .. } => *chain_id,
MockTransaction::Eip1559 { chain_id, .. } |
MockTransaction::Eip4844 { chain_id, .. } |
MockTransaction::Eip2930 { chain_id, .. } => Some(*chain_id),
}
}
}
impl EthPoolTransaction for MockTransaction {
fn take_blob(&mut self) -> EthBlobTransactionSidecar {
match self {
Self::Eip4844 { sidecar, .. } => EthBlobTransactionSidecar::Present(sidecar.clone()),
_ => EthBlobTransactionSidecar::None,
}
}
fn blob_count(&self) -> usize {
match self {
Self::Eip4844 { sidecar, .. } => sidecar.blobs.len(),
_ => 0,
}
}
fn validate_blob(
&self,
_blob: &BlobTransactionSidecar,
_settings: &revm::primitives::KzgSettings,
) -> Result<(), reth_primitives::BlobTransactionValidationError> {
match &self {
Self::Eip4844 { .. } => Ok(()),
_ => Err(BlobTransactionValidationError::NotBlobTransaction(self.tx_type())),
}
}
}

View File

@ -14,8 +14,8 @@ use reth_primitives::{
kzg::KzgSettings, transaction::TryFromRecoveredTransactionError, AccessList, Address,
BlobTransactionSidecar, BlobTransactionValidationError, FromRecoveredPooledTransaction,
IntoRecoveredTransaction, PooledTransactionsElement, PooledTransactionsElementEcRecovered,
SealedBlock, Transaction, TransactionSignedEcRecovered, TryFromRecoveredTransaction, TxEip4844,
TxHash, TxKind, B256, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, U256,
SealedBlock, Transaction, TransactionSignedEcRecovered, TryFromRecoveredTransaction, TxHash,
TxKind, B256, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, U256,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -856,12 +856,7 @@ pub trait EthPoolTransaction: PoolTransaction {
fn take_blob(&mut self) -> EthBlobTransactionSidecar;
/// Returns the number of blobs this transaction has.
fn blob_count(&self) -> usize {
self.as_eip4844().map(|tx| tx.blob_versioned_hashes.len()).unwrap_or_default()
}
/// Returns the transaction as EIP-4844 transaction if it is one.
fn as_eip4844(&self) -> Option<&TxEip4844>;
fn blob_count(&self) -> usize;
/// Validates the blob sidecar of the transaction with the given settings.
fn validate_blob(
@ -908,6 +903,16 @@ pub enum EthBlobTransactionSidecar {
Present(BlobTransactionSidecar),
}
impl EthBlobTransactionSidecar {
/// Returns the blob sidecar if it is present
pub const fn maybe_sidecar(&self) -> Option<&BlobTransactionSidecar> {
match self {
EthBlobTransactionSidecar::Present(sidecar) => Some(sidecar),
_ => None,
}
}
}
impl EthPooledTransaction {
/// Create new instance of [Self].
///
@ -1096,8 +1101,11 @@ impl EthPoolTransaction for EthPooledTransaction {
}
}
fn as_eip4844(&self) -> Option<&TxEip4844> {
self.transaction.as_eip4844()
fn blob_count(&self) -> usize {
match &self.transaction.transaction {
Transaction::Eip4844(tx) => tx.blob_versioned_hashes.len(),
_ => 0,
}
}
fn validate_blob(
@ -1125,13 +1133,13 @@ impl TryFromRecoveredTransaction for EthPooledTransaction {
}
EIP4844_TX_TYPE_ID => {
// doesn't have a blob sidecar
return Err(TryFromRecoveredTransactionError::BlobSidecarMissing);
return Err(TryFromRecoveredTransactionError::BlobSidecarMissing)
}
unsupported => {
// unsupported transaction type
return Err(TryFromRecoveredTransactionError::UnsupportedTransactionType(
unsupported,
));
))
}
};

View File

@ -361,25 +361,17 @@ where
}
}
EthBlobTransactionSidecar::Present(blob) => {
if let Some(eip4844) = transaction.as_eip4844() {
// validate the blob
if let Err(err) = eip4844.validate_blob(&blob, &self.kzg_settings) {
return TransactionValidationOutcome::Invalid(
transaction,
InvalidPoolTransactionError::Eip4844(
Eip4844PoolTransactionError::InvalidEip4844Blob(err),
),
)
}
// store the extracted blob
maybe_blob_sidecar = Some(blob);
} else {
// this should not happen
// validate the blob
if let Err(err) = transaction.validate_blob(&blob, &self.kzg_settings) {
return TransactionValidationOutcome::Invalid(
transaction,
InvalidTransactionError::TxTypeNotSupported.into(),
InvalidPoolTransactionError::Eip4844(
Eip4844PoolTransactionError::InvalidEip4844Blob(err),
),
)
}
// store the extracted blob
maybe_blob_sidecar = Some(blob);
}
}
}