feat: extend txpool remove txs utility (#11702)

This commit is contained in:
caglarkaya
2024-10-15 11:19:23 +03:00
committed by GitHub
parent e0a26ac9a2
commit 2a86245649
5 changed files with 253 additions and 3 deletions

View File

@ -463,6 +463,20 @@ where
self.pool.remove_transactions(hashes)
}
fn remove_transactions_and_descendants(
&self,
hashes: Vec<TxHash>,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
self.pool.remove_transactions_and_descendants(hashes)
}
fn remove_transactions_by_sender(
&self,
sender: Address,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
self.pool.remove_transactions_by_sender(sender)
}
fn retain_unknown<A>(&self, announcement: &mut A)
where
A: HandleMempoolData,

View File

@ -183,6 +183,20 @@ impl TransactionPool for NoopTransactionPool {
vec![]
}
fn remove_transactions_and_descendants(
&self,
_hashes: Vec<TxHash>,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
vec![]
}
fn remove_transactions_by_sender(
&self,
_sender: Address,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
vec![]
}
fn retain_unknown<A>(&self, _announcement: &mut A)
where
A: HandleMempoolData,

View File

@ -195,7 +195,7 @@ where
pub(crate) fn block_info(&self) -> BlockInfo {
self.get_pool_data().block_info()
}
/// Returns the currently tracked block
/// Sets the currently tracked block
pub(crate) fn set_block_info(&self, info: BlockInfo) {
self.pool.write().set_block_info(info)
}
@ -715,6 +715,38 @@ where
removed
}
/// Removes and returns all matching transactions and their dependent transactions from the
/// pool.
pub(crate) fn remove_transactions_and_descendants(
&self,
hashes: Vec<TxHash>,
) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
if hashes.is_empty() {
return Vec::new()
}
let removed = self.pool.write().remove_transactions_and_descendants(hashes);
let mut listener = self.event_listener.write();
removed.iter().for_each(|tx| listener.discarded(tx.hash()));
removed
}
pub(crate) fn remove_transactions_by_sender(
&self,
sender: Address,
) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
let sender_id = self.get_sender_id(sender);
let removed = self.pool.write().remove_transactions_by_sender(sender_id);
let mut listener = self.event_listener.write();
removed.iter().for_each(|tx| listener.discarded(tx.hash()));
removed
}
/// Removes and returns all transactions that are present in the pool.
pub(crate) fn retain_unknown<A>(&self, announcement: &mut A)
where

View File

