Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add BestTransactionsWithAttributes blob fee checks #6674

Merged
merged 11 commits into from Feb 22, 2024
16 changes: 12 additions & 4 deletions crates/transaction-pool/src/pool/best.rs
Expand Up @@ -17,13 +17,14 @@ use tracing::debug;
///
/// This is a wrapper around [`BestTransactions`] that also enforces a specific basefee.
///
/// This iterator guarantees that all transaction it returns satisfy the base fee.
pub(crate) struct BestTransactionsWithBasefee<T: TransactionOrdering> {
/// This iterator guarantees that all transaction it returns satisfy both the base fee and blob fee!
pub(crate) struct BestTransactionsWithFees<T: TransactionOrdering> {
pub(crate) best: BestTransactions<T>,
pub(crate) base_fee: u64,
pub(crate) base_fee_per_blob_gas: u64,
}

impl<T: TransactionOrdering> crate::traits::BestTransactions for BestTransactionsWithBasefee<T> {
impl<T: TransactionOrdering> crate::traits::BestTransactions for BestTransactionsWithFees<T> {
fn mark_invalid(&mut self, tx: &Self::Item) {
BestTransactions::mark_invalid(&mut self.best, tx)
}
Expand All @@ -41,7 +42,7 @@ impl<T: TransactionOrdering> crate::traits::BestTransactions for BestTransaction
}
}

impl<T: TransactionOrdering> Iterator for BestTransactionsWithBasefee<T> {
impl<T: TransactionOrdering> Iterator for BestTransactionsWithFees<T> {
type Item = Arc<ValidPoolTransaction<T::Transaction>>;

fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -52,6 +53,13 @@ impl<T: TransactionOrdering> Iterator for BestTransactionsWithBasefee<T> {
// tx violates base fee, mark it as invalid and continue
crate::traits::BestTransactions::mark_invalid(self, &best);
} else {
// tx is EIP4844 and violates blob fee, mark it as invalid and continue
if best.transaction.max_fee_per_blob_gas().is_some_and(|max_fee_per_blob_gas| {
max_fee_per_blob_gas < self.base_fee_per_blob_gas as u128
}) {
crate::traits::BestTransactions::mark_invalid(self, &best);
continue;
};
return Some(best)
}
}
Expand Down
26 changes: 24 additions & 2 deletions crates/transaction-pool/src/pool/blob.rs
Expand Up @@ -81,11 +81,33 @@ impl<T: PoolTransaction> BlobTransactions<T> {
}

/// Returns all transactions that satisfy the given basefee and blob_fee.
pub(crate) const fn satisfy_attributes(
pub(crate) fn satisfy_attributes(
&self,
_best_transactions_attributes: BestTransactionsAttributes,
allnil marked this conversation as resolved.
Show resolved Hide resolved
) -> Vec<Arc<ValidPoolTransaction<T>>> {
Vec::new()
let mut transactions = Vec::new();
{
let mut iter = self.by_id.iter().peekable();

while let Some((id, tx)) = iter.next() {
if tx.transaction.max_fee_per_blob_gas().unwrap_or_default() <
_best_transactions_attributes.blob_fee.unwrap_or_default() as u128 ||
tx.transaction.max_fee_per_gas() <
_best_transactions_attributes.basefee as u128
{
mattsse marked this conversation as resolved.
Show resolved Hide resolved
// still parked in blob pool -> skip descendant transactions
'this: while let Some((peek, _)) = iter.peek() {
if peek.sender != id.sender {
break 'this
}
iter.next();
}
} else {
transactions.push(tx.transaction.clone());
}
}
}
transactions
}

/// The reported size of all transactions in this pool.
Expand Down
12 changes: 8 additions & 4 deletions crates/transaction-pool/src/pool/pending.rs
@@ -1,7 +1,7 @@
use crate::{
identifier::{SenderId, TransactionId},
pool::{
best::{BestTransactions, BestTransactionsWithBasefee},
best::{BestTransactions, BestTransactionsWithFees},
size::SizeTracker,
},
Priority, SubPoolLimit, TransactionOrdering, ValidPoolTransaction,
Expand Down Expand Up @@ -115,9 +115,13 @@ impl<T: TransactionOrdering> PendingPool<T> {
}
}

/// Same as `best` but only returns transactions that satisfy the given basefee.
pub(crate) fn best_with_basefee(&self, base_fee: u64) -> BestTransactionsWithBasefee<T> {
BestTransactionsWithBasefee { best: self.best(), base_fee }
/// Same as `best` but only returns transactions that satisfy the given basefee and blobfee.
pub(crate) fn best_with_basefee_and_blobfee(
&self,
base_fee: u64,
base_fee_per_blob_gas: u64,
) -> BestTransactionsWithFees<T> {
BestTransactionsWithFees { best: self.best(), base_fee, base_fee_per_blob_gas }
}

/// Same as `best` but also includes the given unlocked transactions.
Expand Down
21 changes: 17 additions & 4 deletions crates/transaction-pool/src/pool/txpool.rs
Expand Up @@ -291,7 +291,6 @@ impl<T: TransactionOrdering> TxPool<T> {
pub(crate) fn best_transactions(&self) -> BestTransactions<T> {
self.pending_pool.best()
}

/// Returns an iterator that yields transactions that are ready to be included in the block with
/// the given base fee and optional blob fee.
pub(crate) fn best_transactions_with_attributes(
Expand All @@ -302,12 +301,26 @@ impl<T: TransactionOrdering> TxPool<T> {
match best_transactions_attributes.basefee.cmp(&self.all_transactions.pending_fees.base_fee)
{
Ordering::Equal => {
// fee unchanged, nothing to shift
Box::new(self.best_transactions())
// check if blob_fee become lower
let mut unlocked_with_blob = Vec::new();
if best_transactions_attributes.blob_fee.unwrap_or_default() <
self.all_transactions.pending_fees.blob_fee as u64
{
unlocked_with_blob =
self.blob_pool.satisfy_attributes(best_transactions_attributes);
}

Box::new(self.pending_pool.best_with_unlocked(
unlocked_with_blob,
self.all_transactions.pending_fees.base_fee,
))
}
Ordering::Greater => {
// base fee increased, we only need to enforce this on the pending pool
Box::new(self.pending_pool.best_with_basefee(best_transactions_attributes.basefee))
Box::new(self.pending_pool.best_with_basefee_and_blobfee(
best_transactions_attributes.basefee,
best_transactions_attributes.blob_fee.unwrap_or_default(),
))
allnil marked this conversation as resolved.
Show resolved Hide resolved
}
Ordering::Less => {
// base fee decreased, we need to move transactions from the basefee pool to the
Expand Down