diff --git a/crates/transaction-pool/src/pool/best.rs b/crates/transaction-pool/src/pool/best.rs index 36a14edaa2..068ef98995 100644 --- a/crates/transaction-pool/src/pool/best.rs +++ b/crates/transaction-pool/src/pool/best.rs @@ -128,6 +128,15 @@ impl BestTransactions { } } + /// Removes the currently best independent transaction from the independent set and the total + /// set. + fn pop_best(&mut self) -> Option> { + self.independent.pop_last().inspect(|best| { + let removed = self.all.remove(best.transaction.id()); + debug_assert!(removed.is_some(), "must be present in both sets"); + }) + } + /// Checks for new transactions that have come into the `PendingPool` after this iterator was /// created and inserts them fn add_new_transactions(&mut self) { @@ -167,7 +176,7 @@ impl Iterator for BestTransactions { loop { self.add_new_transactions(); // Remove the next independent tx with the highest priority - let best = self.independent.pop_last()?; + let best = self.pop_best()?; let sender_id = best.transaction.sender_id(); // skip transactions for which sender was marked as invalid diff --git a/crates/transaction-pool/src/pool/pending.rs b/crates/transaction-pool/src/pool/pending.rs index ff5269014c..c9cfd85e28 100644 --- a/crates/transaction-pool/src/pool/pending.rs +++ b/crates/transaction-pool/src/pool/pending.rs @@ -815,4 +815,47 @@ mod tests { pending.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::>(); assert_eq!(pending, expected_pending); } + + // + #[test] + fn test_eligible_updates_promoted() { + let mut pool = PendingPool::new(MockOrdering::default()); + let mut f = MockTransactionFactory::default(); + + let num_senders = 10; + + let first_txs: Vec<_> = (0..num_senders) // + .map(|_| MockTransaction::eip1559()) + .collect(); + let second_txs: Vec<_> = + first_txs.iter().map(|tx| tx.clone().rng_hash().inc_nonce()).collect(); + + for tx in first_txs { + let valid_tx = f.validated(tx); + pool.add_transaction(Arc::new(valid_tx), 0); + } + + let mut best = pool.best(); + + for _ in 0..num_senders { + if let Some(tx) = best.next() { + assert_eq!(tx.nonce(), 0); + } else { + panic!("cannot read one of first_txs"); + } + } + + for tx in second_txs { + let valid_tx = f.validated(tx); + pool.add_transaction(Arc::new(valid_tx), 0); + } + + for _ in 0..num_senders { + if let Some(tx) = best.next() { + assert_eq!(tx.nonce(), 1); + } else { + panic!("cannot read one of second_txs"); + } + } + } }