Skip to content

Commit

Permalink
feat: add blob sidecar extraction to tx validation (#4254)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Aug 17, 2023
1 parent 0bcd388 commit f53fdd5
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 17 deletions.
12 changes: 6 additions & 6 deletions crates/transaction-pool/src/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
//! to be generic over it.

use crate::{
error::PoolError, traits::PendingTransactionListenerKind, AllPoolTransactions,
AllTransactionsEvents, BestTransactions, BlockInfo, EthPooledTransaction, NewTransactionEvent,
PoolResult, PoolSize, PoolTransaction, PropagatedTransactions, TransactionEvents,
TransactionOrigin, TransactionPool, TransactionValidationOutcome, TransactionValidator,
ValidPoolTransaction,
error::PoolError, traits::PendingTransactionListenerKind, validate::ValidTransaction,
AllPoolTransactions, AllTransactionsEvents, BestTransactions, BlockInfo, EthPooledTransaction,
NewTransactionEvent, PoolResult, PoolSize, PoolTransaction, PropagatedTransactions,
TransactionEvents, TransactionOrigin, TransactionPool, TransactionValidationOutcome,
TransactionValidator, ValidPoolTransaction,
};
use reth_primitives::{Address, TxHash};
use std::{collections::HashSet, marker::PhantomData, sync::Arc};
Expand Down Expand Up @@ -184,7 +184,7 @@ impl<T: PoolTransaction> TransactionValidator for MockTransactionValidator<T> {
TransactionValidationOutcome::Valid {
balance: Default::default(),
state_nonce: 0,
transaction,
transaction: ValidTransaction::Valid(transaction),
propagate: match origin {
TransactionOrigin::External => true,
TransactionOrigin::Local => self.propagate_local,
Expand Down
15 changes: 14 additions & 1 deletion crates/transaction-pool/src/pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ mod events;
pub use events::{FullTransactionEvent, TransactionEvent};

mod listener;
use crate::{pool::txpool::UpdateOutcome, traits::PendingTransactionListenerKind};
use crate::{
pool::txpool::UpdateOutcome, traits::PendingTransactionListenerKind, validate::ValidTransaction,
};
pub use listener::{AllTransactionsEvents, TransactionEvents};

mod best;
Expand Down Expand Up @@ -314,6 +316,17 @@ where
let transaction_id = TransactionId::new(sender_id, transaction.nonce());
let encoded_length = transaction.encoded_length();

let (transaction, _maybe_sidecar) = match transaction {
ValidTransaction::Valid(tx) => (tx, None),
ValidTransaction::ValidWithSidecar { transaction, sidecar } => {
debug_assert!(
transaction.is_eip4844(),
"validator returned sidecar for non EIP-4844 transaction"
);
(transaction, Some(sidecar))
}
};

let tx = ValidPoolTransaction {
transaction,
transaction_id,
Expand Down
6 changes: 3 additions & 3 deletions crates/transaction-pool/src/validate/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::{
error::InvalidPoolTransactionError,
traits::{PoolTransaction, TransactionOrigin},
validate::{
task::ValidationJobSender, TransactionValidatorError, ValidationTask, MAX_INIT_CODE_SIZE,
TX_MAX_SIZE,
task::ValidationJobSender, TransactionValidatorError, ValidTransaction, ValidationTask,
MAX_INIT_CODE_SIZE, TX_MAX_SIZE,
},
TransactionValidationOutcome, TransactionValidator,
};
Expand Down Expand Up @@ -499,7 +499,7 @@ where
TransactionValidationOutcome::Valid {
balance: account.balance,
state_nonce: account.nonce,
transaction,
transaction: ValidTransaction::Valid(transaction),
// by this point assume all external transactions should be propagated
propagate: match origin {
TransactionOrigin::External => true,
Expand Down
77 changes: 73 additions & 4 deletions crates/transaction-pool/src/validate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::{
traits::{PoolTransaction, TransactionOrigin},
};
use reth_primitives::{
Address, IntoRecoveredTransaction, TransactionKind, TransactionSignedEcRecovered, TxHash, U256,
Address, BlobTransactionSidecar, IntoRecoveredTransaction, TransactionKind,
TransactionSignedEcRecovered, TxHash, H256, U256,
};
use std::{fmt, time::Instant};

Expand All @@ -32,9 +33,13 @@ pub enum TransactionValidationOutcome<T: PoolTransaction> {
balance: U256,
/// Current nonce of the sender.
state_nonce: u64,
/// Validated transaction.
// TODO add enum type for blob,regular?
transaction: T,
/// The validated transaction.
///
/// See also [ValidTransaction].
///
/// If this is a _new_ EIP-4844 blob transaction, then this must contain the extracted
/// sidecar.
transaction: ValidTransaction<T>,
/// Whether to propagate the transaction to the network.
propagate: bool,
},
Expand All @@ -56,6 +61,65 @@ impl<T: PoolTransaction> TransactionValidationOutcome<T> {
}
}

/// A wrapper type for a transaction that is valid and has an optional extracted EIP-4844 blob
/// transaction sidecar.
///
/// If this is provided, then the sidecar will be temporarily stored in the blob store until the
/// transaction is finalized.
///
/// Note: Since blob transactions can be re-injected without their sidecar (after reorg), the
/// validator can omit the sidecar if it is still in the blob store and return a
/// [ValidTransaction::Valid] instead.
#[derive(Debug)]
pub enum ValidTransaction<T> {
/// A valid transaction without a sidecar.
Valid(T),
/// A valid transaction for which a sidecar should be stored.
///
/// Caution: The [TransactionValidator] must ensure that this is only returned for EIP-4844
/// transactions.
ValidWithSidecar {
/// The valid EIP-4844 transaction.
transaction: T,
/// The extracted sidecar of that transaction
sidecar: BlobTransactionSidecar,
},
}

impl<T: PoolTransaction> ValidTransaction<T> {
#[inline]
pub(crate) fn transaction(&self) -> &T {
match self {
Self::Valid(transaction) => transaction,
Self::ValidWithSidecar { transaction, .. } => transaction,
}
}

/// Returns the address of that transaction.
#[inline]
pub(crate) fn sender(&self) -> Address {
self.transaction().sender()
}

/// Returns the hash of the transaction.
#[inline]
pub(crate) fn hash(&self) -> &H256 {
self.transaction().hash()
}

/// Returns the length of the rlp encoded object
#[inline]
pub(crate) fn encoded_length(&self) -> usize {
self.transaction().encoded_length()
}

/// Returns the nonce of the transaction.
#[inline]
pub(crate) fn nonce(&self) -> u64 {
self.transaction().nonce()
}
}

/// Provides support for validating transaction at any given state of the chain
#[async_trait::async_trait]
pub trait TransactionValidator: Send + Sync {
Expand Down Expand Up @@ -113,6 +177,11 @@ pub trait TransactionValidator: Send + Sync {
}

/// A valid transaction in the pool.
///
/// This is used as the internal representation of a transaction inside the pool.
///
/// For EIP-4844 blob transactions this will _not_ contain the blob sidecar which is stored
/// separately in the [BlobStore](crate::blobstore::BlobStore).
pub struct ValidPoolTransaction<T: PoolTransaction> {
/// The transaction
pub transaction: T,
Expand Down
6 changes: 3 additions & 3 deletions examples/network-txpool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
use reth_network::{config::rng_secret_key, NetworkConfig, NetworkManager};
use reth_provider::test_utils::NoopProvider;
use reth_transaction_pool::{
CoinbaseTipOrdering, EthPooledTransaction, PoolTransaction, TransactionOrigin, TransactionPool,
TransactionValidationOutcome, TransactionValidator,
validate::ValidTransaction, CoinbaseTipOrdering, EthPooledTransaction, PoolTransaction,
TransactionOrigin, TransactionPool, TransactionValidationOutcome, TransactionValidator,
};

#[tokio::main]
Expand Down Expand Up @@ -79,7 +79,7 @@ impl TransactionValidator for OkValidator {
TransactionValidationOutcome::Valid {
balance: transaction.cost(),
state_nonce: transaction.nonce(),
transaction,
transaction: ValidTransaction::Valid(transaction),
propagate: false,
}
}
Expand Down

0 comments on commit f53fdd5

Please sign in to comment.