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_consensus::{Transaction, TxType};
524 use alloy_primitives::address;
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!("0x000000000000000000000000000000000000000a");
589 let b_sender = address!("0x000000000000000000000000000000000000000b");
590 let c_sender = address!("0x000000000000000000000000000000000000000c");
591 let d_sender = address!("0x000000000000000000000000000000000000000d");
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!("0x000000000000000000000000000000000000000a");
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!("0x000000000000000000000000000000000000000a");
693 let b_sender = address!("0x000000000000000000000000000000000000000b");
694 let c_sender = address!("0x000000000000000000000000000000000000000c");
695 let d_sender = address!("0x000000000000000000000000000000000000000d");
696
697 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
699 let a = tx_set.clone().into_vec();
700
701 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
702 tx_set.extend(b.clone());
703
704 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
706 tx_set.extend(c.clone());
707
708 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
709 tx_set.extend(d.clone());
710
711 let all_txs = tx_set.into_vec();
712
713 for tx in all_txs {
715 pool.add_transaction(f.validated_arc(tx));
716 }
717
718 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
720 assert_eq!(senders.len(), 4);
721 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
722 .into_iter()
723 .map(|s| f.ids.sender_id(&s).unwrap())
724 .collect::<Vec<_>>();
725 assert_eq!(senders, expected_senders);
726
727 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
729 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
730
731 for tx in all_txs {
733 pool.add_transaction(f.validated_arc(tx));
734 }
735
736 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
737 assert_eq!(senders.len(), 4);
738 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
739 .into_iter()
740 .map(|s| f.ids.sender_id(&s).unwrap())
741 .collect::<Vec<_>>();
742 assert_eq!(senders, expected_senders);
743 }
744
745 #[test]
746 fn test_add_sender_count_new_sender() {
747 let mut f = MockTransactionFactory::default();
749 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
751 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
753 pool.add_transaction(tx);
754
755 let sender: SenderId = 11.into();
757 let submission_id = 1;
758
759 pool.add_sender_count(sender, submission_id);
761
762 assert_eq!(pool.sender_transaction_count.len(), 2);
764 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
765 assert_eq!(sender_info.count, 1);
766 assert_eq!(sender_info.last_submission_id, submission_id);
767
768 assert_eq!(pool.last_sender_submission.len(), 2);
770 let submission_info = pool.last_sender_submission.iter().next().unwrap();
771 assert_eq!(submission_info.sender_id, sender);
772 assert_eq!(submission_info.submission_id, submission_id);
773 }
774
775 #[test]
776 fn test_add_sender_count_existing_sender() {
777 let mut f = MockTransactionFactory::default();
779 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
781 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
783 pool.add_transaction(tx);
784
785 let sender: SenderId = 11.into();
787 let initial_submission_id = 1;
788
789 pool.add_sender_count(sender, initial_submission_id);
791
792 let new_submission_id = 2;
794 pool.add_sender_count(sender, new_submission_id);
796
797 assert_eq!(pool.sender_transaction_count.len(), 2);
799 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
800 assert_eq!(sender_info.count, 2);
801 assert_eq!(sender_info.last_submission_id, new_submission_id);
802
803 assert_eq!(pool.last_sender_submission.len(), 2);
805 let submission_info = pool.last_sender_submission.iter().next().unwrap();
806 assert_eq!(submission_info.sender_id, sender);
807 assert_eq!(submission_info.submission_id, new_submission_id);
808 }
809
810 #[test]
811 fn test_add_sender_count_multiple_senders() {
812 let mut f = MockTransactionFactory::default();
814 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
816 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
818 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
819 pool.add_transaction(tx1);
820 pool.add_transaction(tx2);
821
822 let sender1: SenderId = 11.into();
824 let sender2: SenderId = 22.into();
825
826 pool.add_sender_count(sender1, 1);
828 pool.add_sender_count(sender2, 2);
829
830 assert_eq!(pool.sender_transaction_count.len(), 4);
832
833 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
834 assert_eq!(sender1_info.count, 1);
835 assert_eq!(sender1_info.last_submission_id, 1);
836
837 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
838 assert_eq!(sender2_info.count, 1);
839 assert_eq!(sender2_info.last_submission_id, 2);
840
841 assert_eq!(pool.last_sender_submission.len(), 3);
843
844 let submission_info1 =
846 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
847 assert!(submission_info1.is_none());
848
849 let submission_info2 =
851 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
852 assert_eq!(submission_info2.sender_id, sender2);
853 assert_eq!(submission_info2.submission_id, 2);
854 }
855
856 #[test]
857 fn test_remove_sender_count() {
858 let mut f = MockTransactionFactory::default();
860 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
862 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
864 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
865 pool.add_transaction(tx1);
866 pool.add_transaction(tx2);
867
868 let sender1: SenderId = 11.into();
870 let sender2: SenderId = 22.into();
871
872 pool.add_sender_count(sender1, 1);
874
875 pool.add_sender_count(sender2, 2);
877 pool.add_sender_count(sender2, 3);
878
879 assert_eq!(pool.sender_transaction_count.len(), 4);
881 assert!(pool.sender_transaction_count.contains_key(&sender1));
882
883 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
885
886 pool.remove_sender_count(sender1);
888
889 assert_eq!(pool.sender_transaction_count.len(), 3);
891 assert!(!pool.sender_transaction_count.contains_key(&sender1));
892
893 assert_eq!(
895 *pool.sender_transaction_count.get(&sender2).unwrap(),
896 SenderTransactionCount { count: 2, last_submission_id: 3 }
897 );
898
899 pool.remove_sender_count(sender2);
901
902 assert_eq!(pool.sender_transaction_count.len(), 3);
907 assert!(pool.sender_transaction_count.contains_key(&sender2));
908
909 assert_eq!(
911 *pool.sender_transaction_count.get(&sender2).unwrap(),
912 SenderTransactionCount { count: 1, last_submission_id: 3 }
913 );
914 }
915
916 #[test]
917 fn test_pool_size() {
918 let mut f = MockTransactionFactory::default();
919 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
920
921 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
923 pool.add_transaction(tx);
924
925 assert_eq!(pool.size(), 1024);
927 }
928
929 #[test]
930 fn test_pool_len() {
931 let mut f = MockTransactionFactory::default();
932 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
933
934 assert_eq!(pool.len(), 0);
936
937 let tx = f.validated_arc(MockTransaction::eip1559());
939 pool.add_transaction(tx);
940 assert_eq!(pool.len(), 1);
941 }
942
943 #[test]
944 fn test_pool_contains() {
945 let mut f = MockTransactionFactory::default();
946 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
947
948 let tx = f.validated_arc(MockTransaction::eip1559());
950 let tx_id = *tx.id();
951
952 assert!(!pool.contains(&tx_id));
954
955 pool.add_transaction(tx);
957 assert!(pool.contains(&tx_id));
958 }
959
960 #[test]
961 fn test_get_transaction() {
962 let mut f = MockTransactionFactory::default();
963 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
964
965 let tx = f.validated_arc(MockTransaction::eip1559());
967 let tx_id = *tx.id();
968 pool.add_transaction(tx.clone());
969
970 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
972 assert_eq!(retrieved.transaction.id(), tx.id());
973 }
974
975 #[test]
976 fn test_all_transactions() {
977 let mut f = MockTransactionFactory::default();
978 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
979
980 let tx1 = f.validated_arc(MockTransaction::eip1559());
982 let tx2 = f.validated_arc(MockTransaction::eip1559());
983 pool.add_transaction(tx1.clone());
984 pool.add_transaction(tx2.clone());
985
986 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
988 assert_eq!(all_txs.len(), 2);
989
990 assert!(all_txs.contains(tx1.id()));
992 assert!(all_txs.contains(tx2.id()));
993 }
994
995 #[test]
996 fn test_truncate_pool_edge_case() {
997 let mut f = MockTransactionFactory::default();
998 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
999
1000 let tx1 = f.validated_arc(MockTransaction::eip1559());
1002 let tx2 = f.validated_arc(MockTransaction::eip1559());
1003 pool.add_transaction(tx1);
1004 pool.add_transaction(tx2);
1005
1006 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1008 let removed = pool.truncate_pool(limit);
1009
1010 assert!(removed.is_empty());
1012
1013 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1015 let removed = pool.truncate_pool(limit);
1016
1017 assert_eq!(removed.len(), 1);
1019 assert_eq!(pool.len(), 1);
1020 }
1021
1022 #[test]
1023 fn test_satisfy_base_fee_transactions() {
1024 let mut f = MockTransactionFactory::default();
1025 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1026
1027 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1029 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1030 pool.add_transaction(tx1);
1031 pool.add_transaction(tx2.clone());
1032
1033 let satisfied = pool.satisfy_base_fee_transactions(150);
1035 assert_eq!(satisfied.len(), 1);
1036 assert_eq!(satisfied[0].id(), tx2.id())
1037 }
1038
1039 #[test]
1040 fn test_remove_transaction() {
1041 let mut f = MockTransactionFactory::default();
1042 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1043
1044 let tx = f.validated_arc(MockTransaction::eip1559());
1046 let tx_id = *tx.id();
1047 pool.add_transaction(tx);
1048
1049 assert!(pool.contains(&tx_id));
1051
1052 let removed = pool.remove_transaction(&tx_id);
1054 assert!(removed.is_some());
1055 assert!(!pool.contains(&tx_id));
1056 }
1057}