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 const 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 pub(crate) fn is_empty(&self) -> bool {
244 self.by_id.is_empty()
245 }
246
247 pub(crate) fn contains(&self, id: &TransactionId) -> bool {
249 self.by_id.contains_key(id)
250 }
251
252 fn get(&self, id: &TransactionId) -> Option<&ParkedPoolTransaction<T>> {
254 self.by_id.get(id)
255 }
256
257 #[cfg(any(test, feature = "test-utils"))]
259 pub(crate) fn assert_invariants(&self) {
260 assert_eq!(self.by_id.len(), self.best.len(), "by_id.len() != best.len()");
261
262 assert_eq!(
263 self.last_sender_submission.len(),
264 self.sender_transaction_count.len(),
265 "last_sender_transaction.len() != sender_to_last_transaction.len()"
266 );
267 }
268}
269
270impl<T: PoolTransaction> ParkedPool<BasefeeOrd<T>> {
271 pub(crate) fn satisfy_base_fee_transactions(
275 &self,
276 basefee: u64,
277 ) -> Vec<Arc<ValidPoolTransaction<T>>> {
278 let ids = self.satisfy_base_fee_ids(basefee);
279 let mut txs = Vec::with_capacity(ids.len());
280 for id in ids {
281 txs.push(self.get(&id).expect("transaction exists").transaction.clone().into());
282 }
283 txs
284 }
285
286 fn satisfy_base_fee_ids(&self, basefee: u64) -> Vec<TransactionId> {
288 let mut transactions = Vec::new();
289 {
290 let mut iter = self.by_id.iter().peekable();
291
292 while let Some((id, tx)) = iter.next() {
293 if tx.transaction.transaction.max_fee_per_gas() < basefee as u128 {
294 'this: while let Some((peek, _)) = iter.peek() {
296 if peek.sender != id.sender {
297 break 'this
298 }
299 iter.next();
300 }
301 } else {
302 transactions.push(*id);
303 }
304 }
305 }
306 transactions
307 }
308
309 pub(crate) fn enforce_basefee(&mut self, basefee: u64) -> Vec<Arc<ValidPoolTransaction<T>>> {
314 let to_remove = self.satisfy_base_fee_ids(basefee);
315
316 let mut removed = Vec::with_capacity(to_remove.len());
317 for id in to_remove {
318 removed.push(self.remove_transaction(&id).expect("transaction exists"));
319 }
320
321 removed
322 }
323}
324
325impl<T: ParkedOrd> Default for ParkedPool<T> {
326 fn default() -> Self {
327 Self {
328 submission_id: 0,
329 by_id: Default::default(),
330 best: Default::default(),
331 last_sender_submission: Default::default(),
332 sender_transaction_count: Default::default(),
333 size_of: Default::default(),
334 }
335 }
336}
337
338#[derive(Debug, Clone, Default, PartialEq, Eq)]
340struct SenderTransactionCount {
341 count: u64,
342 last_submission_id: u64,
343}
344
345#[derive(Debug)]
347struct ParkedPoolTransaction<T: ParkedOrd> {
348 submission_id: u64,
350 transaction: T,
352}
353
354impl<T: ParkedOrd> Clone for ParkedPoolTransaction<T> {
355 fn clone(&self) -> Self {
356 Self { submission_id: self.submission_id, transaction: self.transaction.clone() }
357 }
358}
359
360impl<T: ParkedOrd> Eq for ParkedPoolTransaction<T> {}
361
362impl<T: ParkedOrd> PartialEq<Self> for ParkedPoolTransaction<T> {
363 fn eq(&self, other: &Self) -> bool {
364 self.cmp(other) == Ordering::Equal
365 }
366}
367
368impl<T: ParkedOrd> PartialOrd<Self> for ParkedPoolTransaction<T> {
369 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
370 Some(self.cmp(other))
371 }
372}
373
374impl<T: ParkedOrd> Ord for ParkedPoolTransaction<T> {
375 fn cmp(&self, other: &Self) -> Ordering {
376 self.transaction
380 .cmp(&other.transaction)
381 .then_with(|| other.submission_id.cmp(&self.submission_id))
382 }
383}
384
385#[derive(Debug, PartialEq, Eq, Copy, Clone)]
388pub(crate) struct SubmissionSenderId {
389 pub(crate) sender_id: SenderId,
391 pub(crate) submission_id: u64,
393}
394
395impl SubmissionSenderId {
396 const fn new(sender_id: SenderId, submission_id: u64) -> Self {
398 Self { sender_id, submission_id }
399 }
400}
401
402impl Ord for SubmissionSenderId {
403 fn cmp(&self, other: &Self) -> Ordering {
404 other.submission_id.cmp(&self.submission_id)
406 }
407}
408
409impl PartialOrd for SubmissionSenderId {
410 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
411 Some(self.cmp(other))
412 }
413}
414
415pub trait ParkedOrd:
419 Ord
420 + Clone
421 + From<Arc<ValidPoolTransaction<Self::Transaction>>>
422 + Into<Arc<ValidPoolTransaction<Self::Transaction>>>
423 + Deref<Target = Arc<ValidPoolTransaction<Self::Transaction>>>
424{
425 type Transaction: PoolTransaction;
427}
428
429macro_rules! impl_ord_wrapper {
431 ($name:ident) => {
432 impl<T: PoolTransaction> Clone for $name<T> {
433 fn clone(&self) -> Self {
434 Self(self.0.clone())
435 }
436 }
437
438 impl<T: PoolTransaction> Eq for $name<T> {}
439
440 impl<T: PoolTransaction> PartialEq<Self> for $name<T> {
441 fn eq(&self, other: &Self) -> bool {
442 self.cmp(other) == Ordering::Equal
443 }
444 }
445
446 impl<T: PoolTransaction> PartialOrd<Self> for $name<T> {
447 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
448 Some(self.cmp(other))
449 }
450 }
451 impl<T: PoolTransaction> Deref for $name<T> {
452 type Target = Arc<ValidPoolTransaction<T>>;
453
454 fn deref(&self) -> &Self::Target {
455 &self.0
456 }
457 }
458
459 impl<T: PoolTransaction> ParkedOrd for $name<T> {
460 type Transaction = T;
461 }
462
463 impl<T: PoolTransaction> From<Arc<ValidPoolTransaction<T>>> for $name<T> {
464 fn from(value: Arc<ValidPoolTransaction<T>>) -> Self {
465 Self(value)
466 }
467 }
468
469 impl<T: PoolTransaction> From<$name<T>> for Arc<ValidPoolTransaction<T>> {
470 fn from(value: $name<T>) -> Arc<ValidPoolTransaction<T>> {
471 value.0
472 }
473 }
474 };
475}
476
477#[derive(Debug)]
483pub struct BasefeeOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
484
485impl_ord_wrapper!(BasefeeOrd);
486
487impl<T: PoolTransaction> Ord for BasefeeOrd<T> {
488 fn cmp(&self, other: &Self) -> Ordering {
489 self.0.transaction.max_fee_per_gas().cmp(&other.0.transaction.max_fee_per_gas())
490 }
491}
492
493#[derive(Debug)]
503pub struct QueuedOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
504
505impl_ord_wrapper!(QueuedOrd);
506
507impl<T: PoolTransaction> Ord for QueuedOrd<T> {
509 fn cmp(&self, other: &Self) -> Ordering {
510 self.max_fee_per_gas().cmp(&self.max_fee_per_gas()).then_with(||
512 other.timestamp.cmp(&self.timestamp))
514 }
515}
516
517#[cfg(test)]
518mod tests {
519 use super::*;
520 use crate::test_utils::{MockTransaction, MockTransactionFactory, MockTransactionSet};
521 use alloy_consensus::{Transaction, TxType};
522 use alloy_primitives::address;
523 use std::collections::HashSet;
524
525 #[test]
526 fn test_enforce_parked_basefee() {
527 let mut f = MockTransactionFactory::default();
528 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
529 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
530 pool.add_transaction(tx.clone());
531
532 assert!(pool.contains(tx.id()));
533 assert_eq!(pool.len(), 1);
534
535 let removed = pool.enforce_basefee(u64::MAX);
536 assert!(removed.is_empty());
537
538 let removed = pool.enforce_basefee((tx.max_fee_per_gas() - 1) as u64);
539 assert_eq!(removed.len(), 1);
540 assert!(pool.is_empty());
541 }
542
543 #[test]
544 fn test_enforce_parked_basefee_descendant() {
545 let mut f = MockTransactionFactory::default();
546 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
547 let t = MockTransaction::eip1559().inc_price_by(10);
548 let root_tx = f.validated_arc(t.clone());
549 pool.add_transaction(root_tx.clone());
550
551 let descendant_tx = f.validated_arc(t.inc_nonce().decr_price());
552 pool.add_transaction(descendant_tx.clone());
553
554 assert!(pool.contains(root_tx.id()));
555 assert!(pool.contains(descendant_tx.id()));
556 assert_eq!(pool.len(), 2);
557
558 let removed = pool.enforce_basefee(u64::MAX);
559 assert!(removed.is_empty());
560 assert_eq!(pool.len(), 2);
561 {
564 let mut pool2 = pool.clone();
566 let removed = pool2.enforce_basefee(root_tx.max_fee_per_gas() as u64);
567 assert_eq!(removed.len(), 1);
568 assert_eq!(pool2.len(), 1);
569 assert!(!pool2.contains(root_tx.id()));
571 assert!(pool2.contains(descendant_tx.id()));
572 }
573
574 let removed = pool.enforce_basefee(descendant_tx.max_fee_per_gas() as u64);
576 assert_eq!(removed.len(), 2);
577 assert!(pool.is_empty());
578 }
579
580 #[test]
581 fn truncate_parked_by_submission_id() {
582 let mut f = MockTransactionFactory::default();
584 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
585
586 let a_sender = address!("0x000000000000000000000000000000000000000a");
587 let b_sender = address!("0x000000000000000000000000000000000000000b");
588 let c_sender = address!("0x000000000000000000000000000000000000000c");
589 let d_sender = address!("0x000000000000000000000000000000000000000d");
590
591 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
593 let a = tx_set.clone().into_vec();
594
595 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
596 tx_set.extend(b.clone());
597
598 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
600 tx_set.extend(c.clone());
601
602 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
603 tx_set.extend(d.clone());
604
605 let all_txs = tx_set.into_vec();
606
607 let expected_parked = vec![c[0].clone(), c[1].clone(), c[2].clone(), d[0].clone()]
609 .into_iter()
610 .map(|tx| (tx.sender(), tx.nonce()))
611 .collect::<HashSet<_>>();
612
613 let expected_removed = vec![
617 a[0].clone(),
618 a[1].clone(),
619 a[2].clone(),
620 a[3].clone(),
621 b[0].clone(),
622 b[1].clone(),
623 b[2].clone(),
624 ]
625 .into_iter()
626 .map(|tx| (tx.sender(), tx.nonce()))
627 .collect::<HashSet<_>>();
628
629 for tx in all_txs {
631 pool.add_transaction(f.validated_arc(tx));
632 }
633
634 let pool_limit = SubPoolLimit { max_txs: 4, max_size: usize::MAX };
636
637 let removed = pool.truncate_pool(pool_limit);
639 assert_eq!(removed.len(), expected_removed.len());
640
641 let removed =
643 removed.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
644 assert_eq!(removed, expected_removed);
645
646 let parked = pool.all().collect::<Vec<_>>();
648 assert_eq!(parked.len(), expected_parked.len());
649
650 let parked = parked.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
652 assert_eq!(parked, expected_parked);
653 }
654
655 #[test]
656 fn test_truncate_parked_with_large_tx() {
657 let mut f = MockTransactionFactory::default();
658 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
659 let default_limits = SubPoolLimit::default();
660
661 let a_sender = address!("0x000000000000000000000000000000000000000a");
664
665 let a_txs = MockTransactionSet::dependent(a_sender, 0, 2, TxType::Eip1559)
667 .into_iter()
668 .map(|mut tx| {
669 tx.set_size(default_limits.max_size / 2 + 1);
670 tx
671 })
672 .collect::<Vec<_>>();
673
674 for tx in a_txs {
676 pool.add_transaction(f.validated_arc(tx));
677 }
678
679 let removed = pool.truncate_pool(default_limits);
681 assert_eq!(removed.len(), 1);
682 }
683
684 #[test]
685 fn test_senders_by_submission_id() {
686 let mut f = MockTransactionFactory::default();
688 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
689
690 let a_sender = address!("0x000000000000000000000000000000000000000a");
691 let b_sender = address!("0x000000000000000000000000000000000000000b");
692 let c_sender = address!("0x000000000000000000000000000000000000000c");
693 let d_sender = address!("0x000000000000000000000000000000000000000d");
694
695 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
697 let a = tx_set.clone().into_vec();
698
699 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
700 tx_set.extend(b.clone());
701
702 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
704 tx_set.extend(c.clone());
705
706 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
707 tx_set.extend(d.clone());
708
709 let all_txs = tx_set.into_vec();
710
711 for tx in all_txs {
713 pool.add_transaction(f.validated_arc(tx));
714 }
715
716 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
718 assert_eq!(senders.len(), 4);
719 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
720 .into_iter()
721 .map(|s| f.ids.sender_id(&s).unwrap())
722 .collect::<Vec<_>>();
723 assert_eq!(senders, expected_senders);
724
725 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
727 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
728
729 for tx in all_txs {
731 pool.add_transaction(f.validated_arc(tx));
732 }
733
734 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
735 assert_eq!(senders.len(), 4);
736 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
737 .into_iter()
738 .map(|s| f.ids.sender_id(&s).unwrap())
739 .collect::<Vec<_>>();
740 assert_eq!(senders, expected_senders);
741 }
742
743 #[test]
744 fn test_add_sender_count_new_sender() {
745 let mut f = MockTransactionFactory::default();
747 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
749 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
751 pool.add_transaction(tx);
752
753 let sender: SenderId = 11.into();
755 let submission_id = 1;
756
757 pool.add_sender_count(sender, submission_id);
759
760 assert_eq!(pool.sender_transaction_count.len(), 2);
762 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
763 assert_eq!(sender_info.count, 1);
764 assert_eq!(sender_info.last_submission_id, submission_id);
765
766 assert_eq!(pool.last_sender_submission.len(), 2);
768 let submission_info = pool.last_sender_submission.iter().next().unwrap();
769 assert_eq!(submission_info.sender_id, sender);
770 assert_eq!(submission_info.submission_id, submission_id);
771 }
772
773 #[test]
774 fn test_add_sender_count_existing_sender() {
775 let mut f = MockTransactionFactory::default();
777 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
779 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
781 pool.add_transaction(tx);
782
783 let sender: SenderId = 11.into();
785 let initial_submission_id = 1;
786
787 pool.add_sender_count(sender, initial_submission_id);
789
790 let new_submission_id = 2;
792 pool.add_sender_count(sender, new_submission_id);
794
795 assert_eq!(pool.sender_transaction_count.len(), 2);
797 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
798 assert_eq!(sender_info.count, 2);
799 assert_eq!(sender_info.last_submission_id, new_submission_id);
800
801 assert_eq!(pool.last_sender_submission.len(), 2);
803 let submission_info = pool.last_sender_submission.iter().next().unwrap();
804 assert_eq!(submission_info.sender_id, sender);
805 assert_eq!(submission_info.submission_id, new_submission_id);
806 }
807
808 #[test]
809 fn test_add_sender_count_multiple_senders() {
810 let mut f = MockTransactionFactory::default();
812 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
814 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
816 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
817 pool.add_transaction(tx1);
818 pool.add_transaction(tx2);
819
820 let sender1: SenderId = 11.into();
822 let sender2: SenderId = 22.into();
823
824 pool.add_sender_count(sender1, 1);
826 pool.add_sender_count(sender2, 2);
827
828 assert_eq!(pool.sender_transaction_count.len(), 4);
830
831 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
832 assert_eq!(sender1_info.count, 1);
833 assert_eq!(sender1_info.last_submission_id, 1);
834
835 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
836 assert_eq!(sender2_info.count, 1);
837 assert_eq!(sender2_info.last_submission_id, 2);
838
839 assert_eq!(pool.last_sender_submission.len(), 3);
841
842 let submission_info1 =
844 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
845 assert!(submission_info1.is_none());
846
847 let submission_info2 =
849 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
850 assert_eq!(submission_info2.sender_id, sender2);
851 assert_eq!(submission_info2.submission_id, 2);
852 }
853
854 #[test]
855 fn test_remove_sender_count() {
856 let mut f = MockTransactionFactory::default();
858 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
860 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
862 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
863 pool.add_transaction(tx1);
864 pool.add_transaction(tx2);
865
866 let sender1: SenderId = 11.into();
868 let sender2: SenderId = 22.into();
869
870 pool.add_sender_count(sender1, 1);
872
873 pool.add_sender_count(sender2, 2);
875 pool.add_sender_count(sender2, 3);
876
877 assert_eq!(pool.sender_transaction_count.len(), 4);
879 assert!(pool.sender_transaction_count.contains_key(&sender1));
880
881 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
883
884 pool.remove_sender_count(sender1);
886
887 assert_eq!(pool.sender_transaction_count.len(), 3);
889 assert!(!pool.sender_transaction_count.contains_key(&sender1));
890
891 assert_eq!(
893 *pool.sender_transaction_count.get(&sender2).unwrap(),
894 SenderTransactionCount { count: 2, last_submission_id: 3 }
895 );
896
897 pool.remove_sender_count(sender2);
899
900 assert_eq!(pool.sender_transaction_count.len(), 3);
905 assert!(pool.sender_transaction_count.contains_key(&sender2));
906
907 assert_eq!(
909 *pool.sender_transaction_count.get(&sender2).unwrap(),
910 SenderTransactionCount { count: 1, last_submission_id: 3 }
911 );
912 }
913
914 #[test]
915 fn test_pool_size() {
916 let mut f = MockTransactionFactory::default();
917 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
918
919 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
921 pool.add_transaction(tx);
922
923 assert_eq!(pool.size(), 1024);
925 }
926
927 #[test]
928 fn test_pool_len() {
929 let mut f = MockTransactionFactory::default();
930 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
931
932 assert_eq!(pool.len(), 0);
934
935 let tx = f.validated_arc(MockTransaction::eip1559());
937 pool.add_transaction(tx);
938 assert_eq!(pool.len(), 1);
939 }
940
941 #[test]
942 fn test_pool_contains() {
943 let mut f = MockTransactionFactory::default();
944 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
945
946 let tx = f.validated_arc(MockTransaction::eip1559());
948 let tx_id = *tx.id();
949
950 assert!(!pool.contains(&tx_id));
952
953 pool.add_transaction(tx);
955 assert!(pool.contains(&tx_id));
956 }
957
958 #[test]
959 fn test_get_transaction() {
960 let mut f = MockTransactionFactory::default();
961 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
962
963 let tx = f.validated_arc(MockTransaction::eip1559());
965 let tx_id = *tx.id();
966 pool.add_transaction(tx.clone());
967
968 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
970 assert_eq!(retrieved.transaction.id(), tx.id());
971 }
972
973 #[test]
974 fn test_all_transactions() {
975 let mut f = MockTransactionFactory::default();
976 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
977
978 let tx1 = f.validated_arc(MockTransaction::eip1559());
980 let tx2 = f.validated_arc(MockTransaction::eip1559());
981 pool.add_transaction(tx1.clone());
982 pool.add_transaction(tx2.clone());
983
984 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
986 assert_eq!(all_txs.len(), 2);
987
988 assert!(all_txs.contains(tx1.id()));
990 assert!(all_txs.contains(tx2.id()));
991 }
992
993 #[test]
994 fn test_truncate_pool_edge_case() {
995 let mut f = MockTransactionFactory::default();
996 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
997
998 let tx1 = f.validated_arc(MockTransaction::eip1559());
1000 let tx2 = f.validated_arc(MockTransaction::eip1559());
1001 pool.add_transaction(tx1);
1002 pool.add_transaction(tx2);
1003
1004 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1006 let removed = pool.truncate_pool(limit);
1007
1008 assert!(removed.is_empty());
1010
1011 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1013 let removed = pool.truncate_pool(limit);
1014
1015 assert_eq!(removed.len(), 1);
1017 assert_eq!(pool.len(), 1);
1018 }
1019
1020 #[test]
1021 fn test_satisfy_base_fee_transactions() {
1022 let mut f = MockTransactionFactory::default();
1023 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1024
1025 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1027 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1028 pool.add_transaction(tx1);
1029 pool.add_transaction(tx2.clone());
1030
1031 let satisfied = pool.satisfy_base_fee_transactions(150);
1033 assert_eq!(satisfied.len(), 1);
1034 assert_eq!(satisfied[0].id(), tx2.id())
1035 }
1036
1037 #[test]
1038 fn test_remove_transaction() {
1039 let mut f = MockTransactionFactory::default();
1040 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1041
1042 let tx = f.validated_arc(MockTransaction::eip1559());
1044 let tx_id = *tx.id();
1045 pool.add_transaction(tx);
1046
1047 assert!(pool.contains(&tx_id));
1049
1050 let removed = pool.remove_transaction(&tx_id);
1052 assert!(removed.is_some());
1053 assert!(!pool.contains(&tx_id));
1054 }
1055}