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)]
25pub struct ParkedPool<T: ParkedOrd> {
26 submission_id: u64,
30 by_id: BTreeMap<TransactionId, ParkedPoolTransaction<T>>,
32 best: BTreeSet<ParkedPoolTransaction<T>>,
36 last_sender_submission: BTreeSet<SubmissionSenderId>,
41 sender_transaction_count: FxHashMap<SenderId, SenderTransactionCount>,
44 size_of: SizeTracker,
48}
49
50impl<T: ParkedOrd> ParkedPool<T> {
53 pub fn add_transaction(&mut self, tx: Arc<ValidPoolTransaction<T::Transaction>>) {
59 let id = *tx.id();
60 assert!(
61 !self.contains(&id),
62 "transaction already included {:?}",
63 self.get(&id).unwrap().transaction.transaction
64 );
65 let submission_id = self.next_id();
66
67 self.size_of += tx.size();
69
70 self.add_sender_count(tx.sender_id(), submission_id);
72 let transaction = ParkedPoolTransaction { submission_id, transaction: tx.into() };
73
74 self.by_id.insert(id, transaction.clone());
75 self.best.insert(transaction);
76 }
77
78 fn add_sender_count(&mut self, sender: SenderId, submission_id: u64) {
81 match self.sender_transaction_count.entry(sender) {
82 Entry::Occupied(mut entry) => {
83 let value = entry.get_mut();
84 self.last_sender_submission
86 .remove(&SubmissionSenderId::new(sender, value.last_submission_id));
87
88 value.count += 1;
89 value.last_submission_id = submission_id;
90 }
91 Entry::Vacant(entry) => {
92 entry
93 .insert(SenderTransactionCount { count: 1, last_submission_id: submission_id });
94 }
95 }
96 self.last_sender_submission.insert(SubmissionSenderId::new(sender, submission_id));
98 }
99
100 fn remove_sender_count(&mut self, sender_id: SenderId) {
107 let removed_sender = match self.sender_transaction_count.entry(sender_id) {
108 Entry::Occupied(mut entry) => {
109 let value = entry.get_mut();
110 value.count -= 1;
111 if value.count == 0 {
112 entry.remove()
113 } else {
114 return
115 }
116 }
117 Entry::Vacant(_) => {
118 unreachable!("sender count not found {:?}", sender_id);
120 }
121 };
122
123 assert!(
125 self.last_sender_submission
126 .remove(&SubmissionSenderId::new(sender_id, removed_sender.last_submission_id)),
127 "last sender transaction not found {sender_id:?}"
128 );
129 }
130
131 pub(crate) fn all(
133 &self,
134 ) -> impl Iterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
135 self.by_id.values().map(|tx| tx.transaction.clone().into())
136 }
137
138 pub(crate) fn remove_transaction(
140 &mut self,
141 id: &TransactionId,
142 ) -> Option<Arc<ValidPoolTransaction<T::Transaction>>> {
143 let tx = self.by_id.remove(id)?;
145 self.best.remove(&tx);
146 self.remove_sender_count(tx.transaction.sender_id());
147
148 self.size_of -= tx.transaction.size();
150
151 Some(tx.transaction.into())
152 }
153
154 pub(crate) fn get_txs_by_sender(
157 &self,
158 sender: SenderId,
159 ) -> SmallVec<[TransactionId; TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER]> {
160 self.by_id
161 .range((sender.start_bound(), Unbounded))
162 .take_while(move |(other, _)| sender == other.sender)
163 .map(|(tx_id, _)| *tx_id)
164 .collect()
165 }
166
167 #[cfg(test)]
168 pub(crate) fn get_senders_by_submission_id(
169 &self,
170 ) -> impl Iterator<Item = SubmissionSenderId> + '_ {
171 self.last_sender_submission.iter().copied()
172 }
173
174 pub fn truncate_pool(
188 &mut self,
189 limit: SubPoolLimit,
190 ) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
191 if !self.exceeds(&limit) {
192 return Vec::new()
194 }
195
196 let mut removed = Vec::new();
197
198 while limit.is_exceeded(self.len(), self.size()) && !self.last_sender_submission.is_empty()
199 {
200 let sender_id = self.last_sender_submission.last().expect("not empty").sender_id;
202 let list = self.get_txs_by_sender(sender_id);
203
204 for txid in list.into_iter().rev() {
206 if let Some(tx) = self.remove_transaction(&txid) {
207 removed.push(tx);
208 }
209
210 if !self.exceeds(&limit) {
211 break
212 }
213 }
214 }
215
216 removed
217 }
218
219 fn next_id(&mut self) -> u64 {
220 let id = self.submission_id;
221 self.submission_id = self.submission_id.wrapping_add(1);
222 id
223 }
224
225 pub(crate) fn size(&self) -> usize {
227 self.size_of.into()
228 }
229
230 pub(crate) fn len(&self) -> usize {
232 self.by_id.len()
233 }
234
235 #[inline]
237 pub(crate) fn exceeds(&self, limit: &SubPoolLimit) -> bool {
238 limit.is_exceeded(self.len(), self.size())
239 }
240
241 #[cfg(test)]
243 #[allow(dead_code)]
244 pub(crate) fn is_empty(&self) -> bool {
245 self.by_id.is_empty()
246 }
247
248 pub(crate) fn contains(&self, id: &TransactionId) -> bool {
250 self.by_id.contains_key(id)
251 }
252
253 fn get(&self, id: &TransactionId) -> Option<&ParkedPoolTransaction<T>> {
255 self.by_id.get(id)
256 }
257
258 #[cfg(any(test, feature = "test-utils"))]
260 pub(crate) fn assert_invariants(&self) {
261 assert_eq!(self.by_id.len(), self.best.len(), "by_id.len() != best.len()");
262
263 assert_eq!(
264 self.last_sender_submission.len(),
265 self.sender_transaction_count.len(),
266 "last_sender_transaction.len() != sender_to_last_transaction.len()"
267 );
268 }
269}
270
271impl<T: PoolTransaction> ParkedPool<BasefeeOrd<T>> {
272 #[allow(dead_code)]
276 pub(crate) fn satisfy_base_fee_transactions(
277 &self,
278 basefee: u64,
279 ) -> Vec<Arc<ValidPoolTransaction<T>>> {
280 let ids = self.satisfy_base_fee_ids(basefee);
281 let mut txs = Vec::with_capacity(ids.len());
282 for id in ids {
283 txs.push(self.get(&id).expect("transaction exists").transaction.clone().into());
284 }
285 txs
286 }
287
288 fn satisfy_base_fee_ids(&self, basefee: u64) -> Vec<TransactionId> {
290 let mut transactions = Vec::new();
291 {
292 let mut iter = self.by_id.iter().peekable();
293
294 while let Some((id, tx)) = iter.next() {
295 if tx.transaction.transaction.max_fee_per_gas() < basefee as u128 {
296 'this: while let Some((peek, _)) = iter.peek() {
298 if peek.sender != id.sender {
299 break 'this
300 }
301 iter.next();
302 }
303 } else {
304 transactions.push(*id);
305 }
306 }
307 }
308 transactions
309 }
310
311 pub(crate) fn enforce_basefee(&mut self, basefee: u64) -> Vec<Arc<ValidPoolTransaction<T>>> {
316 let to_remove = self.satisfy_base_fee_ids(basefee);
317
318 let mut removed = Vec::with_capacity(to_remove.len());
319 for id in to_remove {
320 removed.push(self.remove_transaction(&id).expect("transaction exists"));
321 }
322
323 removed
324 }
325}
326
327impl<T: ParkedOrd> Default for ParkedPool<T> {
328 fn default() -> Self {
329 Self {
330 submission_id: 0,
331 by_id: Default::default(),
332 best: Default::default(),
333 last_sender_submission: Default::default(),
334 sender_transaction_count: Default::default(),
335 size_of: Default::default(),
336 }
337 }
338}
339
340#[derive(Debug, Clone, Default, PartialEq, Eq)]
342struct SenderTransactionCount {
343 count: u64,
344 last_submission_id: u64,
345}
346
347#[derive(Debug)]
349struct ParkedPoolTransaction<T: ParkedOrd> {
350 submission_id: u64,
352 transaction: T,
354}
355
356impl<T: ParkedOrd> Clone for ParkedPoolTransaction<T> {
357 fn clone(&self) -> Self {
358 Self { submission_id: self.submission_id, transaction: self.transaction.clone() }
359 }
360}
361
362impl<T: ParkedOrd> Eq for ParkedPoolTransaction<T> {}
363
364impl<T: ParkedOrd> PartialEq<Self> for ParkedPoolTransaction<T> {
365 fn eq(&self, other: &Self) -> bool {
366 self.cmp(other) == Ordering::Equal
367 }
368}
369
370impl<T: ParkedOrd> PartialOrd<Self> for ParkedPoolTransaction<T> {
371 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
372 Some(self.cmp(other))
373 }
374}
375
376impl<T: ParkedOrd> Ord for ParkedPoolTransaction<T> {
377 fn cmp(&self, other: &Self) -> Ordering {
378 self.transaction
382 .cmp(&other.transaction)
383 .then_with(|| other.submission_id.cmp(&self.submission_id))
384 }
385}
386
387#[derive(Debug, PartialEq, Eq, Copy, Clone)]
390pub(crate) struct SubmissionSenderId {
391 pub(crate) sender_id: SenderId,
393 pub(crate) submission_id: u64,
395}
396
397impl SubmissionSenderId {
398 const fn new(sender_id: SenderId, submission_id: u64) -> Self {
400 Self { sender_id, submission_id }
401 }
402}
403
404impl Ord for SubmissionSenderId {
405 fn cmp(&self, other: &Self) -> Ordering {
406 other.submission_id.cmp(&self.submission_id)
408 }
409}
410
411impl PartialOrd for SubmissionSenderId {
412 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
413 Some(self.cmp(other))
414 }
415}
416
417pub trait ParkedOrd:
421 Ord
422 + Clone
423 + From<Arc<ValidPoolTransaction<Self::Transaction>>>
424 + Into<Arc<ValidPoolTransaction<Self::Transaction>>>
425 + Deref<Target = Arc<ValidPoolTransaction<Self::Transaction>>>
426{
427 type Transaction: PoolTransaction;
429}
430
431macro_rules! impl_ord_wrapper {
433 ($name:ident) => {
434 impl<T: PoolTransaction> Clone for $name<T> {
435 fn clone(&self) -> Self {
436 Self(self.0.clone())
437 }
438 }
439
440 impl<T: PoolTransaction> Eq for $name<T> {}
441
442 impl<T: PoolTransaction> PartialEq<Self> for $name<T> {
443 fn eq(&self, other: &Self) -> bool {
444 self.cmp(other) == Ordering::Equal
445 }
446 }
447
448 impl<T: PoolTransaction> PartialOrd<Self> for $name<T> {
449 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
450 Some(self.cmp(other))
451 }
452 }
453 impl<T: PoolTransaction> Deref for $name<T> {
454 type Target = Arc<ValidPoolTransaction<T>>;
455
456 fn deref(&self) -> &Self::Target {
457 &self.0
458 }
459 }
460
461 impl<T: PoolTransaction> ParkedOrd for $name<T> {
462 type Transaction = T;
463 }
464
465 impl<T: PoolTransaction> From<Arc<ValidPoolTransaction<T>>> for $name<T> {
466 fn from(value: Arc<ValidPoolTransaction<T>>) -> Self {
467 Self(value)
468 }
469 }
470
471 impl<T: PoolTransaction> From<$name<T>> for Arc<ValidPoolTransaction<T>> {
472 fn from(value: $name<T>) -> Arc<ValidPoolTransaction<T>> {
473 value.0
474 }
475 }
476 };
477}
478
479#[derive(Debug)]
485pub struct BasefeeOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
486
487impl_ord_wrapper!(BasefeeOrd);
488
489impl<T: PoolTransaction> Ord for BasefeeOrd<T> {
490 fn cmp(&self, other: &Self) -> Ordering {
491 self.0.transaction.max_fee_per_gas().cmp(&other.0.transaction.max_fee_per_gas())
492 }
493}
494
495#[derive(Debug)]
505pub struct QueuedOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
506
507impl_ord_wrapper!(QueuedOrd);
508
509impl<T: PoolTransaction> Ord for QueuedOrd<T> {
511 fn cmp(&self, other: &Self) -> Ordering {
512 self.max_fee_per_gas().cmp(&self.max_fee_per_gas()).then_with(||
514 other.timestamp.cmp(&self.timestamp))
516 }
517}
518
519#[cfg(test)]
520mod tests {
521 use super::*;
522 use crate::test_utils::{MockTransaction, MockTransactionFactory, MockTransactionSet};
523 use alloy_primitives::address;
524 use reth_primitives::TxType;
525 use std::collections::HashSet;
526
527 #[test]
528 fn test_enforce_parked_basefee() {
529 let mut f = MockTransactionFactory::default();
530 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
531 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
532 pool.add_transaction(tx.clone());
533
534 assert!(pool.contains(tx.id()));
535 assert_eq!(pool.len(), 1);
536
537 let removed = pool.enforce_basefee(u64::MAX);
538 assert!(removed.is_empty());
539
540 let removed = pool.enforce_basefee((tx.max_fee_per_gas() - 1) as u64);
541 assert_eq!(removed.len(), 1);
542 assert!(pool.is_empty());
543 }
544
545 #[test]
546 fn test_enforce_parked_basefee_descendant() {
547 let mut f = MockTransactionFactory::default();
548 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
549 let t = MockTransaction::eip1559().inc_price_by(10);
550 let root_tx = f.validated_arc(t.clone());
551 pool.add_transaction(root_tx.clone());
552
553 let descendant_tx = f.validated_arc(t.inc_nonce().decr_price());
554 pool.add_transaction(descendant_tx.clone());
555
556 assert!(pool.contains(root_tx.id()));
557 assert!(pool.contains(descendant_tx.id()));
558 assert_eq!(pool.len(), 2);
559
560 let removed = pool.enforce_basefee(u64::MAX);
561 assert!(removed.is_empty());
562 assert_eq!(pool.len(), 2);
563 {
566 let mut pool2 = pool.clone();
568 let removed = pool2.enforce_basefee(root_tx.max_fee_per_gas() as u64);
569 assert_eq!(removed.len(), 1);
570 assert_eq!(pool2.len(), 1);
571 assert!(!pool2.contains(root_tx.id()));
573 assert!(pool2.contains(descendant_tx.id()));
574 }
575
576 let removed = pool.enforce_basefee(descendant_tx.max_fee_per_gas() as u64);
578 assert_eq!(removed.len(), 2);
579 assert!(pool.is_empty());
580 }
581
582 #[test]
583 fn truncate_parked_by_submission_id() {
584 let mut f = MockTransactionFactory::default();
586 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
587
588 let a_sender = address!("000000000000000000000000000000000000000a");
589 let b_sender = address!("000000000000000000000000000000000000000b");
590 let c_sender = address!("000000000000000000000000000000000000000c");
591 let d_sender = address!("000000000000000000000000000000000000000d");
592
593 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
595 let a = tx_set.clone().into_vec();
596
597 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
598 tx_set.extend(b.clone());
599
600 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
602 tx_set.extend(c.clone());
603
604 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
605 tx_set.extend(d.clone());
606
607 let all_txs = tx_set.into_vec();
608
609 let expected_parked = vec![c[0].clone(), c[1].clone(), c[2].clone(), d[0].clone()]
611 .into_iter()
612 .map(|tx| (tx.sender(), tx.nonce()))
613 .collect::<HashSet<_>>();
614
615 let expected_removed = vec![
619 a[0].clone(),
620 a[1].clone(),
621 a[2].clone(),
622 a[3].clone(),
623 b[0].clone(),
624 b[1].clone(),
625 b[2].clone(),
626 ]
627 .into_iter()
628 .map(|tx| (tx.sender(), tx.nonce()))
629 .collect::<HashSet<_>>();
630
631 for tx in all_txs {
633 pool.add_transaction(f.validated_arc(tx));
634 }
635
636 let pool_limit = SubPoolLimit { max_txs: 4, max_size: usize::MAX };
638
639 let removed = pool.truncate_pool(pool_limit);
641 assert_eq!(removed.len(), expected_removed.len());
642
643 let removed =
645 removed.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
646 assert_eq!(removed, expected_removed);
647
648 let parked = pool.all().collect::<Vec<_>>();
650 assert_eq!(parked.len(), expected_parked.len());
651
652 let parked = parked.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
654 assert_eq!(parked, expected_parked);
655 }
656
657 #[test]
658 fn test_truncate_parked_with_large_tx() {
659 let mut f = MockTransactionFactory::default();
660 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
661 let default_limits = SubPoolLimit::default();
662
663 let a_sender = address!("000000000000000000000000000000000000000a");
666
667 let a_txs = MockTransactionSet::dependent(a_sender, 0, 2, TxType::Eip1559)
669 .into_iter()
670 .map(|mut tx| {
671 tx.set_size(default_limits.max_size / 2 + 1);
672 tx
673 })
674 .collect::<Vec<_>>();
675
676 for tx in a_txs {
678 pool.add_transaction(f.validated_arc(tx));
679 }
680
681 let removed = pool.truncate_pool(default_limits);
683 assert_eq!(removed.len(), 1);
684 }
685
686 #[test]
687 fn test_senders_by_submission_id() {
688 let mut f = MockTransactionFactory::default();
690 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
691
692 let a_sender = address!("000000000000000000000000000000000000000a");
693 let b_sender = address!("000000000000000000000000000000000000000b");
694 let c_sender = address!("000000000000000000000000000000000000000c");
695 let d_sender = address!("000000000000000000000000000000000000000d");
696
697 let mut tx_set =
699 MockTransactionSet::dependent(a_sender, 0, 4, reth_primitives::TxType::Eip1559);
700 let a = tx_set.clone().into_vec();
701
702 let b = MockTransactionSet::dependent(b_sender, 0, 3, reth_primitives::TxType::Eip1559)
703 .into_vec();
704 tx_set.extend(b.clone());
705
706 let c = MockTransactionSet::dependent(c_sender, 0, 3, reth_primitives::TxType::Eip1559)
708 .into_vec();
709 tx_set.extend(c.clone());
710
711 let d = MockTransactionSet::dependent(d_sender, 0, 1, reth_primitives::TxType::Eip1559)
712 .into_vec();
713 tx_set.extend(d.clone());
714
715 let all_txs = tx_set.into_vec();
716
717 for tx in all_txs {
719 pool.add_transaction(f.validated_arc(tx));
720 }
721
722 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
724 assert_eq!(senders.len(), 4);
725 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
726 .into_iter()
727 .map(|s| f.ids.sender_id(&s).unwrap())
728 .collect::<Vec<_>>();
729 assert_eq!(senders, expected_senders);
730
731 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
733 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
734
735 for tx in all_txs {
737 pool.add_transaction(f.validated_arc(tx));
738 }
739
740 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
741 assert_eq!(senders.len(), 4);
742 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
743 .into_iter()
744 .map(|s| f.ids.sender_id(&s).unwrap())
745 .collect::<Vec<_>>();
746 assert_eq!(senders, expected_senders);
747 }
748
749 #[test]
750 fn test_add_sender_count_new_sender() {
751 let mut f = MockTransactionFactory::default();
753 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
755 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
757 pool.add_transaction(tx);
758
759 let sender: SenderId = 11.into();
761 let submission_id = 1;
762
763 pool.add_sender_count(sender, submission_id);
765
766 assert_eq!(pool.sender_transaction_count.len(), 2);
768 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
769 assert_eq!(sender_info.count, 1);
770 assert_eq!(sender_info.last_submission_id, submission_id);
771
772 assert_eq!(pool.last_sender_submission.len(), 2);
774 let submission_info = pool.last_sender_submission.iter().next().unwrap();
775 assert_eq!(submission_info.sender_id, sender);
776 assert_eq!(submission_info.submission_id, submission_id);
777 }
778
779 #[test]
780 fn test_add_sender_count_existing_sender() {
781 let mut f = MockTransactionFactory::default();
783 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
785 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
787 pool.add_transaction(tx);
788
789 let sender: SenderId = 11.into();
791 let initial_submission_id = 1;
792
793 pool.add_sender_count(sender, initial_submission_id);
795
796 let new_submission_id = 2;
798 pool.add_sender_count(sender, new_submission_id);
800
801 assert_eq!(pool.sender_transaction_count.len(), 2);
803 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
804 assert_eq!(sender_info.count, 2);
805 assert_eq!(sender_info.last_submission_id, new_submission_id);
806
807 assert_eq!(pool.last_sender_submission.len(), 2);
809 let submission_info = pool.last_sender_submission.iter().next().unwrap();
810 assert_eq!(submission_info.sender_id, sender);
811 assert_eq!(submission_info.submission_id, new_submission_id);
812 }
813
814 #[test]
815 fn test_add_sender_count_multiple_senders() {
816 let mut f = MockTransactionFactory::default();
818 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
820 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
822 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
823 pool.add_transaction(tx1);
824 pool.add_transaction(tx2);
825
826 let sender1: SenderId = 11.into();
828 let sender2: SenderId = 22.into();
829
830 pool.add_sender_count(sender1, 1);
832 pool.add_sender_count(sender2, 2);
833
834 assert_eq!(pool.sender_transaction_count.len(), 4);
836
837 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
838 assert_eq!(sender1_info.count, 1);
839 assert_eq!(sender1_info.last_submission_id, 1);
840
841 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
842 assert_eq!(sender2_info.count, 1);
843 assert_eq!(sender2_info.last_submission_id, 2);
844
845 assert_eq!(pool.last_sender_submission.len(), 3);
847
848 let submission_info1 =
850 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
851 assert!(submission_info1.is_none());
852
853 let submission_info2 =
855 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
856 assert_eq!(submission_info2.sender_id, sender2);
857 assert_eq!(submission_info2.submission_id, 2);
858 }
859
860 #[test]
861 fn test_remove_sender_count() {
862 let mut f = MockTransactionFactory::default();
864 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
866 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
868 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
869 pool.add_transaction(tx1);
870 pool.add_transaction(tx2);
871
872 let sender1: SenderId = 11.into();
874 let sender2: SenderId = 22.into();
875
876 pool.add_sender_count(sender1, 1);
878
879 pool.add_sender_count(sender2, 2);
881 pool.add_sender_count(sender2, 3);
882
883 assert_eq!(pool.sender_transaction_count.len(), 4);
885 assert!(pool.sender_transaction_count.contains_key(&sender1));
886
887 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
889
890 pool.remove_sender_count(sender1);
892
893 assert_eq!(pool.sender_transaction_count.len(), 3);
895 assert!(!pool.sender_transaction_count.contains_key(&sender1));
896
897 assert_eq!(
899 *pool.sender_transaction_count.get(&sender2).unwrap(),
900 SenderTransactionCount { count: 2, last_submission_id: 3 }
901 );
902
903 pool.remove_sender_count(sender2);
905
906 assert_eq!(pool.sender_transaction_count.len(), 3);
911 assert!(pool.sender_transaction_count.contains_key(&sender2));
912
913 assert_eq!(
915 *pool.sender_transaction_count.get(&sender2).unwrap(),
916 SenderTransactionCount { count: 1, last_submission_id: 3 }
917 );
918 }
919
920 #[test]
921 fn test_pool_size() {
922 let mut f = MockTransactionFactory::default();
923 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
924
925 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
927 pool.add_transaction(tx);
928
929 assert_eq!(pool.size(), 1024);
931 }
932
933 #[test]
934 fn test_pool_len() {
935 let mut f = MockTransactionFactory::default();
936 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
937
938 assert_eq!(pool.len(), 0);
940
941 let tx = f.validated_arc(MockTransaction::eip1559());
943 pool.add_transaction(tx);
944 assert_eq!(pool.len(), 1);
945 }
946
947 #[test]
948 fn test_pool_contains() {
949 let mut f = MockTransactionFactory::default();
950 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
951
952 let tx = f.validated_arc(MockTransaction::eip1559());
954 let tx_id = *tx.id();
955
956 assert!(!pool.contains(&tx_id));
958
959 pool.add_transaction(tx);
961 assert!(pool.contains(&tx_id));
962 }
963
964 #[test]
965 fn test_get_transaction() {
966 let mut f = MockTransactionFactory::default();
967 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
968
969 let tx = f.validated_arc(MockTransaction::eip1559());
971 let tx_id = *tx.id();
972 pool.add_transaction(tx.clone());
973
974 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
976 assert_eq!(retrieved.transaction.id(), tx.id());
977 }
978
979 #[test]
980 fn test_all_transactions() {
981 let mut f = MockTransactionFactory::default();
982 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
983
984 let tx1 = f.validated_arc(MockTransaction::eip1559());
986 let tx2 = f.validated_arc(MockTransaction::eip1559());
987 pool.add_transaction(tx1.clone());
988 pool.add_transaction(tx2.clone());
989
990 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
992 assert_eq!(all_txs.len(), 2);
993
994 assert!(all_txs.contains(tx1.id()));
996 assert!(all_txs.contains(tx2.id()));
997 }
998
999 #[test]
1000 fn test_truncate_pool_edge_case() {
1001 let mut f = MockTransactionFactory::default();
1002 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1003
1004 let tx1 = f.validated_arc(MockTransaction::eip1559());
1006 let tx2 = f.validated_arc(MockTransaction::eip1559());
1007 pool.add_transaction(tx1);
1008 pool.add_transaction(tx2);
1009
1010 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1012 let removed = pool.truncate_pool(limit);
1013
1014 assert!(removed.is_empty());
1016
1017 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1019 let removed = pool.truncate_pool(limit);
1020
1021 assert_eq!(removed.len(), 1);
1023 assert_eq!(pool.len(), 1);
1024 }
1025
1026 #[test]
1027 fn test_satisfy_base_fee_transactions() {
1028 let mut f = MockTransactionFactory::default();
1029 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1030
1031 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1033 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1034 pool.add_transaction(tx1);
1035 pool.add_transaction(tx2.clone());
1036
1037 let satisfied = pool.satisfy_base_fee_transactions(150);
1039 assert_eq!(satisfied.len(), 1);
1040 assert_eq!(satisfied[0].id(), tx2.id())
1041 }
1042
1043 #[test]
1044 fn test_remove_transaction() {
1045 let mut f = MockTransactionFactory::default();
1046 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1047
1048 let tx = f.validated_arc(MockTransaction::eip1559());
1050 let tx_id = *tx.id();
1051 pool.add_transaction(tx);
1052
1053 assert!(pool.contains(&tx_id));
1055
1056 let removed = pool.remove_transaction(&tx_id);
1058 assert!(removed.is_some());
1059 assert!(!pool.contains(&tx_id));
1060 }
1061}