Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/rpc/rpc/src/eth/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ pub enum RpcPoolError {
/// Custom pool error
#[error("{0:?}")]
PoolTransactionError(Box<dyn PoolTransactionError>),
/// Unable to find the blob for an EIP4844 transaction
#[error("blob not found for EIP4844 transaction")]
MissingEip4844Blob,
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
Expand Down Expand Up @@ -508,6 +511,7 @@ impl From<InvalidPoolTransactionError> for RpcPoolError {
InvalidPoolTransactionError::OversizedData(_, _) => RpcPoolError::OversizedData,
InvalidPoolTransactionError::Underpriced => RpcPoolError::Underpriced,
InvalidPoolTransactionError::Other(err) => RpcPoolError::PoolTransactionError(err),
InvalidPoolTransactionError::MissingEip4844Blob => RpcPoolError::MissingEip4844Blob,
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions crates/transaction-pool/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ pub enum InvalidPoolTransactionError {
/// Thrown if the transaction's fee is below the minimum fee
#[error("transaction underpriced")]
Underpriced,
/// Thrown if we're unable to find the blob for a transaction that was previously extracted
#[error("blob not found for EIP4844 transaction")]
MissingEip4844Blob,
/// Any other error that occurred while inserting/validating that is transaction specific
#[error("{0:?}")]
Other(Box<dyn PoolTransactionError>),
Expand Down Expand Up @@ -195,6 +198,11 @@ impl InvalidPoolTransactionError {
false
}
InvalidPoolTransactionError::Other(err) => err.is_bad_transaction(),
InvalidPoolTransactionError::MissingEip4844Blob => {
// this is only reachable when blob transactions are reinjected and we're unable to
// find the previously extracted blob
false
}
}
}
}
7 changes: 4 additions & 3 deletions crates/transaction-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,10 @@ pub use crate::{
},
traits::{
AllPoolTransactions, BestTransactions, BlockInfo, CanonicalStateUpdate, ChangedAccount,
EthPooledTransaction, GetPooledTransactionLimit, NewTransactionEvent,
PendingTransactionListenerKind, PoolSize, PoolTransaction, PropagateKind,
PropagatedTransactions, TransactionOrigin, TransactionPool, TransactionPoolExt,
EthBlobTransactionSidecar, EthPoolTransaction, EthPooledTransaction,
GetPooledTransactionLimit, NewTransactionEvent, PendingTransactionListenerKind, PoolSize,
PoolTransaction, PropagateKind, PropagatedTransactions, TransactionOrigin, TransactionPool,
TransactionPoolExt,
},
validate::{
EthTransactionValidator, TransactionValidationOutcome, TransactionValidationTaskExecutor,
Expand Down
19 changes: 18 additions & 1 deletion crates/transaction-pool/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,13 @@ pub trait PoolTransaction:
fn chain_id(&self) -> Option<u64>;
}

/// An extension trait that provides additional interfaces for the
/// [EthTransactionValidator](crate::EthTransactionValidator).
pub trait EthPoolTransaction: PoolTransaction {
/// Extracts the blob sidecar from the transaction.
fn take_blob(&mut self) -> EthBlobTransactionSidecar;
}

