1use 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 mut txs = Vec::new();
264 self.satisfy_base_fee_ids(basefee as u128, |tx| {
265 txs.push(tx.clone());
266 });
267 txs
268 }
269
270 fn satisfy_base_fee_ids<F>(&self, basefee: u128, mut tx_handler: F)
272 where
273 F: FnMut(&Arc<ValidPoolTransaction<T>>),
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 tx_handler(&tx.transaction);
288 }
289 }
290 }
291
292 pub(crate) fn enforce_basefee_with<F>(&mut self, basefee: u64, mut tx_handler: F)
304 where
305 F: FnMut(Arc<ValidPoolTransaction<T>>),
306 {
307 let mut to_remove = Vec::new();
308 self.satisfy_base_fee_ids(basefee as u128, |tx| {
309 to_remove.push(*tx.id());
310 });
311
312 for id in to_remove {
313 if let Some(tx) = self.remove_transaction(&id) {
314 tx_handler(tx);
315 }
316 }
317 }
318
319 #[cfg(test)]
327 pub(crate) fn enforce_basefee(&mut self, basefee: u64) -> Vec<Arc<ValidPoolTransaction<T>>> {
328 let mut removed = Vec::new();
329 self.enforce_basefee_with(basefee, |tx| {
330 removed.push(tx);
331 });
332 removed
333 }
334}
335
336impl<T: ParkedOrd> Default for ParkedPool<T> {
337 fn default() -> Self {
338 Self {
339 submission_id: 0,
340 by_id: Default::default(),
341 last_sender_submission: Default::default(),
342 sender_transaction_count: Default::default(),
343 size_of: Default::default(),
344 }
345 }
346}
347
348#[derive(Debug, Clone, Default, PartialEq, Eq)]
350struct SenderTransactionCount {
351 count: u64,
352 last_submission_id: u64,
353}
354
355#[derive(Debug)]
357struct ParkedPoolTransaction<T: ParkedOrd> {
358 submission_id: u64,
360 transaction: T,
362}
363
364impl<T: ParkedOrd> Clone for ParkedPoolTransaction<T> {
365 fn clone(&self) -> Self {
366 Self { submission_id: self.submission_id, transaction: self.transaction.clone() }
367 }
368}
369
370impl<T: ParkedOrd> Eq for ParkedPoolTransaction<T> {}
371
372impl<T: ParkedOrd> PartialEq<Self> for ParkedPoolTransaction<T> {
373 fn eq(&self, other: &Self) -> bool {
374 self.cmp(other) == Ordering::Equal
375 }
376}
377
378impl<T: ParkedOrd> PartialOrd<Self> for ParkedPoolTransaction<T> {
379 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
380 Some(self.cmp(other))
381 }
382}
383
384impl<T: ParkedOrd> Ord for ParkedPoolTransaction<T> {
385 fn cmp(&self, other: &Self) -> Ordering {
386 self.transaction
390 .cmp(&other.transaction)
391 .then_with(|| other.submission_id.cmp(&self.submission_id))
392 }
393}
394
395#[derive(Debug, PartialEq, Eq, Copy, Clone)]
398pub(crate) struct SubmissionSenderId {
399 pub(crate) sender_id: SenderId,
401 pub(crate) submission_id: u64,
403}
404
405impl SubmissionSenderId {
406 const fn new(sender_id: SenderId, submission_id: u64) -> Self {
408 Self { sender_id, submission_id }
409 }
410}
411
412impl Ord for SubmissionSenderId {
413 fn cmp(&self, other: &Self) -> Ordering {
414 other.submission_id.cmp(&self.submission_id)
416 }
417}
418
419impl PartialOrd for SubmissionSenderId {
420 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
421 Some(self.cmp(other))
422 }
423}
424
425pub trait ParkedOrd:
429 Ord
430 + Clone
431 + From<Arc<ValidPoolTransaction<Self::Transaction>>>
432 + Into<Arc<ValidPoolTransaction<Self::Transaction>>>
433 + Deref<Target = Arc<ValidPoolTransaction<Self::Transaction>>>
434{
435 type Transaction: PoolTransaction;
437}
438
439macro_rules! impl_ord_wrapper {
441 ($name:ident) => {
442 impl<T: PoolTransaction> Clone for $name<T> {
443 fn clone(&self) -> Self {
444 Self(self.0.clone())
445 }
446 }
447
448 impl<T: PoolTransaction> Eq for $name<T> {}
449
450 impl<T: PoolTransaction> PartialEq<Self> for $name<T> {
451 fn eq(&self, other: &Self) -> bool {
452 self.cmp(other) == Ordering::Equal
453 }
454 }
455
456 impl<T: PoolTransaction> PartialOrd<Self> for $name<T> {
457 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
458 Some(self.cmp(other))
459 }
460 }
461 impl<T: PoolTransaction> Deref for $name<T> {
462 type Target = Arc<ValidPoolTransaction<T>>;
463
464 fn deref(&self) -> &Self::Target {
465 &self.0
466 }
467 }
468
469 impl<T: PoolTransaction> ParkedOrd for $name<T> {
470 type Transaction = T;
471 }
472
473 impl<T: PoolTransaction> From<Arc<ValidPoolTransaction<T>>> for $name<T> {
474 fn from(value: Arc<ValidPoolTransaction<T>>) -> Self {
475 Self(value)
476 }
477 }
478
479 impl<T: PoolTransaction> From<$name<T>> for Arc<ValidPoolTransaction<T>> {
480 fn from(value: $name<T>) -> Arc<ValidPoolTransaction<T>> {
481 value.0
482 }
483 }
484 };
485}
486
487#[derive(Debug)]
493pub struct BasefeeOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
494
495impl_ord_wrapper!(BasefeeOrd);
496
497impl<T: PoolTransaction> Ord for BasefeeOrd<T> {
498 fn cmp(&self, other: &Self) -> Ordering {
499 self.0.transaction.max_fee_per_gas().cmp(&other.0.transaction.max_fee_per_gas())
500 }
501}
502
503#[derive(Debug)]
513pub struct QueuedOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
514
515impl_ord_wrapper!(QueuedOrd);
516
517impl<T: PoolTransaction> Ord for QueuedOrd<T> {
518 fn cmp(&self, other: &Self) -> Ordering {
519 self.max_fee_per_gas().cmp(&other.max_fee_per_gas()).then_with(||
521 other.timestamp.cmp(&self.timestamp))
523 }
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529 use crate::test_utils::{MockTransaction, MockTransactionFactory, MockTransactionSet};
530 use alloy_consensus::{Transaction, TxType};
531 use alloy_primitives::address;
532 use std::collections::HashSet;
533
534 #[test]
535 fn test_enforce_parked_basefee() {
536 let mut f = MockTransactionFactory::default();
537 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
538 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
539 pool.add_transaction(tx.clone());
540
541 assert!(pool.contains(tx.id()));
542 assert_eq!(pool.len(), 1);
543
544 let removed = pool.enforce_basefee(u64::MAX);
545 assert!(removed.is_empty());
546
547 let removed = pool.enforce_basefee((tx.max_fee_per_gas() - 1) as u64);
548 assert_eq!(removed.len(), 1);
549 assert!(pool.is_empty());
550 }
551
552 #[test]
553 fn test_enforce_parked_basefee_descendant() {
554 let mut f = MockTransactionFactory::default();
555 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
556 let t = MockTransaction::eip1559().inc_price_by(10);
557 let root_tx = f.validated_arc(t.clone());
558 pool.add_transaction(root_tx.clone());
559
560 let descendant_tx = f.validated_arc(t.inc_nonce().decr_price());
561 pool.add_transaction(descendant_tx.clone());
562
563 assert!(pool.contains(root_tx.id()));
564 assert!(pool.contains(descendant_tx.id()));
565 assert_eq!(pool.len(), 2);
566
567 let removed = pool.enforce_basefee(u64::MAX);
568 assert!(removed.is_empty());
569 assert_eq!(pool.len(), 2);
570 {
573 let mut pool2 = pool.clone();
575 let removed = pool2.enforce_basefee(root_tx.max_fee_per_gas() as u64);
576 assert_eq!(removed.len(), 1);
577 assert_eq!(pool2.len(), 1);
578 assert!(!pool2.contains(root_tx.id()));
580 assert!(pool2.contains(descendant_tx.id()));
581 }
582
583 let removed = pool.enforce_basefee(descendant_tx.max_fee_per_gas() as u64);
585 assert_eq!(removed.len(), 2);
586 assert!(pool.is_empty());
587 }
588
589 #[test]
590 fn truncate_parked_by_submission_id() {
591 let mut f = MockTransactionFactory::default();
593 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
594
595 let a_sender = address!("0x000000000000000000000000000000000000000a");
596 let b_sender = address!("0x000000000000000000000000000000000000000b");
597 let c_sender = address!("0x000000000000000000000000000000000000000c");
598 let d_sender = address!("0x000000000000000000000000000000000000000d");
599
600 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
602 let a = tx_set.clone().into_vec();
603
604 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
605 tx_set.extend(b.clone());
606
607 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
609 tx_set.extend(c.clone());
610
611 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
612 tx_set.extend(d.clone());
613
614 let all_txs = tx_set.into_vec();
615
616 let expected_parked = vec![c[0].clone(), c[1].clone(), c[2].clone(), d[0].clone()]
618 .into_iter()
619 .map(|tx| (tx.sender(), tx.nonce()))
620 .collect::<HashSet<_>>();
621
622 let expected_removed = vec![
626 a[0].clone(),
627 a[1].clone(),
628 a[2].clone(),
629 a[3].clone(),
630 b[0].clone(),
631 b[1].clone(),
632 b[2].clone(),
633 ]
634 .into_iter()
635 .map(|tx| (tx.sender(), tx.nonce()))
636 .collect::<HashSet<_>>();
637
638 for tx in all_txs {
640 pool.add_transaction(f.validated_arc(tx));
641 }
642
643 let pool_limit = SubPoolLimit { max_txs: 4, max_size: usize::MAX };
645
646 let removed = pool.truncate_pool(pool_limit);
648 assert_eq!(removed.len(), expected_removed.len());
649
650 let removed =
652 removed.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
653 assert_eq!(removed, expected_removed);
654
655 let parked = pool.all().collect::<Vec<_>>();
657 assert_eq!(parked.len(), expected_parked.len());
658
659 let parked = parked.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
661 assert_eq!(parked, expected_parked);
662 }
663
664 #[test]
665 fn test_truncate_parked_with_large_tx() {
666 let mut f = MockTransactionFactory::default();
667 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
668 let default_limits = SubPoolLimit::default();
669
670 let a_sender = address!("0x000000000000000000000000000000000000000a");
673
674 let a_txs = MockTransactionSet::dependent(a_sender, 0, 2, TxType::Eip1559)
676 .into_iter()
677 .map(|mut tx| {
678 tx.set_size(default_limits.max_size / 2 + 1);
679 tx
680 })
681 .collect::<Vec<_>>();
682
683 for tx in a_txs {
685 pool.add_transaction(f.validated_arc(tx));
686 }
687
688 let removed = pool.truncate_pool(default_limits);
690 assert_eq!(removed.len(), 1);
691 }
692
693 #[test]
694 fn test_senders_by_submission_id() {
695 let mut f = MockTransactionFactory::default();
697 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
698
699 let a_sender = address!("0x000000000000000000000000000000000000000a");
700 let b_sender = address!("0x000000000000000000000000000000000000000b");
701 let c_sender = address!("0x000000000000000000000000000000000000000c");
702 let d_sender = address!("0x000000000000000000000000000000000000000d");
703
704 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
706 let a = tx_set.clone().into_vec();
707
708 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
709 tx_set.extend(b.clone());
710
711 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
713 tx_set.extend(c.clone());
714
715 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
716 tx_set.extend(d.clone());
717
718 let all_txs = tx_set.into_vec();
719
720 for tx in all_txs {
722 pool.add_transaction(f.validated_arc(tx));
723 }
724
725 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
727 assert_eq!(senders.len(), 4);
728 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
729 .into_iter()
730 .map(|s| f.ids.sender_id(&s).unwrap())
731 .collect::<Vec<_>>();
732 assert_eq!(senders, expected_senders);
733
734 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
736 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
737
738 for tx in all_txs {
740 pool.add_transaction(f.validated_arc(tx));
741 }
742
743 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
744 assert_eq!(senders.len(), 4);
745 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
746 .into_iter()
747 .map(|s| f.ids.sender_id(&s).unwrap())
748 .collect::<Vec<_>>();
749 assert_eq!(senders, expected_senders);
750 }
751
752 #[test]
753 fn test_add_sender_count_new_sender() {
754 let mut f = MockTransactionFactory::default();
756 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
758 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
760 pool.add_transaction(tx);
761
762 let sender: SenderId = 11.into();
764 let submission_id = 1;
765
766 pool.add_sender_count(sender, submission_id);
768
769 assert_eq!(pool.sender_transaction_count.len(), 2);
771 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
772 assert_eq!(sender_info.count, 1);
773 assert_eq!(sender_info.last_submission_id, submission_id);
774
775 assert_eq!(pool.last_sender_submission.len(), 2);
777 let submission_info = pool.last_sender_submission.iter().next().unwrap();
778 assert_eq!(submission_info.sender_id, sender);
779 assert_eq!(submission_info.submission_id, submission_id);
780 }
781
782 #[test]
783 fn test_add_sender_count_existing_sender() {
784 let mut f = MockTransactionFactory::default();
786 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
788 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
790 pool.add_transaction(tx);
791
792 let sender: SenderId = 11.into();
794 let initial_submission_id = 1;
795
796 pool.add_sender_count(sender, initial_submission_id);
798
799 let new_submission_id = 2;
801 pool.add_sender_count(sender, new_submission_id);
803
804 assert_eq!(pool.sender_transaction_count.len(), 2);
806 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
807 assert_eq!(sender_info.count, 2);
808 assert_eq!(sender_info.last_submission_id, new_submission_id);
809
810 assert_eq!(pool.last_sender_submission.len(), 2);
812 let submission_info = pool.last_sender_submission.iter().next().unwrap();
813 assert_eq!(submission_info.sender_id, sender);
814 assert_eq!(submission_info.submission_id, new_submission_id);
815 }
816
817 #[test]
818 fn test_add_sender_count_multiple_senders() {
819 let mut f = MockTransactionFactory::default();
821 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
823 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
825 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
826 pool.add_transaction(tx1);
827 pool.add_transaction(tx2);
828
829 let sender1: SenderId = 11.into();
831 let sender2: SenderId = 22.into();
832
833 pool.add_sender_count(sender1, 1);
835 pool.add_sender_count(sender2, 2);
836
837 assert_eq!(pool.sender_transaction_count.len(), 4);
839
840 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
841 assert_eq!(sender1_info.count, 1);
842 assert_eq!(sender1_info.last_submission_id, 1);
843
844 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
845 assert_eq!(sender2_info.count, 1);
846 assert_eq!(sender2_info.last_submission_id, 2);
847
848 assert_eq!(pool.last_sender_submission.len(), 3);
850
851 let submission_info1 =
853 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
854 assert!(submission_info1.is_none());
855
856 let submission_info2 =
858 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
859 assert_eq!(submission_info2.sender_id, sender2);
860 assert_eq!(submission_info2.submission_id, 2);
861 }
862
863 #[test]
864 fn test_remove_sender_count() {
865 let mut f = MockTransactionFactory::default();
867 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
869 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
871 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
872 pool.add_transaction(tx1);
873 pool.add_transaction(tx2);
874
875 let sender1: SenderId = 11.into();
877 let sender2: SenderId = 22.into();
878
879 pool.add_sender_count(sender1, 1);
881
882 pool.add_sender_count(sender2, 2);
884 pool.add_sender_count(sender2, 3);
885
886 assert_eq!(pool.sender_transaction_count.len(), 4);
888 assert!(pool.sender_transaction_count.contains_key(&sender1));
889
890 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
892
893 pool.remove_sender_count(sender1);
895
896 assert_eq!(pool.sender_transaction_count.len(), 3);
898 assert!(!pool.sender_transaction_count.contains_key(&sender1));
899
900 assert_eq!(
902 *pool.sender_transaction_count.get(&sender2).unwrap(),
903 SenderTransactionCount { count: 2, last_submission_id: 3 }
904 );
905
906 pool.remove_sender_count(sender2);
908
909 assert_eq!(pool.sender_transaction_count.len(), 3);
914 assert!(pool.sender_transaction_count.contains_key(&sender2));
915
916 assert_eq!(
918 *pool.sender_transaction_count.get(&sender2).unwrap(),
919 SenderTransactionCount { count: 1, last_submission_id: 3 }
920 );
921 }
922
923 #[test]
924 fn test_pool_size() {
925 let mut f = MockTransactionFactory::default();
926 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
927
928 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
930 pool.add_transaction(tx);
931
932 assert_eq!(pool.size(), 1024);
934 }
935
936 #[test]
937 fn test_pool_len() {
938 let mut f = MockTransactionFactory::default();
939 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
940
941 assert_eq!(pool.len(), 0);
943
944 let tx = f.validated_arc(MockTransaction::eip1559());
946 pool.add_transaction(tx);
947 assert_eq!(pool.len(), 1);
948 }
949
950 #[test]
951 fn test_pool_contains() {
952 let mut f = MockTransactionFactory::default();
953 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
954
955 let tx = f.validated_arc(MockTransaction::eip1559());
957 let tx_id = *tx.id();
958
959 assert!(!pool.contains(&tx_id));
961
962 pool.add_transaction(tx);
964 assert!(pool.contains(&tx_id));
965 }
966
967 #[test]
968 fn test_get_transaction() {
969 let mut f = MockTransactionFactory::default();
970 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
971
972 let tx = f.validated_arc(MockTransaction::eip1559());
974 let tx_id = *tx.id();
975 pool.add_transaction(tx.clone());
976
977 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
979 assert_eq!(retrieved.transaction.id(), tx.id());
980 }
981
982 #[test]
983 fn test_all_transactions() {
984 let mut f = MockTransactionFactory::default();
985 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
986
987 let tx1 = f.validated_arc(MockTransaction::eip1559());
989 let tx2 = f.validated_arc(MockTransaction::eip1559());
990 pool.add_transaction(tx1.clone());
991 pool.add_transaction(tx2.clone());
992
993 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
995 assert_eq!(all_txs.len(), 2);
996
997 assert!(all_txs.contains(tx1.id()));
999 assert!(all_txs.contains(tx2.id()));
1000 }
1001
1002 #[test]
1003 fn test_truncate_pool_edge_case() {
1004 let mut f = MockTransactionFactory::default();
1005 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1006
1007 let tx1 = f.validated_arc(MockTransaction::eip1559());
1009 let tx2 = f.validated_arc(MockTransaction::eip1559());
1010 pool.add_transaction(tx1);
1011 pool.add_transaction(tx2);
1012
1013 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1015 let removed = pool.truncate_pool(limit);
1016
1017 assert!(removed.is_empty());
1019
1020 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1022 let removed = pool.truncate_pool(limit);
1023
1024 assert_eq!(removed.len(), 1);
1026 assert_eq!(pool.len(), 1);
1027 }
1028
1029 #[test]
1030 fn test_satisfy_base_fee_transactions() {
1031 let mut f = MockTransactionFactory::default();
1032 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1033
1034 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1036 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1037 pool.add_transaction(tx1);
1038 pool.add_transaction(tx2.clone());
1039
1040 let satisfied = pool.satisfy_base_fee_transactions(150);
1042 assert_eq!(satisfied.len(), 1);
1043 assert_eq!(satisfied[0].id(), tx2.id())
1044 }
1045
1046 #[test]
1047 fn test_remove_transaction() {
1048 let mut f = MockTransactionFactory::default();
1049 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1050
1051 let tx = f.validated_arc(MockTransaction::eip1559());
1053 let tx_id = *tx.id();
1054 pool.add_transaction(tx);
1055
1056 assert!(pool.contains(&tx_id));
1058
1059 let removed = pool.remove_transaction(&tx_id);
1061 assert!(removed.is_some());
1062 assert!(!pool.contains(&tx_id));
1063 }
1064
1065 #[test]
1066 fn test_enforce_basefee_with_handler_zero_allocation() {
1067 let mut f = MockTransactionFactory::default();
1068 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1069
1070 let sender_a = address!("0x000000000000000000000000000000000000000a");
1072 let sender_b = address!("0x000000000000000000000000000000000000000b");
1073
1074 let txs = vec![
1078 f.validated_arc(
1079 MockTransaction::eip1559()
1080 .set_sender(sender_a)
1081 .set_nonce(0)
1082 .set_max_fee(500)
1083 .clone(),
1084 ),
1085 f.validated_arc(
1086 MockTransaction::eip1559()
1087 .set_sender(sender_a)
1088 .set_nonce(1)
1089 .set_max_fee(600)
1090 .clone(),
1091 ),
1092 f.validated_arc(
1093 MockTransaction::eip1559()
1094 .set_sender(sender_b)
1095 .set_nonce(0)
1096 .set_max_fee(300)
1097 .clone(),
1098 ),
1099 ];
1100
1101 let expected_affordable = vec![txs[0].clone(), txs[1].clone()]; for tx in txs {
1103 pool.add_transaction(tx);
1104 }
1105
1106 let mut processed_txs = Vec::new();
1108 let mut handler_call_count = 0;
1109
1110 pool.enforce_basefee_with(400, |tx| {
1111 processed_txs.push(tx);
1112 handler_call_count += 1;
1113 });
1114
1115 assert_eq!(handler_call_count, 2);
1117 assert_eq!(processed_txs.len(), 2);
1118
1119 let processed_ids: Vec<_> = processed_txs.iter().map(|tx| *tx.id()).collect();
1121 for expected_tx in expected_affordable {
1122 assert!(processed_ids.contains(expected_tx.id()));
1123 }
1124
1125 assert_eq!(pool.len(), 1); }
1128}