feat: add blob sidecar extraction to tx validation (#4254)

This commit is contained in:
Matthias Seitz
2023-08-17 21:57:40 +02:00
committed by GitHub
parent 0bcd388a20
commit f53fdd5329
5 changed files with 99 additions and 17 deletions

View File

@ -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};
@ -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,

View File

@ -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;
@ -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,

View File

@ -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,
};
@ -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,

View File

@ -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};
@ -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,
},
@ -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 {
@ -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,