/// The default [PoolTransaction] for the [Pool](crate::Pool) for Ethereum.
///
/// This type is essentially a wrapper around [TransactionSignedEcRecovered] with additional fields
Expand All @@ -659,7 +666,7 @@ pub struct EthPooledTransaction {

/// Represents the blob sidecar of the [EthPooledTransaction].
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum EthBlobTransactionSidecar {
pub enum EthBlobTransactionSidecar {
/// This transaction does not have a blob sidecar
None,
/// This transaction has a blob sidecar (EIP-4844) but it is missing
Expand Down Expand Up @@ -812,6 +819,16 @@ impl PoolTransaction for EthPooledTransaction {
}
}

impl EthPoolTransaction for EthPooledTransaction {
fn take_blob(&mut self) -> EthBlobTransactionSidecar {
if self.is_eip4844() {
std::mem::replace(&mut self.blob_sidecar, EthBlobTransactionSidecar::Missing)
} else {
EthBlobTransactionSidecar::None
}
}
}

impl FromRecoveredTransaction for EthPooledTransaction {
fn from_recovered_transaction(tx: TransactionSignedEcRecovered) -> Self {
EthPooledTransaction::new(tx)
Expand Down
42 changes: 34 additions & 8 deletions crates/transaction-pool/src/validate/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
use crate::{
blobstore::BlobStore,
error::InvalidPoolTransactionError,
traits::{PoolTransaction, TransactionOrigin},
traits::TransactionOrigin,
validate::{ValidTransaction, ValidationTask, MAX_INIT_CODE_SIZE, TX_MAX_SIZE},
TransactionValidationOutcome, TransactionValidationTaskExecutor, TransactionValidator,
EthBlobTransactionSidecar, EthPoolTransaction, TransactionValidationOutcome,
TransactionValidationTaskExecutor, TransactionValidator,
};
use reth_primitives::{
constants::{eip4844::KZG_TRUSTED_SETUP, ETHEREUM_BLOCK_GAS_LIMIT},
Expand All @@ -32,7 +33,7 @@ pub struct EthTransactionValidator<Client, T> {
impl<Client, Tx> TransactionValidator for EthTransactionValidator<Client, Tx>
where
Client: StateProviderFactory,
Tx: PoolTransaction,
Tx: EthPoolTransaction,
{
type Transaction = Tx;

Expand All @@ -57,7 +58,6 @@ pub(crate) struct EthTransactionValidatorInner<Client, T> {
/// This type fetches account info from the db
client: Client,
/// Blobstore used for fetching re-injected blob transactions.
#[allow(unused)]
blob_store: Box<dyn BlobStore>,
/// tracks activated forks relevant for transaction validation
fork_tracker: ForkTracker,
Expand Down Expand Up @@ -93,14 +93,14 @@ impl<Client, Tx> EthTransactionValidatorInner<Client, Tx> {
impl<Client, Tx> TransactionValidator for EthTransactionValidatorInner<Client, Tx>
where
Client: StateProviderFactory,
Tx: PoolTransaction,
Tx: EthPoolTransaction,
{
type Transaction = Tx;

async fn validate_transaction(
&self,
origin: TransactionOrigin,
transaction: Self::Transaction,
mut transaction: Self::Transaction,
) -> TransactionValidationOutcome<Self::Transaction> {
// Checks for tx_type
match transaction.tx_type() {
Expand Down Expand Up @@ -198,6 +198,8 @@ where
}
}

let mut blob_sidecar = None;

// blob tx checks
if transaction.is_eip4844() {
// Cancun fork is required for blob txs
Expand All @@ -207,7 +209,31 @@ where
InvalidTransactionError::TxTypeNotSupported.into(),
)
}
// TODO add checks for blob tx

// extract the blob from the transaction
match transaction.take_blob() {
EthBlobTransactionSidecar::None => {
// this should not happen
return TransactionValidationOutcome::Invalid(
transaction,
InvalidTransactionError::TxTypeNotSupported.into(),
)
}
EthBlobTransactionSidecar::Missing => {
if let Ok(Some(_)) = self.blob_store.get(*transaction.hash()) {
// validated transaction is already in the store
} else {
return TransactionValidationOutcome::Invalid(
transaction,
InvalidPoolTransactionError::MissingEip4844Blob,
)
}
}
Comment on lines +225 to +231
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense

EthBlobTransactionSidecar::Present(blob) => {
//TODO(mattsse): verify the blob
blob_sidecar = Some(blob);
}
}
}

let account = match self
Expand Down Expand Up @@ -255,7 +281,7 @@ where
TransactionValidationOutcome::Valid {
balance: account.balance,
state_nonce: account.nonce,
transaction: ValidTransaction::Valid(transaction),
transaction: ValidTransaction::new(transaction, blob_sidecar),
// by this point assume all external transactions should be propagated
propagate: match origin {
TransactionOrigin::External => true,
Expand Down
11 changes: 11 additions & 0 deletions crates/transaction-pool/src/validate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ pub enum ValidTransaction<T> {
},
}

impl<T> ValidTransaction<T> {
/// Creates a new valid transaction with an optional sidecar.
pub fn new(transaction: T, sidecar: Option<BlobTransactionSidecar>) -> Self {
if let Some(sidecar) = sidecar {
Self::ValidWithSidecar { transaction, sidecar }
} else {
Self::Valid(transaction)
}
}
}

impl<T: PoolTransaction> ValidTransaction<T> {
#[inline]
pub(crate) fn transaction(&self) -> &T {
Expand Down