reth_transaction_pool/pool/
parked.rs1use crate::{
2 identifier::{SenderId, TransactionId},
3 pool::size::SizeTracker,
4 PoolTransaction, SubPoolLimit, ValidPoolTransaction, TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER,
5};
6use rustc_hash::FxHashMap;
7use smallvec::SmallVec;
8use std::{
9 cmp::Ordering,
10 collections::{hash_map::Entry, BTreeMap, BTreeSet},
11 ops::{Bound::Unbounded, Deref},
12 sync::Arc,
13};
14
15#[derive(Debug, Clone)]
22pub struct ParkedPool<T: ParkedOrd> {
23 submission_id: u64,
27 by_id: BTreeMap<TransactionId, ParkedPoolTransaction<T>>,
29 last_sender_submission: BTreeSet<SubmissionSenderId>,
34 sender_transaction_count: FxHashMap<SenderId, SenderTransactionCount>,
37 size_of: SizeTracker,
41}
42
43impl<T: ParkedOrd> ParkedPool<T> {
46 pub fn add_transaction(&mut self, tx: Arc<ValidPoolTransaction<T::Transaction>>) {
48 let id = *tx.id();
49 debug_assert!(
50 !self.contains(&id),
51 "transaction already included {:?}",
52 self.get(&id).unwrap().transaction.transaction
53 );
54 let submission_id = self.next_id();
55
56 self.size_of += tx.size();
58
59 self.add_sender_count(tx.sender_id(), submission_id);
61 let transaction = ParkedPoolTransaction { submission_id, transaction: tx.into() };
62
63 self.by_id.insert(id, transaction);
64 }
65
66 fn add_sender_count(&mut self, sender: SenderId, submission_id: u64) {
69 match self.sender_transaction_count.entry(sender) {
70 Entry::Occupied(mut entry) => {
71 let value = entry.get_mut();
72 self.last_sender_submission
74 .remove(&SubmissionSenderId::new(sender, value.last_submission_id));
75
76 value.count += 1;
77 value.last_submission_id = submission_id;
78 }
79 Entry::Vacant(entry) => {
80 entry
81 .insert(SenderTransactionCount { count: 1, last_submission_id: submission_id });
82 }
83 }
84 self.last_sender_submission.insert(SubmissionSenderId::new(sender, submission_id));
86 }
87
88 fn remove_sender_count(&mut self, sender_id: SenderId) {
95 let removed_sender = match self.sender_transaction_count.entry(sender_id) {
96 Entry::Occupied(mut entry) => {
97 let value = entry.get_mut();
98 value.count -= 1;
99 if value.count == 0 {
100 entry.remove()
101 } else {
102 return
103 }
104 }
105 Entry::Vacant(_) => {
106 unreachable!("sender count not found {:?}", sender_id);
108 }
109 };
110
111 assert!(
113 self.last_sender_submission
114 .remove(&SubmissionSenderId::new(sender_id, removed_sender.last_submission_id)),
115 "last sender transaction not found {sender_id:?}"
116 );
117 }
118
119 pub(crate) fn all(
121 &self,
122 ) -> impl ExactSizeIterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
123 self.by_id.values().map(|tx| tx.transaction.clone().into())
124 }
125
126 pub(crate) fn remove_transaction(
128 &mut self,
129 id: &TransactionId,
130 ) -> Option<Arc<ValidPoolTransaction<T::Transaction>>> {
131 let tx = self.by_id.remove(id)?;
133 self.remove_sender_count(tx.transaction.sender_id());
134
135 self.size_of -= tx.transaction.size();
137
138 Some(tx.transaction.into())
139 }
140
141 pub(crate) fn get_txs_by_sender(
144 &self,
145 sender: SenderId,
146 ) -> SmallVec<[TransactionId; TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER]> {
147 self.by_id
148 .range((sender.start_bound(), Unbounded))
149 .take_while(move |(other, _)| sender == other.sender)
150 .map(|(tx_id, _)| *tx_id)
151 .collect()
152 }
153
154 #[cfg(test)]
155 pub(crate) fn get_senders_by_submission_id(
156 &self,
157 ) -> impl Iterator<Item = SubmissionSenderId> + '_ {
158 self.last_sender_submission.iter().copied()
159 }
160
161 pub fn truncate_pool(
175 &mut self,
176 limit: SubPoolLimit,
177 ) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
178 if !self.exceeds(&limit) {
179 return Vec::new()
181 }
182
183 let mut removed = Vec::new();
184
185 while !self.last_sender_submission.is_empty() && limit.is_exceeded(self.len(), self.size())
186 {
187 let sender_id = self.last_sender_submission.last().unwrap().sender_id;
189 let list = self.get_txs_by_sender(sender_id);
190
191 for txid in list.into_iter().rev() {
193 if let Some(tx) = self.remove_transaction(&txid) {
194 removed.push(tx);
195 }
196
197 if !self.exceeds(&limit) {
198 break
199 }
200 }
201 }
202
203 removed
204 }
205
206 const fn next_id(&mut self) -> u64 {
207 let id = self.submission_id;
208 self.submission_id = self.submission_id.wrapping_add(1);
209 id
210 }
211
212 pub(crate) fn size(&self) -> usize {
214 self.size_of.into()
215 }
216
217 pub(crate) fn len(&self) -> usize {
219 self.by_id.len()
220 }
221
222 #[inline]
224 pub(crate) fn exceeds(&self, limit: &SubPoolLimit) -> bool {
225 limit.is_exceeded(self.len(), self.size())
226 }
227
228 #[cfg(test)]
230 pub(crate) fn is_empty(&self) -> bool {
231 self.by_id.is_empty()
232 }
233
234 pub(crate) fn contains(&self, id: &TransactionId) -> bool {
236 self.by_id.contains_key(id)
237 }
238
239 fn get(&self, id: &TransactionId) -> Option<&ParkedPoolTransaction<T>> {
241 self.by_id.get(id)
242 }
243
244 #[cfg(any(test, feature = "test-utils"))]
246 pub(crate) fn assert_invariants(&self) {
247 assert_eq!(
248 self.last_sender_submission.len(),
249 self.sender_transaction_count.len(),
250 "last_sender_submission.len() != sender_transaction_count.len()"
251 );
252 }
253}
254
255impl<T: PoolTransaction> ParkedPool<BasefeeOrd<T>> {
256 pub(crate) fn satisfy_base_fee_transactions(
260 &self,
261 basefee: u64,
262 ) -> Vec<Arc<ValidPoolTransaction<T>>> {
263 let ids = self.satisfy_base_fee_ids(basefee as u128);
264 let mut txs = Vec::with_capacity(ids.len());
265 for id in ids {
266 txs.push(self.get(&id).expect("transaction exists").transaction.clone().into());
267 }
268 txs
269 }
270
271 fn satisfy_base_fee_ids(&self, basefee: u128) -> Vec<TransactionId> {
273 let mut transactions = Vec::new();
274 {
275 let mut iter = self.by_id.iter().peekable();
276
277 while let Some((id, tx)) = iter.next() {
278 if tx.transaction.transaction.max_fee_per_gas() < basefee {
279 'this: while let Some((peek, _)) = iter.peek() {
281 if peek.sender != id.sender {
282 break 'this
283 }
284 iter.next();
285 }
286 } else {
287 transactions.push(*id);
288 }
289 }
290 }
291 transactions
292 }
293
294 pub(crate) fn enforce_basefee_with<F>(&mut self, basefee: u64, mut tx_handler: F)
306 where
307 F: FnMut(Arc<ValidPoolTransaction<T>>),
308 {
309 let to_remove = self.satisfy_base_fee_ids(basefee as u128);
310
311 for id in to_remove {
312 if let Some(tx) = self.remove_transaction(&id) {
313 tx_handler(tx);
314 }
315 }
316 }
317
318 #[cfg(test)]
326 pub(crate) fn enforce_basefee(&mut self, basefee: u64) -> Vec<Arc<ValidPoolTransaction<T>>> {
327 let mut removed = Vec::new();
328 self.enforce_basefee_with(basefee, |tx| {
329 removed.push(tx);
330 });
331 removed
332 }
333}
334
335impl<T: ParkedOrd> Default for ParkedPool<T> {
336 fn default() -> Self {
337 Self {
338 submission_id: 0,
339 by_id: Default::default(),
340 last_sender_submission: Default::default(),
341 sender_transaction_count: Default::default(),
342 size_of: Default::default(),
343 }
344 }
345}
346
347#[derive(Debug, Clone, Default, PartialEq, Eq)]
349struct SenderTransactionCount {
350 count: u64,
351 last_submission_id: u64,
352}
353
354#[derive(Debug)]
356struct ParkedPoolTransaction<T: ParkedOrd> {
357 submission_id: u64,
359 transaction: T,
361}
362
363impl<T: ParkedOrd> Clone for ParkedPoolTransaction<T> {
364 fn clone(&self) -> Self {
365 Self { submission_id: self.submission_id, transaction: self.transaction.clone() }
366 }
367}
368
369impl<T: ParkedOrd> Eq for ParkedPoolTransaction<T> {}
370
371impl<T: ParkedOrd> PartialEq<Self> for ParkedPoolTransaction<T> {
372 fn eq(&self, other: &Self) -> bool {
373 self.cmp(other) == Ordering::Equal
374 }
375}
376
377impl<T: ParkedOrd> PartialOrd<Self> for ParkedPoolTransaction<T> {
378 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
379 Some(self.cmp(other))
380 }
381}
382
383impl<T: ParkedOrd> Ord for ParkedPoolTransaction<T> {
384 fn cmp(&self, other: &Self) -> Ordering {
385 self.transaction
389 .cmp(&other.transaction)
390 .then_with(|| other.submission_id.cmp(&self.submission_id))
391 }
392}
393
394#[derive(Debug, PartialEq, Eq, Copy, Clone)]
397pub(crate) struct SubmissionSenderId {
398 pub(crate) sender_id: SenderId,
400 pub(crate) submission_id: u64,
402}
403
404impl SubmissionSenderId {
405 const fn new(sender_id: SenderId, submission_id: u64) -> Self {
407 Self { sender_id, submission_id }
408 }
409}
410
411impl Ord for SubmissionSenderId {
412 fn cmp(&self, other: &Self) -> Ordering {
413 other.submission_id.cmp(&self.submission_id)
415 }
416}
417
418impl PartialOrd for SubmissionSenderId {
419 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
420 Some(self.cmp(other))
421 }
422}
423
424pub trait ParkedOrd:
428 Ord
429 + Clone
430 + From<Arc<ValidPoolTransaction<Self::Transaction>>>
431 + Into<Arc<ValidPoolTransaction<Self::Transaction>>>
432 + Deref<Target = Arc<ValidPoolTransaction<Self::Transaction>>>
433{
434 type Transaction: PoolTransaction;
436}
437
438macro_rules! impl_ord_wrapper {
440 ($name:ident) => {
441 impl<T: PoolTransaction> Clone for $name<T> {
442 fn clone(&self) -> Self {
443 Self(self.0.clone())
444 }
445 }
446
447 impl<T: PoolTransaction> Eq for $name<T> {}
448
449 impl<T: PoolTransaction> PartialEq<Self> for $name<T> {
450 fn eq(&self, other: &Self) -> bool {
451 self.cmp(other) == Ordering::Equal
452 }
453 }
454
455 impl<T: PoolTransaction> PartialOrd<Self> for $name<T> {
456 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
457 Some(self.cmp(other))
458 }
459 }
460 impl<T: PoolTransaction> Deref for $name<T> {
461 type Target = Arc<ValidPoolTransaction<T>>;
462
463 fn deref(&self) -> &Self::Target {
464 &self.0
465 }
466 }
467
468 impl<T: PoolTransaction> ParkedOrd for $name<T> {
469 type Transaction = T;
470 }
471
472 impl<T: PoolTransaction> From<Arc<ValidPoolTransaction<T>>> for $name<T> {
473 fn from(value: Arc<ValidPoolTransaction<T>>) -> Self {
474 Self(value)
475 }
476 }
477
478 impl<T: PoolTransaction> From<$name<T>> for Arc<ValidPoolTransaction<T>> {
479 fn from(value: $name<T>) -> Arc<ValidPoolTransaction<T>> {
480 value.0
481 }
482 }
483 };
484}
485
486#[derive(Debug)]
492pub struct BasefeeOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
493
494impl_ord_wrapper!(BasefeeOrd);
495
496impl<T: PoolTransaction> Ord for BasefeeOrd<T> {
497 fn cmp(&self, other: &Self) -> Ordering {
498 self.0.transaction.max_fee_per_gas().cmp(&other.0.transaction.max_fee_per_gas())
499 }
500}
501
502#[derive(Debug)]
512pub struct QueuedOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
513
514impl_ord_wrapper!(QueuedOrd);
515
516impl<T: PoolTransaction> Ord for QueuedOrd<T> {
517 fn cmp(&self, other: &Self) -> Ordering {
518 self.max_fee_per_gas().cmp(&other.max_fee_per_gas()).then_with(||
520 other.timestamp.cmp(&self.timestamp))
522 }
523}
524
525#[cfg(test)]
526mod tests {
527 use super::*;
528 use crate::test_utils::{MockTransaction, MockTransactionFactory, MockTransactionSet};
529 use alloy_consensus::{Transaction, TxType};
530 use alloy_primitives::address;
531 use std::collections::HashSet;
532
533 #[test]
534 fn test_enforce_parked_basefee() {
535 let mut f = MockTransactionFactory::default();
536 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
537 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
538 pool.add_transaction(tx.clone());
539
540 assert!(pool.contains(tx.id()));
541 assert_eq!(pool.len(), 1);
542
543 let removed = pool.enforce_basefee(u64::MAX);
544 assert!(removed.is_empty());
545
546 let removed = pool.enforce_basefee((tx.max_fee_per_gas() - 1) as u64);
547 assert_eq!(removed.len(), 1);
548 assert!(pool.is_empty());
549 }
550
551 #[test]
552 fn test_enforce_parked_basefee_descendant() {
553 let mut f = MockTransactionFactory::default();
554 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
555 let t = MockTransaction::eip1559().inc_price_by(10);
556 let root_tx = f.validated_arc(t.clone());
557 pool.add_transaction(root_tx.clone());
558
559 let descendant_tx = f.validated_arc(t.inc_nonce().decr_price());
560 pool.add_transaction(descendant_tx.clone());
561
562 assert!(pool.contains(root_tx.id()));
563 assert!(pool.contains(descendant_tx.id()));
564 assert_eq!(pool.len(), 2);
565
566 let removed = pool.enforce_basefee(u64::MAX);
567 assert!(removed.is_empty());
568 assert_eq!(pool.len(), 2);
569 {
572 let mut pool2 = pool.clone();
574 let removed = pool2.enforce_basefee(root_tx.max_fee_per_gas() as u64);
575 assert_eq!(removed.len(), 1);
576 assert_eq!(pool2.len(), 1);
577 assert!(!pool2.contains(root_tx.id()));
579 assert!(pool2.contains(descendant_tx.id()));
580 }
581
582 let removed = pool.enforce_basefee(descendant_tx.max_fee_per_gas() as u64);
584 assert_eq!(removed.len(), 2);
585 assert!(pool.is_empty());
586 }
587
588 #[test]
589 fn truncate_parked_by_submission_id() {
590 let mut f = MockTransactionFactory::default();
592 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
593
594 let a_sender = address!("0x000000000000000000000000000000000000000a");
595 let b_sender = address!("0x000000000000000000000000000000000000000b");
596 let c_sender = address!("0x000000000000000000000000000000000000000c");
597 let d_sender = address!("0x000000000000000000000000000000000000000d");
598
599 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
601 let a = tx_set.clone().into_vec();
602
603 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
604 tx_set.extend(b.clone());
605
606 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
608 tx_set.extend(c.clone());
609
610 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
611 tx_set.extend(d.clone());
612
613 let all_txs = tx_set.into_vec();
614
615 let expected_parked = vec![c[0].clone(), c[1].clone(), c[2].clone(), d[0].clone()]
617 .into_iter()
618 .map(|tx| (tx.sender(), tx.nonce()))
619 .collect::<HashSet<_>>();
620
621 let expected_removed = vec![
625 a[0].clone(),
626 a[1].clone(),
627 a[2].clone(),
628 a[3].clone(),
629 b[0].clone(),
630 b[1].clone(),
631 b[2].clone(),
632 ]
633 .into_iter()
634 .map(|tx| (tx.sender(), tx.nonce()))
635 .collect::<HashSet<_>>();
636
637 for tx in all_txs {
639 pool.add_transaction(f.validated_arc(tx));
640 }
641
642 let pool_limit = SubPoolLimit { max_txs: 4, max_size: usize::MAX };
644
645 let removed = pool.truncate_pool(pool_limit);
647 assert_eq!(removed.len(), expected_removed.len());
648
649 let removed =
651 removed.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
652 assert_eq!(removed, expected_removed);
653
654 let parked = pool.all().collect::<Vec<_>>();
656 assert_eq!(parked.len(), expected_parked.len());
657
658 let parked = parked.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
660 assert_eq!(parked, expected_parked);
661 }
662
663 #[test]
664 fn test_truncate_parked_with_large_tx() {
665 let mut f = MockTransactionFactory::default();
666 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
667 let default_limits = SubPoolLimit::default();
668
669 let a_sender = address!("0x000000000000000000000000000000000000000a");
672
673 let a_txs = MockTransactionSet::dependent(a_sender, 0, 2, TxType::Eip1559)
675 .into_iter()
676 .map(|mut tx| {
677 tx.set_size(default_limits.max_size / 2 + 1);
678 tx
679 })
680 .collect::<Vec<_>>();
681
682 for tx in a_txs {
684 pool.add_transaction(f.validated_arc(tx));
685 }
686
687 let removed = pool.truncate_pool(default_limits);
689 assert_eq!(removed.len(), 1);
690 }
691
692 #[test]
693 fn test_senders_by_submission_id() {
694 let mut f = MockTransactionFactory::default();
696 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
697
698 let a_sender = address!("0x000000000000000000000000000000000000000a");
699 let b_sender = address!("0x000000000000000000000000000000000000000b");
700 let c_sender = address!("0x000000000000000000000000000000000000000c");
701 let d_sender = address!("0x000000000000000000000000000000000000000d");
702
703 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
705 let a = tx_set.clone().into_vec();
706
707 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
708 tx_set.extend(b.clone());
709
710 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
712 tx_set.extend(c.clone());
713
714 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
715 tx_set.extend(d.clone());
716
717 let all_txs = tx_set.into_vec();
718
719 for tx in all_txs {
721 pool.add_transaction(f.validated_arc(tx));
722 }
723
724 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
726 assert_eq!(senders.len(), 4);
727 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
728 .into_iter()
729 .map(|s| f.ids.sender_id(&s).unwrap())
730 .collect::<Vec<_>>();
731 assert_eq!(senders, expected_senders);
732
733 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
735 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
736
737 for tx in all_txs {
739 pool.add_transaction(f.validated_arc(tx));
740 }
741
742 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
743 assert_eq!(senders.len(), 4);
744 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
745 .into_iter()
746 .map(|s| f.ids.sender_id(&s).unwrap())
747 .collect::<Vec<_>>();
748 assert_eq!(senders, expected_senders);
749 }
750
751 #[test]
752 fn test_add_sender_count_new_sender() {
753 let mut f = MockTransactionFactory::default();
755 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
757 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
759 pool.add_transaction(tx);
760
761 let sender: SenderId = 11.into();
763 let submission_id = 1;
764
765 pool.add_sender_count(sender, submission_id);
767
768 assert_eq!(pool.sender_transaction_count.len(), 2);
770 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
771 assert_eq!(sender_info.count, 1);
772 assert_eq!(sender_info.last_submission_id, submission_id);
773
774 assert_eq!(pool.last_sender_submission.len(), 2);
776 let submission_info = pool.last_sender_submission.iter().next().unwrap();
777 assert_eq!(submission_info.sender_id, sender);
778 assert_eq!(submission_info.submission_id, submission_id);
779 }
780
781 #[test]
782 fn test_add_sender_count_existing_sender() {
783 let mut f = MockTransactionFactory::default();
785 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
787 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
789 pool.add_transaction(tx);
790
791 let sender: SenderId = 11.into();
793 let initial_submission_id = 1;
794
795 pool.add_sender_count(sender, initial_submission_id);
797
798 let new_submission_id = 2;
800 pool.add_sender_count(sender, new_submission_id);
802
803 assert_eq!(pool.sender_transaction_count.len(), 2);
805 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
806 assert_eq!(sender_info.count, 2);
807 assert_eq!(sender_info.last_submission_id, new_submission_id);
808
809 assert_eq!(pool.last_sender_submission.len(), 2);
811 let submission_info = pool.last_sender_submission.iter().next().unwrap();
812 assert_eq!(submission_info.sender_id, sender);
813 assert_eq!(submission_info.submission_id, new_submission_id);
814 }
815
816 #[test]
817 fn test_add_sender_count_multiple_senders() {
818 let mut f = MockTransactionFactory::default();
820 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
822 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
824 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
825 pool.add_transaction(tx1);
826 pool.add_transaction(tx2);
827
828 let sender1: SenderId = 11.into();
830 let sender2: SenderId = 22.into();
831
832 pool.add_sender_count(sender1, 1);
834 pool.add_sender_count(sender2, 2);
835
836 assert_eq!(pool.sender_transaction_count.len(), 4);
838
839 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
840 assert_eq!(sender1_info.count, 1);
841 assert_eq!(sender1_info.last_submission_id, 1);
842
843 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
844 assert_eq!(sender2_info.count, 1);
845 assert_eq!(sender2_info.last_submission_id, 2);
846
847 assert_eq!(pool.last_sender_submission.len(), 3);
849
850 let submission_info1 =
852 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
853 assert!(submission_info1.is_none());
854
855 let submission_info2 =
857 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
858 assert_eq!(submission_info2.sender_id, sender2);
859 assert_eq!(submission_info2.submission_id, 2);
860 }
861
862 #[test]
863 fn test_remove_sender_count() {
864 let mut f = MockTransactionFactory::default();
866 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
868 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
870 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
871 pool.add_transaction(tx1);
872 pool.add_transaction(tx2);
873
874 let sender1: SenderId = 11.into();
876 let sender2: SenderId = 22.into();
877
878 pool.add_sender_count(sender1, 1);
880
881 pool.add_sender_count(sender2, 2);
883 pool.add_sender_count(sender2, 3);
884
885 assert_eq!(pool.sender_transaction_count.len(), 4);
887 assert!(pool.sender_transaction_count.contains_key(&sender1));
888
889 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
891
892 pool.remove_sender_count(sender1);
894
895 assert_eq!(pool.sender_transaction_count.len(), 3);
897 assert!(!pool.sender_transaction_count.contains_key(&sender1));
898
899 assert_eq!(
901 *pool.sender_transaction_count.get(&sender2).unwrap(),
902 SenderTransactionCount { count: 2, last_submission_id: 3 }
903 );
904
905 pool.remove_sender_count(sender2);
907
908 assert_eq!(pool.sender_transaction_count.len(), 3);
913 assert!(pool.sender_transaction_count.contains_key(&sender2));
914
915 assert_eq!(
917 *pool.sender_transaction_count.get(&sender2).unwrap(),
918 SenderTransactionCount { count: 1, last_submission_id: 3 }
919 );
920 }
921
922 #[test]
923 fn test_pool_size() {
924 let mut f = MockTransactionFactory::default();
925 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
926
927 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
929 pool.add_transaction(tx);
930
931 assert_eq!(pool.size(), 1024);
933 }
934
935 #[test]
936 fn test_pool_len() {
937 let mut f = MockTransactionFactory::default();
938 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
939
940 assert_eq!(pool.len(), 0);
942
943 let tx = f.validated_arc(MockTransaction::eip1559());
945 pool.add_transaction(tx);
946 assert_eq!(pool.len(), 1);
947 }
948
949 #[test]
950 fn test_pool_contains() {
951 let mut f = MockTransactionFactory::default();
952 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
953
954 let tx = f.validated_arc(MockTransaction::eip1559());
956 let tx_id = *tx.id();
957
958 assert!(!pool.contains(&tx_id));
960
961 pool.add_transaction(tx);
963 assert!(pool.contains(&tx_id));
964 }
965
966 #[test]
967 fn test_get_transaction() {
968 let mut f = MockTransactionFactory::default();
969 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
970
971 let tx = f.validated_arc(MockTransaction::eip1559());
973 let tx_id = *tx.id();
974 pool.add_transaction(tx.clone());
975
976 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
978 assert_eq!(retrieved.transaction.id(), tx.id());
979 }
980
981 #[test]
982 fn test_all_transactions() {
983 let mut f = MockTransactionFactory::default();
984 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
985
986 let tx1 = f.validated_arc(MockTransaction::eip1559());
988 let tx2 = f.validated_arc(MockTransaction::eip1559());
989 pool.add_transaction(tx1.clone());
990 pool.add_transaction(tx2.clone());
991
992 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
994 assert_eq!(all_txs.len(), 2);
995
996 assert!(all_txs.contains(tx1.id()));
998 assert!(all_txs.contains(tx2.id()));
999 }
1000
1001 #[test]
1002 fn test_truncate_pool_edge_case() {
1003 let mut f = MockTransactionFactory::default();
1004 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1005
1006 let tx1 = f.validated_arc(MockTransaction::eip1559());
1008 let tx2 = f.validated_arc(MockTransaction::eip1559());
1009 pool.add_transaction(tx1);
1010 pool.add_transaction(tx2);
1011
1012 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1014 let removed = pool.truncate_pool(limit);
1015
1016 assert!(removed.is_empty());
1018
1019 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1021 let removed = pool.truncate_pool(limit);
1022
1023 assert_eq!(removed.len(), 1);
1025 assert_eq!(pool.len(), 1);
1026 }
1027
1028 #[test]
1029 fn test_satisfy_base_fee_transactions() {
1030 let mut f = MockTransactionFactory::default();
1031 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1032
1033 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1035 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1036 pool.add_transaction(tx1);
1037 pool.add_transaction(tx2.clone());
1038
1039 let satisfied = pool.satisfy_base_fee_transactions(150);
1041 assert_eq!(satisfied.len(), 1);
1042 assert_eq!(satisfied[0].id(), tx2.id())
1043 }
1044
1045 #[test]
1046 fn test_remove_transaction() {
1047 let mut f = MockTransactionFactory::default();
1048 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1049
1050 let tx = f.validated_arc(MockTransaction::eip1559());
1052 let tx_id = *tx.id();
1053 pool.add_transaction(tx);
1054
1055 assert!(pool.contains(&tx_id));
1057
1058 let removed = pool.remove_transaction(&tx_id);
1060 assert!(removed.is_some());
1061 assert!(!pool.contains(&tx_id));
1062 }
1063
1064 #[test]
1065 fn test_enforce_basefee_with_handler_zero_allocation() {
1066 let mut f = MockTransactionFactory::default();
1067 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1068
1069 let sender_a = address!("0x000000000000000000000000000000000000000a");
1071 let sender_b = address!("0x000000000000000000000000000000000000000b");
1072
1073 let txs = vec![
1077 f.validated_arc(
1078 MockTransaction::eip1559()
1079 .set_sender(sender_a)
1080 .set_nonce(0)
1081 .set_max_fee(500)
1082 .clone(),
1083 ),
1084 f.validated_arc(
1085 MockTransaction::eip1559()
1086 .set_sender(sender_a)
1087 .set_nonce(1)
1088 .set_max_fee(600)
1089 .clone(),
1090 ),
1091 f.validated_arc(
1092 MockTransaction::eip1559()
1093 .set_sender(sender_b)
1094 .set_nonce(0)
1095 .set_max_fee(300)
1096 .clone(),
1097 ),
1098 ];
1099
1100 let expected_affordable = vec![txs[0].clone(), txs[1].clone()]; for tx in txs {
1102 pool.add_transaction(tx);
1103 }
1104
1105 let mut processed_txs = Vec::new();
1107 let mut handler_call_count = 0;
1108
1109 pool.enforce_basefee_with(400, |tx| {
1110 processed_txs.push(tx);
1111 handler_call_count += 1;
1112 });
1113
1114 assert_eq!(handler_call_count, 2);
1116 assert_eq!(processed_txs.len(), 2);
1117
1118 let processed_ids: Vec<_> = processed_txs.iter().map(|tx| *tx.id()).collect();
1120 for expected_tx in expected_affordable {
1121 assert!(processed_ids.contains(expected_tx.id()));
1122 }
1123
1124 assert_eq!(pool.len(), 1); }
1127}