1use crate::{
2 error::{Eip4844PoolTransactionError, InvalidPoolTransactionError},
3 identifier::{SenderId, TransactionId},
4 pool::pending::PendingTransaction,
5 PoolTransaction, Priority, TransactionOrdering, ValidPoolTransaction,
6};
7use alloy_consensus::Transaction;
8use alloy_primitives::map::AddressSet;
9use core::fmt;
10use imbl::OrdMap;
11use reth_primitives_traits::transaction::error::InvalidTransactionError;
12use rustc_hash::FxHashSet;
13use std::{
14 collections::{BTreeSet, VecDeque},
15 sync::Arc,
16};
17use tokio::sync::broadcast::{error::TryRecvError, Receiver};
18use tracing::debug;
19
20const MAX_NEW_TRANSACTIONS_PER_BATCH: usize = 16;
21
22pub(crate) struct BestTransactionsWithFees<T: TransactionOrdering> {
30 pub(crate) best: BestTransactions<T>,
31 pub(crate) base_fee: u64,
32 pub(crate) base_fee_per_blob_gas: u64,
33}
34
35impl<T: TransactionOrdering> crate::traits::BestTransactions for BestTransactionsWithFees<T> {
36 fn mark_invalid(&mut self, tx: &Self::Item, kind: InvalidPoolTransactionError) {
37 BestTransactions::mark_invalid(&mut self.best, tx, kind)
38 }
39
40 fn no_updates(&mut self) {
41 self.best.no_updates()
42 }
43
44 fn allow_updates_out_of_order(&mut self) {
45 self.best.allow_updates_out_of_order()
46 }
47
48 fn skip_blobs(&mut self) {
49 self.set_skip_blobs(true)
50 }
51
52 fn set_skip_blobs(&mut self, skip_blobs: bool) {
53 self.best.set_skip_blobs(skip_blobs)
54 }
55}
56
57impl<T: TransactionOrdering> Iterator for BestTransactionsWithFees<T> {
58 type Item = Arc<ValidPoolTransaction<T::Transaction>>;
59
60 fn next(&mut self) -> Option<Self::Item> {
61 loop {
63 let best = Iterator::next(&mut self.best)?;
64 if best.transaction.max_fee_per_gas() >= self.base_fee as u128 &&
67 best.transaction
68 .max_fee_per_blob_gas()
69 .is_none_or(|fee| fee >= self.base_fee_per_blob_gas as u128)
70 {
71 return Some(best);
72 }
73 crate::traits::BestTransactions::mark_invalid(
74 self,
75 &best,
76 InvalidPoolTransactionError::Underpriced,
77 );
78 }
79 }
80
81 fn size_hint(&self) -> (usize, Option<usize>) {
82 let (_, upper) = self.best.size_hint();
83 (0, upper)
84 }
85}
86
87#[derive(Debug)]
95pub struct BestTransactions<T: TransactionOrdering> {
96 pub(crate) all: OrdMap<TransactionId, PendingTransaction<T>>,
99 pub(crate) independent: BTreeSet<PendingTransaction<T>>,
104 pub(crate) invalid: FxHashSet<SenderId>,
106 pub(crate) new_transaction_receiver: Option<Receiver<PendingTransaction<T>>>,
112 pub(crate) last_priority: Option<Priority<T::PriorityValue>>,
116 pub(crate) skip_blobs: bool,
118 pub(crate) allow_updates_out_of_order: bool,
120}
121
122impl<T: TransactionOrdering> BestTransactions<T> {
123 pub(crate) fn mark_invalid(
125 &mut self,
126 tx: &Arc<ValidPoolTransaction<T::Transaction>>,
127 _kind: InvalidPoolTransactionError,
128 ) {
129 self.invalid.insert(tx.sender_id());
130 }
131
132 pub(crate) fn ancestor(&self, id: &TransactionId) -> Option<&PendingTransaction<T>> {
137 self.all.get(&id.unchecked_ancestor()?)
138 }
139
140 fn try_recv(&mut self) -> Option<IncomingTransaction<T>> {
142 loop {
143 match self.new_transaction_receiver.as_mut()?.try_recv() {
144 Ok(tx) => {
145 if !self.allow_updates_out_of_order &&
146 let Some(last_priority) = &self.last_priority &&
147 &tx.priority > last_priority
148 {
149 return Some(IncomingTransaction::Stash(tx))
152 }
153 return Some(IncomingTransaction::Process(tx))
154 }
155 Err(TryRecvError::Lagged(_)) => {
161 }
164
165 Err(_) => return None,
168 }
169 }
170 }
171
172 fn pop_best(&mut self) -> Option<PendingTransaction<T>> {
175 self.independent.pop_last().inspect(|best| {
176 self.all.remove(best.transaction.id());
177 })
178 }
179
180 fn add_new_transactions(&mut self) {
183 for _ in 0..MAX_NEW_TRANSACTIONS_PER_BATCH {
184 if let Some(pending_tx) = self.try_recv() {
185 match pending_tx {
188 IncomingTransaction::Process(tx) => {
189 let tx_id = *tx.transaction.id();
190 if self.ancestor(&tx_id).is_none() {
191 self.independent.insert(tx.clone());
192 }
193 self.all.insert(tx_id, tx);
194 }
195 IncomingTransaction::Stash(tx) => {
196 let tx_id = *tx.transaction.id();
197 self.all.insert(tx_id, tx);
198 }
199 }
200 } else {
201 break;
202 }
203 }
204 }
205
206 #[expect(clippy::type_complexity)]
208 pub fn next_tx_and_priority(
209 &mut self,
210 ) -> Option<(Arc<ValidPoolTransaction<T::Transaction>>, Priority<T::PriorityValue>)> {
211 loop {
212 self.add_new_transactions();
213 let best = self.pop_best()?;
215 let sender_id = best.transaction.sender_id();
216
217 if self.invalid.contains(&sender_id) {
219 debug!(
220 target: "txpool",
221 "[{:?}] skipping invalid transaction",
222 best.transaction.hash()
223 );
224 continue
225 }
226
227 if let Some(unlocked) = self.all.get(&best.unlocks()) {
229 self.independent.insert(unlocked.clone());
230 }
231
232 if self.skip_blobs && best.transaction.is_eip4844() {
233 self.mark_invalid(
236 &best.transaction,
237 InvalidPoolTransactionError::Eip4844(
238 Eip4844PoolTransactionError::NoEip4844Blobs,
239 ),
240 )
241 } else {
242 if self.new_transaction_receiver.is_some() {
243 self.last_priority = Some(best.priority.clone())
244 }
245 return Some((best.transaction, best.priority))
246 }
247 }
248 }
249}
250
251enum IncomingTransaction<T: TransactionOrdering> {
256 Process(PendingTransaction<T>),
263
264 Stash(PendingTransaction<T>),
276}
277
278impl<T: TransactionOrdering> crate::traits::BestTransactions for BestTransactions<T> {
279 fn mark_invalid(&mut self, tx: &Self::Item, kind: InvalidPoolTransactionError) {
280 Self::mark_invalid(self, tx, kind)
281 }
282
283 fn no_updates(&mut self) {
284 self.new_transaction_receiver.take();
285 self.last_priority.take();
286 }
287
288 fn allow_updates_out_of_order(&mut self) {
289 self.allow_updates_out_of_order = true;
290 }
291
292 fn skip_blobs(&mut self) {
293 self.set_skip_blobs(true);
294 }
295
296 fn set_skip_blobs(&mut self, skip_blobs: bool) {
297 self.skip_blobs = skip_blobs;
298 }
299}
300
301impl<T: TransactionOrdering> Iterator for BestTransactions<T> {
302 type Item = Arc<ValidPoolTransaction<T::Transaction>>;
303
304 fn next(&mut self) -> Option<Self::Item> {
305 self.next_tx_and_priority().map(|(tx, _)| tx)
306 }
307
308 fn size_hint(&self) -> (usize, Option<usize>) {
309 (0, self.new_transaction_receiver.is_none().then_some(self.all.len()))
310 }
311}
312
313pub struct BestTransactionFilter<I, P> {
319 pub(crate) best: I,
320 pub(crate) predicate: P,
321}
322
323impl<I, P> BestTransactionFilter<I, P> {
324 pub const fn new(best: I, predicate: P) -> Self {
326 Self { best, predicate }
327 }
328}
329
330impl<I, P> Iterator for BestTransactionFilter<I, P>
331where
332 I: crate::traits::BestTransactions,
333 P: FnMut(&<I as Iterator>::Item) -> bool,
334{
335 type Item = <I as Iterator>::Item;
336
337 fn next(&mut self) -> Option<Self::Item> {
338 loop {
339 let best = self.best.next()?;
340 if (self.predicate)(&best) {
341 return Some(best)
342 }
343 self.best.mark_invalid(
344 &best,
345 InvalidPoolTransactionError::Consensus(InvalidTransactionError::TxTypeNotSupported),
346 );
347 }
348 }
349
350 fn size_hint(&self) -> (usize, Option<usize>) {
351 let (_, upper) = self.best.size_hint();
352 (0, upper)
353 }
354}
355
356impl<I, P> crate::traits::BestTransactions for BestTransactionFilter<I, P>
357where
358 I: crate::traits::BestTransactions,
359 P: FnMut(&<I as Iterator>::Item) -> bool + Send,
360{
361 fn mark_invalid(&mut self, tx: &Self::Item, kind: InvalidPoolTransactionError) {
362 crate::traits::BestTransactions::mark_invalid(&mut self.best, tx, kind)
363 }
364
365 fn no_updates(&mut self) {
366 self.best.no_updates()
367 }
368
369 fn allow_updates_out_of_order(&mut self) {
370 self.best.allow_updates_out_of_order()
371 }
372
373 fn skip_blobs(&mut self) {
374 self.set_skip_blobs(true)
375 }
376
377 fn set_skip_blobs(&mut self, skip_blobs: bool) {
378 self.best.set_skip_blobs(skip_blobs)
379 }
380}
381
382impl<I: fmt::Debug, P> fmt::Debug for BestTransactionFilter<I, P> {
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384 f.debug_struct("BestTransactionFilter").field("best", &self.best).finish()
385 }
386}
387
388#[derive(Debug)]
391pub struct BestTransactionsWithPrioritizedSenders<I: Iterator> {
392 inner: I,
394 prioritized_senders: AddressSet,
396 max_prioritized_gas: u64,
398 buffer: VecDeque<I::Item>,
401 prioritized_gas: u64,
404}
405
406impl<I: Iterator> BestTransactionsWithPrioritizedSenders<I> {
407 pub fn new(prioritized_senders: AddressSet, max_prioritized_gas: u64, inner: I) -> Self {
409 Self {
410 inner,
411 prioritized_senders,
412 max_prioritized_gas,
413 buffer: Default::default(),
414 prioritized_gas: Default::default(),
415 }
416 }
417}
418
419impl<I, T> Iterator for BestTransactionsWithPrioritizedSenders<I>
420where
421 I: crate::traits::BestTransactions<Item = Arc<ValidPoolTransaction<T>>>,
422 T: PoolTransaction,
423{
424 type Item = <I as Iterator>::Item;
425
426 fn next(&mut self) -> Option<Self::Item> {
427 if self.prioritized_gas < self.max_prioritized_gas {
429 for item in &mut self.inner {
430 if self.prioritized_senders.contains(&item.transaction.sender()) &&
431 self.prioritized_gas + item.transaction.gas_limit() <=
432 self.max_prioritized_gas
433 {
434 self.prioritized_gas += item.transaction.gas_limit();
435 return Some(item)
436 }
437 self.buffer.push_back(item);
438 }
439 }
440
441 if let Some(item) = self.buffer.pop_front() {
442 Some(item)
443 } else {
444 self.inner.next()
445 }
446 }
447
448 fn size_hint(&self) -> (usize, Option<usize>) {
449 let buffered = self.buffer.len();
450 let (inner_lower, inner_upper) = self.inner.size_hint();
451
452 (
453 buffered.saturating_add(inner_lower),
454 inner_upper.and_then(|upper| upper.checked_add(buffered)),
455 )
456 }
457}
458
459impl<I, T> crate::traits::BestTransactions for BestTransactionsWithPrioritizedSenders<I>
460where
461 I: crate::traits::BestTransactions<Item = Arc<ValidPoolTransaction<T>>>,
462 T: PoolTransaction,
463{
464 fn mark_invalid(&mut self, tx: &Self::Item, kind: InvalidPoolTransactionError) {
465 self.inner.mark_invalid(tx, kind)
466 }
467
468 fn no_updates(&mut self) {
469 self.inner.no_updates()
470 }
471
472 fn allow_updates_out_of_order(&mut self) {
473 self.inner.allow_updates_out_of_order()
474 }
475
476 fn set_skip_blobs(&mut self, skip_blobs: bool) {
477 if skip_blobs {
478 self.buffer.retain(|tx| !tx.transaction.is_eip4844())
479 }
480 self.inner.set_skip_blobs(skip_blobs)
481 }
482}
483
484#[cfg(test)]
485mod tests {
486 use super::*;
487 use crate::{
488 pool::pending::PendingPool,
489 test_utils::{MockOrdering, MockTransaction, MockTransactionFactory},
490 BestTransactions, Priority,
491 };
492
493 #[test]
494 fn test_best_iter() {
495 let mut pool = PendingPool::new(MockOrdering::default());
496 let mut f = MockTransactionFactory::default();
497
498 let num_tx = 10;
499 let tx = MockTransaction::eip1559();
501 for nonce in 0..num_tx {
502 let tx = tx.clone().rng_hash().with_nonce(nonce);
503 let valid_tx = f.validated(tx);
504 pool.add_transaction(Arc::new(valid_tx), 0);
505 }
506
507 let mut best = pool.best();
508 assert_eq!(best.all.len(), num_tx as usize);
509 assert_eq!(best.independent.len(), 1);
510
511 for nonce in 0..num_tx {
513 assert_eq!(best.independent.len(), 1);
514 let tx = best.next().unwrap();
515 assert_eq!(tx.nonce(), nonce);
516 }
517 }
518
519 #[test]
520 fn test_best_transactions_size_hint() {
521 let mut pool = PendingPool::new(MockOrdering::default());
522 let mut f = MockTransactionFactory::default();
523
524 for nonce in 0..3 {
525 let tx = MockTransaction::eip1559().rng_hash().with_nonce(nonce);
526 pool.add_transaction(Arc::new(f.validated(tx)), 0);
527 }
528
529 let mut best = pool.best();
530 assert_eq!(best.size_hint(), (0, None));
531
532 best.no_updates();
533 assert_eq!(best.size_hint(), (0, Some(3)));
534
535 assert_eq!(best.next().unwrap().nonce(), 0);
536 assert_eq!(best.size_hint(), (0, Some(2)));
537 }
538
539 #[test]
540 fn test_best_transactions_with_fees_size_hint() {
541 let mut pool = PendingPool::new(MockOrdering::default());
542 let mut f = MockTransactionFactory::default();
543
544 for nonce in 0..3 {
545 let tx = MockTransaction::eip1559().rng_hash().with_nonce(nonce).with_max_fee(100);
546 pool.add_transaction(Arc::new(f.validated(tx)), 0);
547 }
548
549 let mut best = pool.best_with_basefee_and_blobfee(10, 0);
550 best.no_updates();
551
552 assert_eq!(best.size_hint(), (0, Some(3)));
553 assert_eq!(best.next().unwrap().nonce(), 0);
554 assert_eq!(best.size_hint(), (0, Some(2)));
555 }
556
557 #[test]
558 fn test_best_transaction_filter_size_hint() {
559 let mut pool = PendingPool::new(MockOrdering::default());
560 let mut f = MockTransactionFactory::default();
561
562 for nonce in 0..3 {
563 let tx = MockTransaction::eip1559().rng_hash().with_nonce(nonce);
564 pool.add_transaction(Arc::new(f.validated(tx)), 0);
565 }
566
567 let best = pool.best().without_updates();
568 let mut filter =
569 BestTransactionFilter::new(best, |_: &Arc<ValidPoolTransaction<MockTransaction>>| {
570 false
571 });
572
573 assert_eq!(filter.size_hint(), (0, Some(3)));
574 assert!(filter.next().is_none());
575 assert_eq!(filter.size_hint(), (0, Some(0)));
576 }
577
578 #[test]
579 fn test_best_transactions_with_prioritized_senders_size_hint() {
580 let mut pool = PendingPool::new(MockOrdering::default());
581 let mut f = MockTransactionFactory::default();
582
583 for gas_price in 0..5 {
584 let tx = MockTransaction::eip1559().with_gas_price((gas_price + 1) * 10);
585 pool.add_transaction(Arc::new(f.validated(tx)), 0);
586 }
587
588 let prioritized_tx = MockTransaction::eip1559().with_gas_price(5).with_gas_limit(200);
589 let prioritized_sender = prioritized_tx.sender();
590 pool.add_transaction(Arc::new(f.validated(prioritized_tx)), 0);
591
592 let mut best = BestTransactionsWithPrioritizedSenders::new(
593 AddressSet::from_iter([prioritized_sender]),
594 200,
595 pool.best().without_updates(),
596 );
597
598 assert_eq!(best.size_hint(), (0, Some(6)));
599 assert_eq!(best.next().unwrap().sender(), prioritized_sender);
600 assert_eq!(best.size_hint(), (5, Some(5)));
601 }
602
603 #[test]
604 fn test_best_iter_invalid() {
605 let mut pool = PendingPool::new(MockOrdering::default());
606 let mut f = MockTransactionFactory::default();
607
608 let num_tx = 10;
609 let tx = MockTransaction::eip1559();
611 for nonce in 0..num_tx {
612 let tx = tx.clone().rng_hash().with_nonce(nonce);
613 let valid_tx = f.validated(tx);
614 pool.add_transaction(Arc::new(valid_tx), 0);
615 }
616
617 let mut best = pool.best();
618
619 let invalid = best.independent.iter().next().unwrap();
621 best.mark_invalid(
622 &invalid.transaction.clone(),
623 InvalidPoolTransactionError::Consensus(InvalidTransactionError::TxTypeNotSupported),
624 );
625
626 assert!(best.next().is_none());
628 }
629
630 #[test]
631 fn test_best_transactions_iter_invalid() {
632 let mut pool = PendingPool::new(MockOrdering::default());
633 let mut f = MockTransactionFactory::default();
634
635 let num_tx = 10;
636 let tx = MockTransaction::eip1559();
638 for nonce in 0..num_tx {
639 let tx = tx.clone().rng_hash().with_nonce(nonce);
640 let valid_tx = f.validated(tx);
641 pool.add_transaction(Arc::new(valid_tx), 0);
642 }
643
644 let mut best: Box<
645 dyn crate::traits::BestTransactions<Item = Arc<ValidPoolTransaction<MockTransaction>>>,
646 > = Box::new(pool.best());
647
648 let tx = Iterator::next(&mut best).unwrap();
649 crate::traits::BestTransactions::mark_invalid(
650 &mut *best,
651 &tx,
652 InvalidPoolTransactionError::Consensus(InvalidTransactionError::TxTypeNotSupported),
653 );
654 assert!(Iterator::next(&mut best).is_none());
655 }
656
657 #[test]
658 fn test_best_with_fees_iter_base_fee_satisfied() {
659 let mut pool = PendingPool::new(MockOrdering::default());
660 let mut f = MockTransactionFactory::default();
661
662 let num_tx = 5;
663 let base_fee: u64 = 10;
664 let base_fee_per_blob_gas: u64 = 15;
665
666 for nonce in 0..num_tx {
669 let tx = MockTransaction::eip1559()
670 .rng_hash()
671 .with_nonce(nonce)
672 .with_max_fee(base_fee as u128 + 5);
673 let valid_tx = f.validated(tx);
674 pool.add_transaction(Arc::new(valid_tx), 0);
675 }
676
677 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
678
679 for nonce in 0..num_tx {
680 let tx = best.next().expect("Transaction should be returned");
681 assert_eq!(tx.nonce(), nonce);
682 assert!(tx.transaction.max_fee_per_gas() >= base_fee as u128);
683 }
684 }
685
686 #[test]
687 fn test_best_with_fees_iter_base_fee_violated() {
688 let mut pool = PendingPool::new(MockOrdering::default());
689 let mut f = MockTransactionFactory::default();
690
691 let num_tx = 5;
692 let base_fee: u64 = 20;
693 let base_fee_per_blob_gas: u64 = 15;
694
695 for nonce in 0..num_tx {
697 let tx = MockTransaction::eip1559()
698 .rng_hash()
699 .with_nonce(nonce)
700 .with_max_fee(base_fee as u128 - 5);
701 let valid_tx = f.validated(tx);
702 pool.add_transaction(Arc::new(valid_tx), 0);
703 }
704
705 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
706
707 assert!(best.next().is_none());
709 }
710
711 #[test]
712 fn test_best_with_fees_iter_blob_fee_satisfied() {
713 let mut pool = PendingPool::new(MockOrdering::default());
714 let mut f = MockTransactionFactory::default();
715
716 let num_tx = 5;
717 let base_fee: u64 = 10;
718 let base_fee_per_blob_gas: u64 = 20;
719
720 for nonce in 0..num_tx {
723 let tx = MockTransaction::eip4844()
724 .rng_hash()
725 .with_nonce(nonce)
726 .with_max_fee(base_fee as u128 + 5)
727 .with_blob_fee(base_fee_per_blob_gas as u128 + 5);
728 let valid_tx = f.validated(tx);
729 pool.add_transaction(Arc::new(valid_tx), 0);
730 }
731
732 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
733
734 for nonce in 0..num_tx {
737 let tx = best.next().expect("Transaction should be returned");
738 assert_eq!(tx.nonce(), nonce);
739 assert!(tx.transaction.max_fee_per_gas() >= base_fee as u128);
740 assert!(
741 tx.transaction.max_fee_per_blob_gas().unwrap() >= base_fee_per_blob_gas as u128
742 );
743 }
744
745 assert!(best.next().is_none());
747 }
748
749 #[test]
750 fn test_best_with_fees_iter_blob_fee_violated() {
751 let mut pool = PendingPool::new(MockOrdering::default());
752 let mut f = MockTransactionFactory::default();
753
754 let num_tx = 5;
755 let base_fee: u64 = 10;
756 let base_fee_per_blob_gas: u64 = 20;
757
758 for nonce in 0..num_tx {
760 let tx = MockTransaction::eip4844()
761 .rng_hash()
762 .with_nonce(nonce)
763 .with_max_fee(base_fee as u128 + 5)
764 .with_blob_fee(base_fee_per_blob_gas as u128 - 5);
765 let valid_tx = f.validated(tx);
766 pool.add_transaction(Arc::new(valid_tx), 0);
767 }
768
769 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
770
771 assert!(best.next().is_none());
773 }
774
775 #[test]
776 fn test_best_with_fees_iter_mixed_fees() {
777 let mut pool = PendingPool::new(MockOrdering::default());
778 let mut f = MockTransactionFactory::default();
779
780 let base_fee: u64 = 10;
781 let base_fee_per_blob_gas: u64 = 20;
782
783 let tx1 =
785 MockTransaction::eip1559().rng_hash().with_nonce(0).with_max_fee(base_fee as u128 + 5);
786 let tx2 = MockTransaction::eip4844()
787 .rng_hash()
788 .with_nonce(1)
789 .with_max_fee(base_fee as u128 + 5)
790 .with_blob_fee(base_fee_per_blob_gas as u128 + 5);
791 let tx3 = MockTransaction::eip4844()
792 .rng_hash()
793 .with_nonce(2)
794 .with_max_fee(base_fee as u128 + 5)
795 .with_blob_fee(base_fee_per_blob_gas as u128 - 5);
796 let tx4 =
797 MockTransaction::eip1559().rng_hash().with_nonce(3).with_max_fee(base_fee as u128 - 5);
798
799 pool.add_transaction(Arc::new(f.validated(tx1.clone())), 0);
800 pool.add_transaction(Arc::new(f.validated(tx2.clone())), 0);
801 pool.add_transaction(Arc::new(f.validated(tx3)), 0);
802 pool.add_transaction(Arc::new(f.validated(tx4)), 0);
803
804 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
805
806 let expected_order = vec![tx1, tx2];
807 for expected_tx in expected_order {
808 let tx = best.next().expect("Transaction should be returned");
809 assert_eq!(tx.transaction, expected_tx);
810 }
811
812 assert!(best.next().is_none());
814 }
815
816 #[test]
817 fn test_best_add_transaction_with_next_nonce() {
818 let mut pool = PendingPool::new(MockOrdering::default());
819 let mut f = MockTransactionFactory::default();
820
821 let num_tx = 5;
823 let tx = MockTransaction::eip1559();
824 for nonce in 0..num_tx {
825 let tx = tx.clone().rng_hash().with_nonce(nonce);
826 let valid_tx = f.validated(tx);
827 pool.add_transaction(Arc::new(valid_tx), 0);
828 }
829
830 let mut best = pool.best();
832
833 let (tx_sender, tx_receiver) =
835 tokio::sync::broadcast::channel::<PendingTransaction<MockOrdering>>(1000);
836 best.new_transaction_receiver = Some(tx_receiver);
837
838 let new_tx = MockTransaction::eip1559().rng_hash().with_nonce(5);
840 let valid_new_tx = f.validated(new_tx);
841
842 let pending_tx = PendingTransaction {
844 submission_id: 10,
845 transaction: Arc::new(valid_new_tx.clone()),
846 priority: Priority::Value(1000),
847 };
848 tx_sender.send(pending_tx.clone()).unwrap();
849
850 best.add_new_transactions();
852
853 assert_eq!(best.all.len(), 6);
855 assert!(best.all.contains_key(valid_new_tx.id()));
856
857 assert_eq!(best.independent.len(), 2);
859 assert!(best.independent.contains(&pending_tx));
860 }
861
862 #[test]
863 fn test_best_add_transaction_with_ancestor() {
864 let mut pool = PendingPool::new(MockOrdering::default());
866 let mut f = MockTransactionFactory::default();
867
868 let num_tx = 5;
870 let tx = MockTransaction::eip1559();
871 for nonce in 0..num_tx {
872 let tx = tx.clone().rng_hash().with_nonce(nonce);
873 let valid_tx = f.validated(tx);
874 pool.add_transaction(Arc::new(valid_tx), 0);
875 }
876
877 let mut best = pool.best();
879
880 let (tx_sender, tx_receiver) =
882 tokio::sync::broadcast::channel::<PendingTransaction<MockOrdering>>(1000);
883 best.new_transaction_receiver = Some(tx_receiver);
884
885 let base_tx1 = MockTransaction::eip1559().rng_hash().with_nonce(5);
887 let valid_new_tx1 = f.validated(base_tx1.clone());
888
889 let pending_tx1 = PendingTransaction {
891 submission_id: 10,
892 transaction: Arc::new(valid_new_tx1.clone()),
893 priority: Priority::Value(1000),
894 };
895 tx_sender.send(pending_tx1.clone()).unwrap();
896
897 best.add_new_transactions();
899
900 assert_eq!(best.all.len(), 6);
902 assert!(best.all.contains_key(valid_new_tx1.id()));
903
904 assert_eq!(best.independent.len(), 2);
906 assert!(best.independent.contains(&pending_tx1));
907
908 let base_tx2 = base_tx1.with_nonce(6);
910 let valid_new_tx2 = f.validated(base_tx2);
911
912 let pending_tx2 = PendingTransaction {
914 submission_id: 11, transaction: Arc::new(valid_new_tx2.clone()),
916 priority: Priority::Value(1000),
917 };
918 tx_sender.send(pending_tx2.clone()).unwrap();
919
920 best.add_new_transactions();
922
923 assert_eq!(best.all.len(), 7);
925 assert!(best.all.contains_key(valid_new_tx2.id()));
926
927 assert_eq!(best.independent.len(), 2);
929 assert!(!best.independent.contains(&pending_tx2));
930 }
931
932 #[test]
933 fn test_best_transactions_filter_trait_object() {
934 let mut pool = PendingPool::new(MockOrdering::default());
936 let mut f = MockTransactionFactory::default();
937
938 let num_tx = 5;
940 let tx = MockTransaction::eip1559();
941 for nonce in 0..num_tx {
942 let tx = tx.clone().rng_hash().with_nonce(nonce);
943 let valid_tx = f.validated(tx);
944 pool.add_transaction(Arc::new(valid_tx), 0);
945 }
946
947 let best: Box<dyn crate::traits::BestTransactions<Item = _>> = Box::new(pool.best());
949
950 let filter =
952 BestTransactionFilter::new(best, |tx: &Arc<ValidPoolTransaction<MockTransaction>>| {
953 tx.nonce().is_multiple_of(2)
954 });
955
956 for tx in filter {
958 assert_eq!(tx.nonce() % 2, 0);
959 }
960 }
961
962 #[test]
963 fn test_best_transactions_prioritized_senders() {
964 let mut pool = PendingPool::new(MockOrdering::default());
965 let mut f = MockTransactionFactory::default();
966
967 for gas_price in 0..5 {
969 let tx = MockTransaction::eip1559().with_gas_price((gas_price + 1) * 10);
970 let valid_tx = f.validated(tx);
971 pool.add_transaction(Arc::new(valid_tx), 0);
972 }
973
974 let prioritized_tx = MockTransaction::eip1559().with_gas_price(5).with_gas_limit(200);
976 let valid_prioritized_tx = f.validated(prioritized_tx.clone());
977 pool.add_transaction(Arc::new(valid_prioritized_tx), 0);
978
979 let prioritized_tx2 = MockTransaction::eip1559().with_gas_price(3);
982 let valid_prioritized_tx2 = f.validated(prioritized_tx2.clone());
983 pool.add_transaction(Arc::new(valid_prioritized_tx2), 0);
984
985 let prioritized_senders =
986 AddressSet::from_iter([prioritized_tx.sender(), prioritized_tx2.sender()]);
987 let best =
988 BestTransactionsWithPrioritizedSenders::new(prioritized_senders, 200, pool.best());
989
990 let mut iter = best.into_iter();
993 let top_of_block_tx = iter.next().unwrap();
994 assert_eq!(top_of_block_tx.max_fee_per_gas(), 5);
995 assert_eq!(top_of_block_tx.sender(), prioritized_tx.sender());
996 for gas_price in (0..5).rev() {
997 assert_eq!(iter.next().unwrap().max_fee_per_gas(), (gas_price + 1) * 10);
998 }
999
1000 let top_of_block_tx2 = iter.next().unwrap();
1003 assert_eq!(top_of_block_tx2.max_fee_per_gas(), 3);
1004 assert_eq!(top_of_block_tx2.sender(), prioritized_tx2.sender());
1005 }
1006
1007 #[test]
1008 fn test_best_with_fees_iter_no_blob_fee_required() {
1009 let mut pool = PendingPool::new(MockOrdering::default());
1011 let mut f = MockTransactionFactory::default();
1012
1013 let base_fee: u64 = 10;
1014 let base_fee_per_blob_gas: u64 = 0; for nonce in 0..5 {
1018 let tx = MockTransaction::eip1559()
1019 .rng_hash()
1020 .with_nonce(nonce)
1021 .with_max_fee(base_fee as u128 + 5);
1022 let valid_tx = f.validated(tx);
1023 pool.add_transaction(Arc::new(valid_tx), 0);
1024 }
1025
1026 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
1027
1028 for nonce in 0..5 {
1030 let tx = best.next().expect("Transaction should be returned");
1031 assert_eq!(tx.nonce(), nonce);
1032 }
1033
1034 assert!(best.next().is_none());
1036 }
1037
1038 #[test]
1039 fn test_best_with_fees_iter_mix_of_blob_and_non_blob_transactions() {
1040 let mut pool = PendingPool::new(MockOrdering::default());
1042 let mut f = MockTransactionFactory::default();
1043
1044 let base_fee: u64 = 10;
1045 let base_fee_per_blob_gas: u64 = 15;
1046
1047 let tx_non_blob =
1049 MockTransaction::eip1559().rng_hash().with_nonce(0).with_max_fee(base_fee as u128 + 5);
1050 pool.add_transaction(Arc::new(f.validated(tx_non_blob.clone())), 0);
1051
1052 let tx_blob = MockTransaction::eip4844()
1054 .rng_hash()
1055 .with_nonce(1)
1056 .with_max_fee(base_fee as u128 + 5)
1057 .with_blob_fee(base_fee_per_blob_gas as u128 + 5);
1058 pool.add_transaction(Arc::new(f.validated(tx_blob.clone())), 0);
1059
1060 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
1061
1062 let tx = best.next().expect("Transaction should be returned");
1064 assert_eq!(tx.transaction, tx_non_blob);
1065
1066 let tx = best.next().expect("Transaction should be returned");
1067 assert_eq!(tx.transaction, tx_blob);
1068
1069 assert!(best.next().is_none());
1071 }
1072
1073 #[test]
1074 fn test_best_transactions_with_skipping_blobs() {
1075 let mut pool = PendingPool::new(MockOrdering::default());
1077 let mut f = MockTransactionFactory::default();
1078
1079 let tx_blob = MockTransaction::eip4844().rng_hash().with_nonce(0).with_blob_fee(100);
1081 let valid_blob_tx = f.validated(tx_blob);
1082 pool.add_transaction(Arc::new(valid_blob_tx), 0);
1083
1084 let tx_non_blob = MockTransaction::eip1559().rng_hash().with_nonce(1).with_max_fee(200);
1086 let valid_non_blob_tx = f.validated(tx_non_blob.clone());
1087 pool.add_transaction(Arc::new(valid_non_blob_tx), 0);
1088
1089 let mut best = pool.best();
1090 best.skip_blobs();
1091
1092 let tx = best.next().expect("Transaction should be returned");
1094 assert_eq!(tx.transaction, tx_non_blob);
1095
1096 assert!(best.next().is_none());
1098 }
1099
1100 #[test]
1101 fn test_best_transactions_no_updates() {
1102 let mut pool = PendingPool::new(MockOrdering::default());
1105 let mut f = MockTransactionFactory::default();
1106
1107 let tx = MockTransaction::eip1559().rng_hash().with_nonce(0).with_max_fee(100);
1109 let valid_tx = f.validated(tx);
1110 pool.add_transaction(Arc::new(valid_tx), 0);
1111
1112 let mut best = pool.best();
1113
1114 let (_tx_sender, tx_receiver) =
1116 tokio::sync::broadcast::channel::<PendingTransaction<MockOrdering>>(1000);
1117 best.new_transaction_receiver = Some(tx_receiver);
1118
1119 assert!(best.new_transaction_receiver.is_some());
1121
1122 best.no_updates();
1124
1125 assert!(best.new_transaction_receiver.is_none());
1127 }
1128
1129 #[test]
1130 fn test_best_transactions_yields_updates_after_empty() {
1131 let mut pool = PendingPool::new(MockOrdering::default());
1132 let mut best = pool.best();
1133 best.allow_updates_out_of_order();
1134
1135 assert!(best.next().is_none());
1136
1137 let mut f = MockTransactionFactory::default();
1138 let tx = MockTransaction::eip1559().rng_hash();
1139 let valid_tx = Arc::new(f.validated(tx));
1140 let expected_hash = *valid_tx.hash();
1141 pool.add_transaction(valid_tx, 0);
1142
1143 assert_eq!(*best.next().expect("new transaction should be yielded").hash(), expected_hash);
1144 }
1145
1146 #[test]
1147 fn test_best_update_transaction_priority() {
1148 let mut pool = PendingPool::new(MockOrdering::default());
1149 let mut f = MockTransactionFactory::default();
1150
1151 let num_tx = 5;
1153 let tx = MockTransaction::eip1559();
1154 for nonce in 0..num_tx {
1155 let tx = tx.clone().rng_hash().with_nonce(nonce);
1156 let valid_tx = f.validated(tx);
1157 pool.add_transaction(Arc::new(valid_tx), 0);
1158 }
1159
1160 let mut best = pool.best();
1162
1163 let (tx_sender, tx_receiver) =
1165 tokio::sync::broadcast::channel::<PendingTransaction<MockOrdering>>(1000);
1166 best.new_transaction_receiver = Some(tx_receiver);
1167
1168 let first = best.next().unwrap();
1170
1171 let new_higher_fee_tx = MockTransaction::eip1559().with_nonce(0);
1173 let valid_new_higher_fee_tx = f.validated(new_higher_fee_tx);
1174
1175 let pending_tx = PendingTransaction {
1177 submission_id: 10,
1178 transaction: Arc::new(valid_new_higher_fee_tx.clone()),
1179 priority: Priority::Value(u128::MAX),
1180 };
1181 tx_sender.send(pending_tx).unwrap();
1182
1183 for tx in best {
1185 assert_eq!(tx.sender_id(), first.sender_id());
1186 assert_ne!(tx.sender_id(), valid_new_higher_fee_tx.sender_id());
1187 }
1188 }
1189
1190 #[test]
1195 fn test_blob_transaction_ordering_multiple_clients_shape() {
1196 let mut pool = PendingPool::new(MockOrdering::default());
1197 let mut f = MockTransactionFactory::default();
1198
1199 let base_fee: u64 = 10;
1200 let base_fee_per_blob_gas: u64 = 1;
1201 let max_blob_count: u64 = 6;
1202
1203 let sender_a = MockTransaction::eip4844()
1204 .with_blob_hashes(5)
1205 .with_max_fee(base_fee as u128 + 20)
1206 .with_priority_fee(base_fee as u128 + 20)
1207 .with_blob_fee(120);
1208 for nonce in 0..5u64 {
1209 let tx = sender_a.clone().rng_hash().with_nonce(nonce);
1210 pool.add_transaction(Arc::new(f.validated(tx)), 0);
1211 }
1212
1213 let sender_b = MockTransaction::eip4844()
1214 .with_blob_hashes(1)
1215 .with_max_fee(base_fee as u128 + 20)
1216 .with_priority_fee(base_fee as u128 + 20)
1217 .with_blob_fee(100);
1218 for nonce in 0..5u64 {
1219 let tx = sender_b.clone().rng_hash().with_nonce(nonce);
1220 pool.add_transaction(Arc::new(f.validated(tx)), 0);
1221 }
1222
1223 let mut best = pool.best_with_basefee_and_blobfee(base_fee, base_fee_per_blob_gas);
1224 let mut block_blob_count = 0u64;
1225 let mut included_txs = 0u64;
1226
1227 while let Some(tx) = best.next() {
1228 if let Some(blob_hashes) = tx.transaction.blob_versioned_hashes() {
1229 let tx_blob_count = blob_hashes.len() as u64;
1230
1231 if block_blob_count + tx_blob_count > max_blob_count {
1232 crate::traits::BestTransactions::mark_invalid(
1233 &mut best,
1234 &tx,
1235 InvalidPoolTransactionError::Eip4844(
1236 Eip4844PoolTransactionError::TooManyEip4844Blobs {
1237 have: block_blob_count + tx_blob_count,
1238 permitted: max_blob_count,
1239 },
1240 ),
1241 );
1242 continue;
1243 }
1244
1245 block_blob_count += tx_blob_count;
1246 included_txs += 1;
1247
1248 if block_blob_count == max_blob_count {
1249 best.skip_blobs();
1250 break;
1251 }
1252 }
1253 }
1254
1255 assert_eq!(
1256 block_blob_count, max_blob_count,
1257 "expected a full blob block (5+1 blobs across senders)"
1258 );
1259 assert_eq!(included_txs, 2, "expected one 5-blob tx and one 1-blob tx in the block");
1260 }
1261}