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 pub(crate) fn txs_by_sender(
156 &self,
157 sender: SenderId,
158 ) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
159 self.by_id
160 .range((sender.start_bound(), Unbounded))
161 .take_while(move |(other, _)| sender == other.sender)
162 .map(|(_, tx)| Arc::clone(&tx.transaction))
163 .collect()
164 }
165
166 #[cfg(test)]
167 pub(crate) fn get_senders_by_submission_id(
168 &self,
169 ) -> impl Iterator<Item = SubmissionSenderId> + '_ {
170 self.last_sender_submission.iter().copied()
171 }
172
173 pub fn truncate_pool(
187 &mut self,
188 limit: SubPoolLimit,
189 ) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
190 if !self.exceeds(&limit) {
191 return Vec::new()
193 }
194
195 let mut removed = Vec::with_capacity(limit.tx_excess(self.len()).unwrap_or(1));
196
197 while !self.last_sender_submission.is_empty() && limit.is_exceeded(self.len(), self.size())
198 {
199 let sender_id = self.last_sender_submission.last().unwrap().sender_id;
201
202 while let Some((tx_id, _)) = self.by_id.range(sender_id.range()).next_back() {
204 let tx_id = *tx_id;
205 if let Some(tx) = self.remove_transaction(&tx_id) {
206 removed.push(tx);
207 }
208
209 if !self.exceeds(&limit) {
210 break
211 }
212 }
213 }
214
215 removed
216 }
217
218 const fn next_id(&mut self) -> u64 {
219 let id = self.submission_id;
220 self.submission_id = self.submission_id.wrapping_add(1);
221 id
222 }
223
224 pub(crate) fn size(&self) -> usize {
226 self.size_of.into()
227 }
228
229 pub(crate) fn len(&self) -> usize {
231 self.by_id.len()
232 }
233
234 #[inline]
236 pub(crate) fn exceeds(&self, limit: &SubPoolLimit) -> bool {
237 limit.is_exceeded(self.len(), self.size())
238 }
239
240 #[cfg(test)]
242 pub(crate) fn is_empty(&self) -> bool {
243 self.by_id.is_empty()
244 }
245
246 pub(crate) fn contains(&self, id: &TransactionId) -> bool {
248 self.by_id.contains_key(id)
249 }
250
251 fn get(&self, id: &TransactionId) -> Option<&ParkedPoolTransaction<T>> {
253 self.by_id.get(id)
254 }
255
256 #[cfg(any(test, feature = "test-utils"))]
258 pub(crate) fn assert_invariants(&self) {
259 assert_eq!(
260 self.last_sender_submission.len(),
261 self.sender_transaction_count.len(),
262 "last_sender_submission.len() != sender_transaction_count.len()"
263 );
264 }
265}
266
267impl<T: PoolTransaction> ParkedPool<BasefeeOrd<T>> {
268 pub(crate) fn satisfy_base_fee_transactions(
272 &self,
273 basefee: u64,
274 ) -> Vec<Arc<ValidPoolTransaction<T>>> {
275 let mut txs = Vec::new();
276 self.satisfy_base_fee_ids(basefee as u128, |tx| {
277 txs.push(tx.clone());
278 });
279 txs
280 }
281
282 fn satisfy_base_fee_ids<F>(&self, basefee: u128, mut tx_handler: F)
284 where
285 F: FnMut(&Arc<ValidPoolTransaction<T>>),
286 {
287 let mut iter = self.by_id.iter().peekable();
288
289 while let Some((id, tx)) = iter.next() {
290 if tx.transaction.max_fee_per_gas() < basefee {
291 'this: while let Some((peek, _)) = iter.peek() {
293 if peek.sender != id.sender {
294 break 'this
295 }
296 iter.next();
297 }
298 } else {
299 tx_handler(&tx.transaction);
300 }
301 }
302 }
303
304 pub(crate) fn enforce_basefee_with<F>(&mut self, basefee: u64, mut tx_handler: F)
316 where
317 F: FnMut(Arc<ValidPoolTransaction<T>>),
318 {
319 let mut to_remove = Vec::new();
320 self.satisfy_base_fee_ids(basefee as u128, |tx| {
321 to_remove.push(*tx.id());
322 });
323
324 for id in to_remove {
325 if let Some(tx) = self.remove_transaction(&id) {
326 tx_handler(tx);
327 }
328 }
329 }
330
331 #[cfg(test)]
339 pub(crate) fn enforce_basefee(&mut self, basefee: u64) -> Vec<Arc<ValidPoolTransaction<T>>> {
340 let mut removed = Vec::new();
341 self.enforce_basefee_with(basefee, |tx| {
342 removed.push(tx);
343 });
344 removed
345 }
346}
347
348impl<T: ParkedOrd> Default for ParkedPool<T> {
349 fn default() -> Self {
350 Self {
351 submission_id: 0,
352 by_id: Default::default(),
353 last_sender_submission: Default::default(),
354 sender_transaction_count: Default::default(),
355 size_of: Default::default(),
356 }
357 }
358}
359
360#[derive(Debug, Clone, Default, PartialEq, Eq)]
362struct SenderTransactionCount {
363 count: u64,
364 last_submission_id: u64,
365}
366
367#[derive(Debug)]
369struct ParkedPoolTransaction<T: ParkedOrd> {
370 submission_id: u64,
372 transaction: T,
374}
375
376impl<T: ParkedOrd> Clone for ParkedPoolTransaction<T> {
377 fn clone(&self) -> Self {
378 Self { submission_id: self.submission_id, transaction: self.transaction.clone() }
379 }
380}
381
382impl<T: ParkedOrd> Eq for ParkedPoolTransaction<T> {}
383
384impl<T: ParkedOrd> PartialEq<Self> for ParkedPoolTransaction<T> {
385 fn eq(&self, other: &Self) -> bool {
386 self.cmp(other) == Ordering::Equal
387 }
388}
389
390impl<T: ParkedOrd> PartialOrd<Self> for ParkedPoolTransaction<T> {
391 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
392 Some(self.cmp(other))
393 }
394}
395
396impl<T: ParkedOrd> Ord for ParkedPoolTransaction<T> {
397 fn cmp(&self, other: &Self) -> Ordering {
398 self.transaction
402 .cmp(&other.transaction)
403 .then_with(|| other.submission_id.cmp(&self.submission_id))
404 }
405}
406
407#[derive(Debug, PartialEq, Eq, Copy, Clone)]
410pub(crate) struct SubmissionSenderId {
411 pub(crate) sender_id: SenderId,
413 pub(crate) submission_id: u64,
415}
416
417impl SubmissionSenderId {
418 const fn new(sender_id: SenderId, submission_id: u64) -> Self {
420 Self { sender_id, submission_id }
421 }
422}
423
424impl Ord for SubmissionSenderId {
425 fn cmp(&self, other: &Self) -> Ordering {
426 other.submission_id.cmp(&self.submission_id)
428 }
429}
430
431impl PartialOrd for SubmissionSenderId {
432 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
433 Some(self.cmp(other))
434 }
435}
436
437pub trait ParkedOrd:
441 Ord
442 + Clone
443 + From<Arc<ValidPoolTransaction<Self::Transaction>>>
444 + Into<Arc<ValidPoolTransaction<Self::Transaction>>>
445 + Deref<Target = Arc<ValidPoolTransaction<Self::Transaction>>>
446{
447 type Transaction: PoolTransaction;
449}
450
451macro_rules! impl_ord_wrapper {
453 ($name:ident) => {
454 impl<T: PoolTransaction> Clone for $name<T> {
455 fn clone(&self) -> Self {
456 Self(self.0.clone())
457 }
458 }
459
460 impl<T: PoolTransaction> Eq for $name<T> {}
461
462 impl<T: PoolTransaction> PartialEq<Self> for $name<T> {
463 fn eq(&self, other: &Self) -> bool {
464 self.cmp(other) == Ordering::Equal
465 }
466 }
467
468 impl<T: PoolTransaction> PartialOrd<Self> for $name<T> {
469 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
470 Some(self.cmp(other))
471 }
472 }
473 impl<T: PoolTransaction> Deref for $name<T> {
474 type Target = Arc<ValidPoolTransaction<T>>;
475
476 fn deref(&self) -> &Self::Target {
477 &self.0
478 }
479 }
480
481 impl<T: PoolTransaction> ParkedOrd for $name<T> {
482 type Transaction = T;
483 }
484
485 impl<T: PoolTransaction> From<Arc<ValidPoolTransaction<T>>> for $name<T> {
486 fn from(value: Arc<ValidPoolTransaction<T>>) -> Self {
487 Self(value)
488 }
489 }
490
491 impl<T: PoolTransaction> From<$name<T>> for Arc<ValidPoolTransaction<T>> {
492 fn from(value: $name<T>) -> Arc<ValidPoolTransaction<T>> {
493 value.0
494 }
495 }
496 };
497}
498
499#[derive(Debug)]
505pub struct BasefeeOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
506
507impl_ord_wrapper!(BasefeeOrd);
508
509impl<T: PoolTransaction> Ord for BasefeeOrd<T> {
510 fn cmp(&self, other: &Self) -> Ordering {
511 self.0.transaction.max_fee_per_gas().cmp(&other.0.transaction.max_fee_per_gas())
512 }
513}
514
515#[derive(Debug)]
525pub struct QueuedOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
526
527impl_ord_wrapper!(QueuedOrd);
528
529impl<T: PoolTransaction> Ord for QueuedOrd<T> {
530 fn cmp(&self, other: &Self) -> Ordering {
531 self.max_fee_per_gas().cmp(&other.max_fee_per_gas()).then_with(||
533 other.timestamp.cmp(&self.timestamp))
535 }
536}
537
538#[cfg(test)]
539mod tests {
540 use super::*;
541 use crate::test_utils::{MockTransaction, MockTransactionFactory, MockTransactionSet};
542 use alloy_consensus::{Transaction, TxType};
543 use alloy_primitives::address;
544 use std::collections::HashSet;
545
546 #[test]
547 fn test_enforce_parked_basefee() {
548 let mut f = MockTransactionFactory::default();
549 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
550 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
551 pool.add_transaction(tx.clone());
552
553 assert!(pool.contains(tx.id()));
554 assert_eq!(pool.len(), 1);
555
556 let removed = pool.enforce_basefee(u64::MAX);
557 assert!(removed.is_empty());
558
559 let removed = pool.enforce_basefee((tx.max_fee_per_gas() - 1) as u64);
560 assert_eq!(removed.len(), 1);
561 assert!(pool.is_empty());
562 }
563
564 #[test]
565 fn test_enforce_parked_basefee_descendant() {
566 let mut f = MockTransactionFactory::default();
567 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
568 let t = MockTransaction::eip1559().inc_price_by(10);
569 let root_tx = f.validated_arc(t.clone());
570 pool.add_transaction(root_tx.clone());
571
572 let descendant_tx = f.validated_arc(t.inc_nonce().decr_price());
573 pool.add_transaction(descendant_tx.clone());
574
575 assert!(pool.contains(root_tx.id()));
576 assert!(pool.contains(descendant_tx.id()));
577 assert_eq!(pool.len(), 2);
578
579 let removed = pool.enforce_basefee(u64::MAX);
580 assert!(removed.is_empty());
581 assert_eq!(pool.len(), 2);
582 {
585 let mut pool2 = pool.clone();
587 let removed = pool2.enforce_basefee(root_tx.max_fee_per_gas() as u64);
588 assert_eq!(removed.len(), 1);
589 assert_eq!(pool2.len(), 1);
590 assert!(!pool2.contains(root_tx.id()));
592 assert!(pool2.contains(descendant_tx.id()));
593 }
594
595 let removed = pool.enforce_basefee(descendant_tx.max_fee_per_gas() as u64);
597 assert_eq!(removed.len(), 2);
598 assert!(pool.is_empty());
599 }
600
601 #[test]
602 fn truncate_parked_by_submission_id() {
603 let mut f = MockTransactionFactory::default();
605 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
606
607 let a_sender = address!("0x000000000000000000000000000000000000000a");
608 let b_sender = address!("0x000000000000000000000000000000000000000b");
609 let c_sender = address!("0x000000000000000000000000000000000000000c");
610 let d_sender = address!("0x000000000000000000000000000000000000000d");
611
612 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
614 let a = tx_set.clone().into_vec();
615
616 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
617 tx_set.extend(b.clone());
618
619 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
621 tx_set.extend(c.clone());
622
623 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
624 tx_set.extend(d.clone());
625
626 let all_txs = tx_set.into_vec();
627
628 let expected_parked = vec![c[0].clone(), c[1].clone(), c[2].clone(), d[0].clone()]
630 .into_iter()
631 .map(|tx| (tx.sender(), tx.nonce()))
632 .collect::<HashSet<_>>();
633
634 let expected_removed = vec![
638 a[0].clone(),
639 a[1].clone(),
640 a[2].clone(),
641 a[3].clone(),
642 b[0].clone(),
643 b[1].clone(),
644 b[2].clone(),
645 ]
646 .into_iter()
647 .map(|tx| (tx.sender(), tx.nonce()))
648 .collect::<HashSet<_>>();
649
650 for tx in all_txs {
652 pool.add_transaction(f.validated_arc(tx));
653 }
654
655 let pool_limit = SubPoolLimit { max_txs: 4, max_size: usize::MAX };
657
658 let removed = pool.truncate_pool(pool_limit);
660 assert_eq!(removed.len(), expected_removed.len());
661
662 let removed =
664 removed.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
665 assert_eq!(removed, expected_removed);
666
667 let parked = pool.all().collect::<Vec<_>>();
669 assert_eq!(parked.len(), expected_parked.len());
670
671 let parked = parked.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
673 assert_eq!(parked, expected_parked);
674 }
675
676 #[test]
677 fn test_truncate_parked_with_large_tx() {
678 let mut f = MockTransactionFactory::default();
679 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
680 let default_limits = SubPoolLimit::default();
681
682 let a_sender = address!("0x000000000000000000000000000000000000000a");
685
686 let a_txs = MockTransactionSet::dependent(a_sender, 0, 2, TxType::Eip1559)
688 .into_iter()
689 .map(|mut tx| {
690 tx.set_size(default_limits.max_size / 2 + 1);
691 tx
692 })
693 .collect::<Vec<_>>();
694
695 for tx in a_txs {
697 pool.add_transaction(f.validated_arc(tx));
698 }
699
700 let removed = pool.truncate_pool(default_limits);
702 assert_eq!(removed.len(), 1);
703 }
704
705 #[test]
706 fn test_senders_by_submission_id() {
707 let mut f = MockTransactionFactory::default();
709 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
710
711 let a_sender = address!("0x000000000000000000000000000000000000000a");
712 let b_sender = address!("0x000000000000000000000000000000000000000b");
713 let c_sender = address!("0x000000000000000000000000000000000000000c");
714 let d_sender = address!("0x000000000000000000000000000000000000000d");
715
716 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
718 let a = tx_set.clone().into_vec();
719
720 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
721 tx_set.extend(b.clone());
722
723 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
725 tx_set.extend(c.clone());
726
727 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
728 tx_set.extend(d.clone());
729
730 let all_txs = tx_set.into_vec();
731
732 for tx in all_txs {
734 pool.add_transaction(f.validated_arc(tx));
735 }
736
737 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
739 assert_eq!(senders.len(), 4);
740 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
741 .into_iter()
742 .map(|s| f.ids.sender_id(&s).unwrap())
743 .collect::<Vec<_>>();
744 assert_eq!(senders, expected_senders);
745
746 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
748 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
749
750 for tx in all_txs {
752 pool.add_transaction(f.validated_arc(tx));
753 }
754
755 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
756 assert_eq!(senders.len(), 4);
757 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
758 .into_iter()
759 .map(|s| f.ids.sender_id(&s).unwrap())
760 .collect::<Vec<_>>();
761 assert_eq!(senders, expected_senders);
762 }
763
764 #[test]
765 fn test_add_sender_count_new_sender() {
766 let mut f = MockTransactionFactory::default();
768 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
770 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
772 pool.add_transaction(tx);
773
774 let sender: SenderId = 11.into();
776 let submission_id = 1;
777
778 pool.add_sender_count(sender, submission_id);
780
781 assert_eq!(pool.sender_transaction_count.len(), 2);
783 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
784 assert_eq!(sender_info.count, 1);
785 assert_eq!(sender_info.last_submission_id, submission_id);
786
787 assert_eq!(pool.last_sender_submission.len(), 2);
789 let submission_info = pool.last_sender_submission.iter().next().unwrap();
790 assert_eq!(submission_info.sender_id, sender);
791 assert_eq!(submission_info.submission_id, submission_id);
792 }
793
794 #[test]
795 fn test_add_sender_count_existing_sender() {
796 let mut f = MockTransactionFactory::default();
798 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
800 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
802 pool.add_transaction(tx);
803
804 let sender: SenderId = 11.into();
806 let initial_submission_id = 1;
807
808 pool.add_sender_count(sender, initial_submission_id);
810
811 let new_submission_id = 2;
813 pool.add_sender_count(sender, new_submission_id);
815
816 assert_eq!(pool.sender_transaction_count.len(), 2);
818 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
819 assert_eq!(sender_info.count, 2);
820 assert_eq!(sender_info.last_submission_id, new_submission_id);
821
822 assert_eq!(pool.last_sender_submission.len(), 2);
824 let submission_info = pool.last_sender_submission.iter().next().unwrap();
825 assert_eq!(submission_info.sender_id, sender);
826 assert_eq!(submission_info.submission_id, new_submission_id);
827 }
828
829 #[test]
830 fn test_add_sender_count_multiple_senders() {
831 let mut f = MockTransactionFactory::default();
833 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
835 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
837 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
838 pool.add_transaction(tx1);
839 pool.add_transaction(tx2);
840
841 let sender1: SenderId = 11.into();
843 let sender2: SenderId = 22.into();
844
845 pool.add_sender_count(sender1, 1);
847 pool.add_sender_count(sender2, 2);
848
849 assert_eq!(pool.sender_transaction_count.len(), 4);
851
852 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
853 assert_eq!(sender1_info.count, 1);
854 assert_eq!(sender1_info.last_submission_id, 1);
855
856 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
857 assert_eq!(sender2_info.count, 1);
858 assert_eq!(sender2_info.last_submission_id, 2);
859
860 assert_eq!(pool.last_sender_submission.len(), 3);
862
863 let submission_info1 =
865 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
866 assert!(submission_info1.is_none());
867
868 let submission_info2 =
870 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
871 assert_eq!(submission_info2.sender_id, sender2);
872 assert_eq!(submission_info2.submission_id, 2);
873 }
874
875 #[test]
876 fn test_remove_sender_count() {
877 let mut f = MockTransactionFactory::default();
879 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
881 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
883 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
884 pool.add_transaction(tx1);
885 pool.add_transaction(tx2);
886
887 let sender1: SenderId = 11.into();
889 let sender2: SenderId = 22.into();
890
891 pool.add_sender_count(sender1, 1);
893
894 pool.add_sender_count(sender2, 2);
896 pool.add_sender_count(sender2, 3);
897
898 assert_eq!(pool.sender_transaction_count.len(), 4);
900 assert!(pool.sender_transaction_count.contains_key(&sender1));
901
902 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
904
905 pool.remove_sender_count(sender1);
907
908 assert_eq!(pool.sender_transaction_count.len(), 3);
910 assert!(!pool.sender_transaction_count.contains_key(&sender1));
911
912 assert_eq!(
914 *pool.sender_transaction_count.get(&sender2).unwrap(),
915 SenderTransactionCount { count: 2, last_submission_id: 3 }
916 );
917
918 pool.remove_sender_count(sender2);
920
921 assert_eq!(pool.sender_transaction_count.len(), 3);
926 assert!(pool.sender_transaction_count.contains_key(&sender2));
927
928 assert_eq!(
930 *pool.sender_transaction_count.get(&sender2).unwrap(),
931 SenderTransactionCount { count: 1, last_submission_id: 3 }
932 );
933 }
934
935 #[test]
936 fn test_pool_size() {
937 let mut f = MockTransactionFactory::default();
938 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
939
940 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
942 pool.add_transaction(tx);
943
944 assert_eq!(pool.size(), 1024);
946 }
947
948 #[test]
949 fn test_pool_len() {
950 let mut f = MockTransactionFactory::default();
951 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
952
953 assert_eq!(pool.len(), 0);
955
956 let tx = f.validated_arc(MockTransaction::eip1559());
958 pool.add_transaction(tx);
959 assert_eq!(pool.len(), 1);
960 }
961
962 #[test]
963 fn test_pool_contains() {
964 let mut f = MockTransactionFactory::default();
965 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
966
967 let tx = f.validated_arc(MockTransaction::eip1559());
969 let tx_id = *tx.id();
970
971 assert!(!pool.contains(&tx_id));
973
974 pool.add_transaction(tx);
976 assert!(pool.contains(&tx_id));
977 }
978
979 #[test]
980 fn test_get_transaction() {
981 let mut f = MockTransactionFactory::default();
982 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
983
984 let tx = f.validated_arc(MockTransaction::eip1559());
986 let tx_id = *tx.id();
987 pool.add_transaction(tx.clone());
988
989 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
991 assert_eq!(retrieved.transaction.id(), tx.id());
992 }
993
994 #[test]
995 fn test_all_transactions() {
996 let mut f = MockTransactionFactory::default();
997 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
998
999 let tx1 = f.validated_arc(MockTransaction::eip1559());
1001 let tx2 = f.validated_arc(MockTransaction::eip1559());
1002 pool.add_transaction(tx1.clone());
1003 pool.add_transaction(tx2.clone());
1004
1005 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
1007 assert_eq!(all_txs.len(), 2);
1008
1009 assert!(all_txs.contains(tx1.id()));
1011 assert!(all_txs.contains(tx2.id()));
1012 }
1013
1014 #[test]
1015 fn test_truncate_pool_edge_case() {
1016 let mut f = MockTransactionFactory::default();
1017 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1018
1019 let tx1 = f.validated_arc(MockTransaction::eip1559());
1021 let tx2 = f.validated_arc(MockTransaction::eip1559());
1022 pool.add_transaction(tx1);
1023 pool.add_transaction(tx2);
1024
1025 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1027 let removed = pool.truncate_pool(limit);
1028
1029 assert!(removed.is_empty());
1031
1032 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1034 let removed = pool.truncate_pool(limit);
1035
1036 assert_eq!(removed.len(), 1);
1038 assert_eq!(pool.len(), 1);
1039 }
1040
1041 #[test]
1042 fn test_satisfy_base_fee_transactions() {
1043 let mut f = MockTransactionFactory::default();
1044 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1045
1046 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1048 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1049 pool.add_transaction(tx1);
1050 pool.add_transaction(tx2.clone());
1051
1052 let satisfied = pool.satisfy_base_fee_transactions(150);
1054 assert_eq!(satisfied.len(), 1);
1055 assert_eq!(satisfied[0].id(), tx2.id())
1056 }
1057
1058 #[test]
1059 fn test_remove_transaction() {
1060 let mut f = MockTransactionFactory::default();
1061 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1062
1063 let tx = f.validated_arc(MockTransaction::eip1559());
1065 let tx_id = *tx.id();
1066 pool.add_transaction(tx);
1067
1068 assert!(pool.contains(&tx_id));
1070
1071 let removed = pool.remove_transaction(&tx_id);
1073 assert!(removed.is_some());
1074 assert!(!pool.contains(&tx_id));
1075 }
1076
1077 #[test]
1078 fn test_enforce_basefee_with_handler_zero_allocation() {
1079 let mut f = MockTransactionFactory::default();
1080 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1081
1082 let sender_a = address!("0x000000000000000000000000000000000000000a");
1084 let sender_b = address!("0x000000000000000000000000000000000000000b");
1085
1086 let txs = vec![
1090 f.validated_arc(
1091 MockTransaction::eip1559()
1092 .set_sender(sender_a)
1093 .set_nonce(0)
1094 .set_max_fee(500)
1095 .clone(),
1096 ),
1097 f.validated_arc(
1098 MockTransaction::eip1559()
1099 .set_sender(sender_a)
1100 .set_nonce(1)
1101 .set_max_fee(600)
1102 .clone(),
1103 ),
1104 f.validated_arc(
1105 MockTransaction::eip1559()
1106 .set_sender(sender_b)
1107 .set_nonce(0)
1108 .set_max_fee(300)
1109 .clone(),
1110 ),
1111 ];
1112
1113 let expected_affordable = vec![txs[0].clone(), txs[1].clone()]; for tx in txs {
1115 pool.add_transaction(tx);
1116 }
1117
1118 let mut processed_txs = Vec::new();
1120 let mut handler_call_count = 0;
1121
1122 pool.enforce_basefee_with(400, |tx| {
1123 processed_txs.push(tx);
1124 handler_call_count += 1;
1125 });
1126
1127 assert_eq!(handler_call_count, 2);
1129 assert_eq!(processed_txs.len(), 2);
1130
1131 let processed_ids: Vec<_> = processed_txs.iter().map(|tx| *tx.id()).collect();
1133 for expected_tx in expected_affordable {
1134 assert!(processed_ids.contains(expected_tx.id()));
1135 }
1136
1137 assert_eq!(pool.len(), 1); }
1140}