@ -663,6 +663,38 @@ impl<T: TransactionOrdering> TxPool<T> {
txs
}
/// Removes and returns all matching transactions and their descendants from the pool.
pub(crate) fn remove_transactions_and_descendants(
&mut self,
hashes: Vec<TxHash>,
) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
let mut removed = Vec::new();
for hash in hashes {
if let Some(tx) = self.remove_transaction_by_hash(&hash) {
removed.push(tx.clone());
self.remove_descendants(tx.id(), &mut removed);
}
}
self.update_size_metrics();
removed
}
/// Removes all transactions from the given sender.
pub(crate) fn remove_transactions_by_sender(
&mut self,
sender_id: SenderId,
) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
let mut removed = Vec::new();
let txs = self.get_transactions_by_sender(sender_id);
for tx in txs {
if let Some(tx) = self.remove_transaction(tx.id()) {
removed.push(tx);
}
}
self.update_size_metrics();
removed
}
/// Remove the transaction from the __entire__ pool.
///
/// This includes the total set of transaction and the subpool it currently resides in.
@ -2963,6 +2995,148 @@ mod tests {
assert_eq!(vec![v1.nonce()], pool_txs);
}
#[test]
fn test_remove_transactions() {
let on_chain_balance = U256::from(10_000);
let on_chain_nonce = 0;
let mut f = MockTransactionFactory::default();
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
let tx_0 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_1 = tx_0.next();
let tx_2 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_3 = tx_2.next();
// Create 4 transactions
let v0 = f.validated(tx_0);
let v1 = f.validated(tx_1);
let v2 = f.validated(tx_2);
let v3 = f.validated(tx_3);
// Add them to the pool
let _res = pool.add_transaction(v0.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v1.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v2.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v3.clone(), on_chain_balance, on_chain_nonce).unwrap();
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(4, pool.pending_transactions().len());
pool.remove_transactions(vec![*v0.hash(), *v2.hash()]);
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(2, pool.pending_transactions().len());
assert!(pool.contains(v1.hash()));
assert!(pool.contains(v3.hash()));
}
#[test]
fn test_remove_transactions_and_descendants() {
let on_chain_balance = U256::from(10_000);
let on_chain_nonce = 0;
let mut f = MockTransactionFactory::default();
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
let tx_0 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_1 = tx_0.next();
let tx_2 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_3 = tx_2.next();
let tx_4 = tx_3.next();
// Create 5 transactions
let v0 = f.validated(tx_0);
let v1 = f.validated(tx_1);
let v2 = f.validated(tx_2);
let v3 = f.validated(tx_3);
let v4 = f.validated(tx_4);
// Add them to the pool
let _res = pool.add_transaction(v0.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v1, on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v2.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v3, on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v4, on_chain_balance, on_chain_nonce).unwrap();
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(5, pool.pending_transactions().len());
pool.remove_transactions_and_descendants(vec![*v0.hash(), *v2.hash()]);
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(0, pool.pending_transactions().len());
}
#[test]
fn test_remove_descendants() {
let on_chain_balance = U256::from(10_000);
let on_chain_nonce = 0;
let mut f = MockTransactionFactory::default();
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
let tx_0 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_1 = tx_0.next();
let tx_2 = tx_1.next();
let tx_3 = tx_2.next();
// Create 4 transactions
let v0 = f.validated(tx_0);
let v1 = f.validated(tx_1);
let v2 = f.validated(tx_2);
let v3 = f.validated(tx_3);
// Add them to the pool
let _res = pool.add_transaction(v0.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v1, on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v2, on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v3, on_chain_balance, on_chain_nonce).unwrap();
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(4, pool.pending_transactions().len());
let mut removed = Vec::new();
pool.remove_transaction(v0.id());
pool.remove_descendants(v0.id(), &mut removed);
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(0, pool.pending_transactions().len());
assert_eq!(3, removed.len());
}
#[test]
fn test_remove_transactions_by_sender() {
let on_chain_balance = U256::from(10_000);
let on_chain_nonce = 0;
let mut f = MockTransactionFactory::default();
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
let tx_0 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_1 = tx_0.next();
let tx_2 = MockTransaction::eip1559().set_gas_price(100).inc_limit();
let tx_3 = tx_2.next();
let tx_4 = tx_3.next();
// Create 5 transactions
let v0 = f.validated(tx_0);
let v1 = f.validated(tx_1);
let v2 = f.validated(tx_2);
let v3 = f.validated(tx_3);
let v4 = f.validated(tx_4);
// Add them to the pool
let _res = pool.add_transaction(v0.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v1.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v2.clone(), on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v3, on_chain_balance, on_chain_nonce).unwrap();
let _res = pool.add_transaction(v4, on_chain_balance, on_chain_nonce).unwrap();
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(5, pool.pending_transactions().len());
pool.remove_transactions_by_sender(v2.sender_id());
assert_eq!(0, pool.queued_transactions().len());
assert_eq!(2, pool.pending_transactions().len());
assert!(pool.contains(v0.hash()));
assert!(pool.contains(v1.hash()));
}
#[test]
fn wrong_best_order_of_transactions() {
let on_chain_balance = U256::from(10_000);
let mut on_chain_nonce = 0;

View File

@ -293,14 +293,30 @@ pub trait TransactionPool: Send + Sync + Clone {
/// Removes all transactions corresponding to the given hashes.
///
/// Also removes all _dependent_ transactions.
///
/// Consumer: Utility
fn remove_transactions(
&self,
hashes: Vec<TxHash>,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>>;
/// Removes all transactions corresponding to the given hashes.
///
/// Also removes all _dependent_ transactions.
///
/// Consumer: Utility
fn remove_transactions_and_descendants(
&self,
hashes: Vec<TxHash>,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>>;
/// Removes all transactions from the given sender
///
/// Consumer: Utility
fn remove_transactions_by_sender(
&self,
sender: Address,
) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>>;
/// Retains only those hashes that are unknown to the pool.
/// In other words, removes all transactions from the given set that are currently present in
/// the pool. Returns hashes already known to the pool.