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>>) {
52 let id = *tx.id();
53 assert!(
54 !self.contains(&id),
55 "transaction already included {:?}",
56 self.get(&id).unwrap().transaction.transaction
57 );
58 let submission_id = self.next_id();
59
60 self.size_of += tx.size();
62
63 self.add_sender_count(tx.sender_id(), submission_id);
65 let transaction = ParkedPoolTransaction { submission_id, transaction: tx.into() };
66
67 self.by_id.insert(id, transaction);
68 }
69
70 fn add_sender_count(&mut self, sender: SenderId, submission_id: u64) {
73 match self.sender_transaction_count.entry(sender) {
74 Entry::Occupied(mut entry) => {
75 let value = entry.get_mut();
76 self.last_sender_submission
78 .remove(&SubmissionSenderId::new(sender, value.last_submission_id));
79
80 value.count += 1;
81 value.last_submission_id = submission_id;
82 }
83 Entry::Vacant(entry) => {
84 entry
85 .insert(SenderTransactionCount { count: 1, last_submission_id: submission_id });
86 }
87 }
88 self.last_sender_submission.insert(SubmissionSenderId::new(sender, submission_id));
90 }
91
92 fn remove_sender_count(&mut self, sender_id: SenderId) {
99 let removed_sender = match self.sender_transaction_count.entry(sender_id) {
100 Entry::Occupied(mut entry) => {
101 let value = entry.get_mut();
102 value.count -= 1;
103 if value.count == 0 {
104 entry.remove()
105 } else {
106 return
107 }
108 }
109 Entry::Vacant(_) => {
110 unreachable!("sender count not found {:?}", sender_id);
112 }
113 };
114
115 assert!(
117 self.last_sender_submission
118 .remove(&SubmissionSenderId::new(sender_id, removed_sender.last_submission_id)),
119 "last sender transaction not found {sender_id:?}"
120 );
121 }
122
123 pub(crate) fn all(
125 &self,
126 ) -> impl ExactSizeIterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
127 self.by_id.values().map(|tx| tx.transaction.clone().into())
128 }
129
130 pub(crate) fn remove_transaction(
132 &mut self,
133 id: &TransactionId,
134 ) -> Option<Arc<ValidPoolTransaction<T::Transaction>>> {
135 let tx = self.by_id.remove(id)?;
137 self.remove_sender_count(tx.transaction.sender_id());
138
139 self.size_of -= tx.transaction.size();
141
142 Some(tx.transaction.into())
143 }
144
145 pub(crate) fn get_txs_by_sender(
148 &self,
149 sender: SenderId,
150 ) -> SmallVec<[TransactionId; TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER]> {
151 self.by_id
152 .range((sender.start_bound(), Unbounded))
153 .take_while(move |(other, _)| sender == other.sender)
154 .map(|(tx_id, _)| *tx_id)
155 .collect()
156 }
157
158 #[cfg(test)]
159 pub(crate) fn get_senders_by_submission_id(
160 &self,
161 ) -> impl Iterator<Item = SubmissionSenderId> + '_ {
162 self.last_sender_submission.iter().copied()
163 }
164
165 pub fn truncate_pool(
179 &mut self,
180 limit: SubPoolLimit,
181 ) -> Vec<Arc<ValidPoolTransaction<T::Transaction>>> {
182 if !self.exceeds(&limit) {
183 return Vec::new()
185 }
186
187 let mut removed = Vec::new();
188
189 while !self.last_sender_submission.is_empty() && limit.is_exceeded(self.len(), self.size())
190 {
191 let sender_id = self.last_sender_submission.last().unwrap().sender_id;
193 let list = self.get_txs_by_sender(sender_id);
194
195 for txid in list.into_iter().rev() {
197 if let Some(tx) = self.remove_transaction(&txid) {
198 removed.push(tx);
199 }
200
201 if !self.exceeds(&limit) {
202 break
203 }
204 }
205 }
206
207 removed
208 }
209
210 const fn next_id(&mut self) -> u64 {
211 let id = self.submission_id;
212 self.submission_id = self.submission_id.wrapping_add(1);
213 id
214 }
215
216 pub(crate) fn size(&self) -> usize {
218 self.size_of.into()
219 }
220
221 pub(crate) fn len(&self) -> usize {
223 self.by_id.len()
224 }
225
226 #[inline]
228 pub(crate) fn exceeds(&self, limit: &SubPoolLimit) -> bool {
229 limit.is_exceeded(self.len(), self.size())
230 }
231
232 #[cfg(test)]
234 pub(crate) fn is_empty(&self) -> bool {
235 self.by_id.is_empty()
236 }
237
238 pub(crate) fn contains(&self, id: &TransactionId) -> bool {
240 self.by_id.contains_key(id)
241 }
242
243 fn get(&self, id: &TransactionId) -> Option<&ParkedPoolTransaction<T>> {
245 self.by_id.get(id)
246 }
247
248 #[cfg(any(test, feature = "test-utils"))]
250 pub(crate) fn assert_invariants(&self) {
251 assert_eq!(
252 self.last_sender_submission.len(),
253 self.sender_transaction_count.len(),
254 "last_sender_transaction.len() != sender_to_last_transaction.len()"
255 );
256 }
257}
258
259impl<T: PoolTransaction> ParkedPool<BasefeeOrd<T>> {
260 pub(crate) fn satisfy_base_fee_transactions(
264 &self,
265 basefee: u64,
266 ) -> Vec<Arc<ValidPoolTransaction<T>>> {
267 let ids = self.satisfy_base_fee_ids(basefee as u128);
268 let mut txs = Vec::with_capacity(ids.len());
269 for id in ids {
270 txs.push(self.get(&id).expect("transaction exists").transaction.clone().into());
271 }
272 txs
273 }
274
275 fn satisfy_base_fee_ids(&self, basefee: u128) -> Vec<TransactionId> {
277 let mut transactions = Vec::new();
278 {
279 let mut iter = self.by_id.iter().peekable();
280
281 while let Some((id, tx)) = iter.next() {
282 if tx.transaction.transaction.max_fee_per_gas() < basefee {
283 'this: while let Some((peek, _)) = iter.peek() {
285 if peek.sender != id.sender {
286 break 'this
287 }
288 iter.next();
289 }
290 } else {
291 transactions.push(*id);
292 }
293 }
294 }
295 transactions
296 }
297
298 pub(crate) fn enforce_basefee_with<F>(&mut self, basefee: u64, mut tx_handler: F)
310 where
311 F: FnMut(Arc<ValidPoolTransaction<T>>),
312 {
313 let to_remove = self.satisfy_base_fee_ids(basefee as u128);
314
315 for id in to_remove {
316 if let Some(tx) = self.remove_transaction(&id) {
317 tx_handler(tx);
318 }
319 }
320 }
321
322 #[cfg(test)]
330 pub(crate) fn enforce_basefee(&mut self, basefee: u64) -> Vec<Arc<ValidPoolTransaction<T>>> {
331 let mut removed = Vec::new();
332 self.enforce_basefee_with(basefee, |tx| {
333 removed.push(tx);
334 });
335 removed
336 }
337}
338
339impl<T: ParkedOrd> Default for ParkedPool<T> {
340 fn default() -> Self {
341 Self {
342 submission_id: 0,
343 by_id: Default::default(),
344 last_sender_submission: Default::default(),
345 sender_transaction_count: Default::default(),
346 size_of: Default::default(),
347 }
348 }
349}
350
351#[derive(Debug, Clone, Default, PartialEq, Eq)]
353struct SenderTransactionCount {
354 count: u64,
355 last_submission_id: u64,
356}
357
358#[derive(Debug)]
360struct ParkedPoolTransaction<T: ParkedOrd> {
361 submission_id: u64,
363 transaction: T,
365}
366
367impl<T: ParkedOrd> Clone for ParkedPoolTransaction<T> {
368 fn clone(&self) -> Self {
369 Self { submission_id: self.submission_id, transaction: self.transaction.clone() }
370 }
371}
372
373impl<T: ParkedOrd> Eq for ParkedPoolTransaction<T> {}
374
375impl<T: ParkedOrd> PartialEq<Self> for ParkedPoolTransaction<T> {
376 fn eq(&self, other: &Self) -> bool {
377 self.cmp(other) == Ordering::Equal
378 }
379}
380
381impl<T: ParkedOrd> PartialOrd<Self> for ParkedPoolTransaction<T> {
382 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
383 Some(self.cmp(other))
384 }
385}
386
387impl<T: ParkedOrd> Ord for ParkedPoolTransaction<T> {
388 fn cmp(&self, other: &Self) -> Ordering {
389 self.transaction
393 .cmp(&other.transaction)
394 .then_with(|| other.submission_id.cmp(&self.submission_id))
395 }
396}
397
398#[derive(Debug, PartialEq, Eq, Copy, Clone)]
401pub(crate) struct SubmissionSenderId {
402 pub(crate) sender_id: SenderId,
404 pub(crate) submission_id: u64,
406}
407
408impl SubmissionSenderId {
409 const fn new(sender_id: SenderId, submission_id: u64) -> Self {
411 Self { sender_id, submission_id }
412 }
413}
414
415impl Ord for SubmissionSenderId {
416 fn cmp(&self, other: &Self) -> Ordering {
417 other.submission_id.cmp(&self.submission_id)
419 }
420}
421
422impl PartialOrd for SubmissionSenderId {
423 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
424 Some(self.cmp(other))
425 }
426}
427
428pub trait ParkedOrd:
432 Ord
433 + Clone
434 + From<Arc<ValidPoolTransaction<Self::Transaction>>>
435 + Into<Arc<ValidPoolTransaction<Self::Transaction>>>
436 + Deref<Target = Arc<ValidPoolTransaction<Self::Transaction>>>
437{
438 type Transaction: PoolTransaction;
440}
441
442macro_rules! impl_ord_wrapper {
444 ($name:ident) => {
445 impl<T: PoolTransaction> Clone for $name<T> {
446 fn clone(&self) -> Self {
447 Self(self.0.clone())
448 }
449 }
450
451 impl<T: PoolTransaction> Eq for $name<T> {}
452
453 impl<T: PoolTransaction> PartialEq<Self> for $name<T> {
454 fn eq(&self, other: &Self) -> bool {
455 self.cmp(other) == Ordering::Equal
456 }
457 }
458
459 impl<T: PoolTransaction> PartialOrd<Self> for $name<T> {
460 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
461 Some(self.cmp(other))
462 }
463 }
464 impl<T: PoolTransaction> Deref for $name<T> {
465 type Target = Arc<ValidPoolTransaction<T>>;
466
467 fn deref(&self) -> &Self::Target {
468 &self.0
469 }
470 }
471
472 impl<T: PoolTransaction> ParkedOrd for $name<T> {
473 type Transaction = T;
474 }
475
476 impl<T: PoolTransaction> From<Arc<ValidPoolTransaction<T>>> for $name<T> {
477 fn from(value: Arc<ValidPoolTransaction<T>>) -> Self {
478 Self(value)
479 }
480 }
481
482 impl<T: PoolTransaction> From<$name<T>> for Arc<ValidPoolTransaction<T>> {
483 fn from(value: $name<T>) -> Arc<ValidPoolTransaction<T>> {
484 value.0
485 }
486 }
487 };
488}
489
490#[derive(Debug)]
496pub struct BasefeeOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
497
498impl_ord_wrapper!(BasefeeOrd);
499
500impl<T: PoolTransaction> Ord for BasefeeOrd<T> {
501 fn cmp(&self, other: &Self) -> Ordering {
502 self.0.transaction.max_fee_per_gas().cmp(&other.0.transaction.max_fee_per_gas())
503 }
504}
505
506#[derive(Debug)]
516pub struct QueuedOrd<T: PoolTransaction>(Arc<ValidPoolTransaction<T>>);
517
518impl_ord_wrapper!(QueuedOrd);
519
520impl<T: PoolTransaction> Ord for QueuedOrd<T> {
521 fn cmp(&self, other: &Self) -> Ordering {
522 self.max_fee_per_gas().cmp(&other.max_fee_per_gas()).then_with(||
524 other.timestamp.cmp(&self.timestamp))
526 }
527}
528
529#[cfg(test)]
530mod tests {
531 use super::*;
532 use crate::test_utils::{MockTransaction, MockTransactionFactory, MockTransactionSet};
533 use alloy_consensus::{Transaction, TxType};
534 use alloy_primitives::address;
535 use std::collections::HashSet;
536
537 #[test]
538 fn test_enforce_parked_basefee() {
539 let mut f = MockTransactionFactory::default();
540 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
541 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
542 pool.add_transaction(tx.clone());
543
544 assert!(pool.contains(tx.id()));
545 assert_eq!(pool.len(), 1);
546
547 let removed = pool.enforce_basefee(u64::MAX);
548 assert!(removed.is_empty());
549
550 let removed = pool.enforce_basefee((tx.max_fee_per_gas() - 1) as u64);
551 assert_eq!(removed.len(), 1);
552 assert!(pool.is_empty());
553 }
554
555 #[test]
556 fn test_enforce_parked_basefee_descendant() {
557 let mut f = MockTransactionFactory::default();
558 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
559 let t = MockTransaction::eip1559().inc_price_by(10);
560 let root_tx = f.validated_arc(t.clone());
561 pool.add_transaction(root_tx.clone());
562
563 let descendant_tx = f.validated_arc(t.inc_nonce().decr_price());
564 pool.add_transaction(descendant_tx.clone());
565
566 assert!(pool.contains(root_tx.id()));
567 assert!(pool.contains(descendant_tx.id()));
568 assert_eq!(pool.len(), 2);
569
570 let removed = pool.enforce_basefee(u64::MAX);
571 assert!(removed.is_empty());
572 assert_eq!(pool.len(), 2);
573 {
576 let mut pool2 = pool.clone();
578 let removed = pool2.enforce_basefee(root_tx.max_fee_per_gas() as u64);
579 assert_eq!(removed.len(), 1);
580 assert_eq!(pool2.len(), 1);
581 assert!(!pool2.contains(root_tx.id()));
583 assert!(pool2.contains(descendant_tx.id()));
584 }
585
586 let removed = pool.enforce_basefee(descendant_tx.max_fee_per_gas() as u64);
588 assert_eq!(removed.len(), 2);
589 assert!(pool.is_empty());
590 }
591
592 #[test]
593 fn truncate_parked_by_submission_id() {
594 let mut f = MockTransactionFactory::default();
596 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
597
598 let a_sender = address!("0x000000000000000000000000000000000000000a");
599 let b_sender = address!("0x000000000000000000000000000000000000000b");
600 let c_sender = address!("0x000000000000000000000000000000000000000c");
601 let d_sender = address!("0x000000000000000000000000000000000000000d");
602
603 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
605 let a = tx_set.clone().into_vec();
606
607 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
608 tx_set.extend(b.clone());
609
610 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
612 tx_set.extend(c.clone());
613
614 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
615 tx_set.extend(d.clone());
616
617 let all_txs = tx_set.into_vec();
618
619 let expected_parked = vec![c[0].clone(), c[1].clone(), c[2].clone(), d[0].clone()]
621 .into_iter()
622 .map(|tx| (tx.sender(), tx.nonce()))
623 .collect::<HashSet<_>>();
624
625 let expected_removed = vec![
629 a[0].clone(),
630 a[1].clone(),
631 a[2].clone(),
632 a[3].clone(),
633 b[0].clone(),
634 b[1].clone(),
635 b[2].clone(),
636 ]
637 .into_iter()
638 .map(|tx| (tx.sender(), tx.nonce()))
639 .collect::<HashSet<_>>();
640
641 for tx in all_txs {
643 pool.add_transaction(f.validated_arc(tx));
644 }
645
646 let pool_limit = SubPoolLimit { max_txs: 4, max_size: usize::MAX };
648
649 let removed = pool.truncate_pool(pool_limit);
651 assert_eq!(removed.len(), expected_removed.len());
652
653 let removed =
655 removed.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
656 assert_eq!(removed, expected_removed);
657
658 let parked = pool.all().collect::<Vec<_>>();
660 assert_eq!(parked.len(), expected_parked.len());
661
662 let parked = parked.into_iter().map(|tx| (tx.sender(), tx.nonce())).collect::<HashSet<_>>();
664 assert_eq!(parked, expected_parked);
665 }
666
667 #[test]
668 fn test_truncate_parked_with_large_tx() {
669 let mut f = MockTransactionFactory::default();
670 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
671 let default_limits = SubPoolLimit::default();
672
673 let a_sender = address!("0x000000000000000000000000000000000000000a");
676
677 let a_txs = MockTransactionSet::dependent(a_sender, 0, 2, TxType::Eip1559)
679 .into_iter()
680 .map(|mut tx| {
681 tx.set_size(default_limits.max_size / 2 + 1);
682 tx
683 })
684 .collect::<Vec<_>>();
685
686 for tx in a_txs {
688 pool.add_transaction(f.validated_arc(tx));
689 }
690
691 let removed = pool.truncate_pool(default_limits);
693 assert_eq!(removed.len(), 1);
694 }
695
696 #[test]
697 fn test_senders_by_submission_id() {
698 let mut f = MockTransactionFactory::default();
700 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
701
702 let a_sender = address!("0x000000000000000000000000000000000000000a");
703 let b_sender = address!("0x000000000000000000000000000000000000000b");
704 let c_sender = address!("0x000000000000000000000000000000000000000c");
705 let d_sender = address!("0x000000000000000000000000000000000000000d");
706
707 let mut tx_set = MockTransactionSet::dependent(a_sender, 0, 4, TxType::Eip1559);
709 let a = tx_set.clone().into_vec();
710
711 let b = MockTransactionSet::dependent(b_sender, 0, 3, TxType::Eip1559).into_vec();
712 tx_set.extend(b.clone());
713
714 let c = MockTransactionSet::dependent(c_sender, 0, 3, TxType::Eip1559).into_vec();
716 tx_set.extend(c.clone());
717
718 let d = MockTransactionSet::dependent(d_sender, 0, 1, TxType::Eip1559).into_vec();
719 tx_set.extend(d.clone());
720
721 let all_txs = tx_set.into_vec();
722
723 for tx in all_txs {
725 pool.add_transaction(f.validated_arc(tx));
726 }
727
728 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
730 assert_eq!(senders.len(), 4);
731 let expected_senders = vec![d_sender, c_sender, b_sender, a_sender]
732 .into_iter()
733 .map(|s| f.ids.sender_id(&s).unwrap())
734 .collect::<Vec<_>>();
735 assert_eq!(senders, expected_senders);
736
737 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
739 let all_txs = vec![d[0].clone(), b[0].clone(), c[0].clone(), a[0].clone()];
740
741 for tx in all_txs {
743 pool.add_transaction(f.validated_arc(tx));
744 }
745
746 let senders = pool.get_senders_by_submission_id().map(|s| s.sender_id).collect::<Vec<_>>();
747 assert_eq!(senders.len(), 4);
748 let expected_senders = vec![a_sender, c_sender, b_sender, d_sender]
749 .into_iter()
750 .map(|s| f.ids.sender_id(&s).unwrap())
751 .collect::<Vec<_>>();
752 assert_eq!(senders, expected_senders);
753 }
754
755 #[test]
756 fn test_add_sender_count_new_sender() {
757 let mut f = MockTransactionFactory::default();
759 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
761 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
763 pool.add_transaction(tx);
764
765 let sender: SenderId = 11.into();
767 let submission_id = 1;
768
769 pool.add_sender_count(sender, submission_id);
771
772 assert_eq!(pool.sender_transaction_count.len(), 2);
774 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
775 assert_eq!(sender_info.count, 1);
776 assert_eq!(sender_info.last_submission_id, submission_id);
777
778 assert_eq!(pool.last_sender_submission.len(), 2);
780 let submission_info = pool.last_sender_submission.iter().next().unwrap();
781 assert_eq!(submission_info.sender_id, sender);
782 assert_eq!(submission_info.submission_id, submission_id);
783 }
784
785 #[test]
786 fn test_add_sender_count_existing_sender() {
787 let mut f = MockTransactionFactory::default();
789 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
791 let tx = f.validated_arc(MockTransaction::eip1559().inc_price());
793 pool.add_transaction(tx);
794
795 let sender: SenderId = 11.into();
797 let initial_submission_id = 1;
798
799 pool.add_sender_count(sender, initial_submission_id);
801
802 let new_submission_id = 2;
804 pool.add_sender_count(sender, new_submission_id);
806
807 assert_eq!(pool.sender_transaction_count.len(), 2);
809 let sender_info = pool.sender_transaction_count.get(&sender).unwrap();
810 assert_eq!(sender_info.count, 2);
811 assert_eq!(sender_info.last_submission_id, new_submission_id);
812
813 assert_eq!(pool.last_sender_submission.len(), 2);
815 let submission_info = pool.last_sender_submission.iter().next().unwrap();
816 assert_eq!(submission_info.sender_id, sender);
817 assert_eq!(submission_info.submission_id, new_submission_id);
818 }
819
820 #[test]
821 fn test_add_sender_count_multiple_senders() {
822 let mut f = MockTransactionFactory::default();
824 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
826 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
828 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
829 pool.add_transaction(tx1);
830 pool.add_transaction(tx2);
831
832 let sender1: SenderId = 11.into();
834 let sender2: SenderId = 22.into();
835
836 pool.add_sender_count(sender1, 1);
838 pool.add_sender_count(sender2, 2);
839
840 assert_eq!(pool.sender_transaction_count.len(), 4);
842
843 let sender1_info = pool.sender_transaction_count.get(&sender1).unwrap();
844 assert_eq!(sender1_info.count, 1);
845 assert_eq!(sender1_info.last_submission_id, 1);
846
847 let sender2_info = pool.sender_transaction_count.get(&sender2).unwrap();
848 assert_eq!(sender2_info.count, 1);
849 assert_eq!(sender2_info.last_submission_id, 2);
850
851 assert_eq!(pool.last_sender_submission.len(), 3);
853
854 let submission_info1 =
856 pool.last_sender_submission.iter().find(|info| info.sender_id == sender1);
857 assert!(submission_info1.is_none());
858
859 let submission_info2 =
861 pool.last_sender_submission.iter().find(|info| info.sender_id == sender2).unwrap();
862 assert_eq!(submission_info2.sender_id, sender2);
863 assert_eq!(submission_info2.submission_id, 2);
864 }
865
866 #[test]
867 fn test_remove_sender_count() {
868 let mut f = MockTransactionFactory::default();
870 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
872 let tx1 = f.validated_arc(MockTransaction::eip1559().inc_price());
874 let tx2 = f.validated_arc(MockTransaction::eip1559().inc_price());
875 pool.add_transaction(tx1);
876 pool.add_transaction(tx2);
877
878 let sender1: SenderId = 11.into();
880 let sender2: SenderId = 22.into();
881
882 pool.add_sender_count(sender1, 1);
884
885 pool.add_sender_count(sender2, 2);
887 pool.add_sender_count(sender2, 3);
888
889 assert_eq!(pool.sender_transaction_count.len(), 4);
891 assert!(pool.sender_transaction_count.contains_key(&sender1));
892
893 assert_eq!(pool.sender_transaction_count.get(&sender1).unwrap().count, 1);
895
896 pool.remove_sender_count(sender1);
898
899 assert_eq!(pool.sender_transaction_count.len(), 3);
901 assert!(!pool.sender_transaction_count.contains_key(&sender1));
902
903 assert_eq!(
905 *pool.sender_transaction_count.get(&sender2).unwrap(),
906 SenderTransactionCount { count: 2, last_submission_id: 3 }
907 );
908
909 pool.remove_sender_count(sender2);
911
912 assert_eq!(pool.sender_transaction_count.len(), 3);
917 assert!(pool.sender_transaction_count.contains_key(&sender2));
918
919 assert_eq!(
921 *pool.sender_transaction_count.get(&sender2).unwrap(),
922 SenderTransactionCount { count: 1, last_submission_id: 3 }
923 );
924 }
925
926 #[test]
927 fn test_pool_size() {
928 let mut f = MockTransactionFactory::default();
929 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
930
931 let tx = f.validated_arc(MockTransaction::eip1559().set_size(1024).clone());
933 pool.add_transaction(tx);
934
935 assert_eq!(pool.size(), 1024);
937 }
938
939 #[test]
940 fn test_pool_len() {
941 let mut f = MockTransactionFactory::default();
942 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
943
944 assert_eq!(pool.len(), 0);
946
947 let tx = f.validated_arc(MockTransaction::eip1559());
949 pool.add_transaction(tx);
950 assert_eq!(pool.len(), 1);
951 }
952
953 #[test]
954 fn test_pool_contains() {
955 let mut f = MockTransactionFactory::default();
956 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
957
958 let tx = f.validated_arc(MockTransaction::eip1559());
960 let tx_id = *tx.id();
961
962 assert!(!pool.contains(&tx_id));
964
965 pool.add_transaction(tx);
967 assert!(pool.contains(&tx_id));
968 }
969
970 #[test]
971 fn test_get_transaction() {
972 let mut f = MockTransactionFactory::default();
973 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
974
975 let tx = f.validated_arc(MockTransaction::eip1559());
977 let tx_id = *tx.id();
978 pool.add_transaction(tx.clone());
979
980 let retrieved = pool.get(&tx_id).expect("Transaction should exist in the pool");
982 assert_eq!(retrieved.transaction.id(), tx.id());
983 }
984
985 #[test]
986 fn test_all_transactions() {
987 let mut f = MockTransactionFactory::default();
988 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
989
990 let tx1 = f.validated_arc(MockTransaction::eip1559());
992 let tx2 = f.validated_arc(MockTransaction::eip1559());
993 pool.add_transaction(tx1.clone());
994 pool.add_transaction(tx2.clone());
995
996 let all_txs: Vec<_> = pool.all().map(|tx| *tx.id()).collect();
998 assert_eq!(all_txs.len(), 2);
999
1000 assert!(all_txs.contains(tx1.id()));
1002 assert!(all_txs.contains(tx2.id()));
1003 }
1004
1005 #[test]
1006 fn test_truncate_pool_edge_case() {
1007 let mut f = MockTransactionFactory::default();
1008 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1009
1010 let tx1 = f.validated_arc(MockTransaction::eip1559());
1012 let tx2 = f.validated_arc(MockTransaction::eip1559());
1013 pool.add_transaction(tx1);
1014 pool.add_transaction(tx2);
1015
1016 let limit = SubPoolLimit { max_txs: 2, max_size: usize::MAX };
1018 let removed = pool.truncate_pool(limit);
1019
1020 assert!(removed.is_empty());
1022
1023 let limit = SubPoolLimit { max_txs: 1, max_size: usize::MAX };
1025 let removed = pool.truncate_pool(limit);
1026
1027 assert_eq!(removed.len(), 1);
1029 assert_eq!(pool.len(), 1);
1030 }
1031
1032 #[test]
1033 fn test_satisfy_base_fee_transactions() {
1034 let mut f = MockTransactionFactory::default();
1035 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1036
1037 let tx1 = f.validated_arc(MockTransaction::eip1559().set_max_fee(100).clone());
1039 let tx2 = f.validated_arc(MockTransaction::eip1559().set_max_fee(200).clone());
1040 pool.add_transaction(tx1);
1041 pool.add_transaction(tx2.clone());
1042
1043 let satisfied = pool.satisfy_base_fee_transactions(150);
1045 assert_eq!(satisfied.len(), 1);
1046 assert_eq!(satisfied[0].id(), tx2.id())
1047 }
1048
1049 #[test]
1050 fn test_remove_transaction() {
1051 let mut f = MockTransactionFactory::default();
1052 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1053
1054 let tx = f.validated_arc(MockTransaction::eip1559());
1056 let tx_id = *tx.id();
1057 pool.add_transaction(tx);
1058
1059 assert!(pool.contains(&tx_id));
1061
1062 let removed = pool.remove_transaction(&tx_id);
1064 assert!(removed.is_some());
1065 assert!(!pool.contains(&tx_id));
1066 }
1067
1068 #[test]
1069 fn test_enforce_basefee_with_handler_zero_allocation() {
1070 let mut f = MockTransactionFactory::default();
1071 let mut pool = ParkedPool::<BasefeeOrd<_>>::default();
1072
1073 let sender_a = address!("0x000000000000000000000000000000000000000a");
1075 let sender_b = address!("0x000000000000000000000000000000000000000b");
1076
1077 let txs = vec![
1081 f.validated_arc(
1082 MockTransaction::eip1559()
1083 .set_sender(sender_a)
1084 .set_nonce(0)
1085 .set_max_fee(500)
1086 .clone(),
1087 ),
1088 f.validated_arc(
1089 MockTransaction::eip1559()
1090 .set_sender(sender_a)
1091 .set_nonce(1)
1092 .set_max_fee(600)
1093 .clone(),
1094 ),
1095 f.validated_arc(
1096 MockTransaction::eip1559()
1097 .set_sender(sender_b)
1098 .set_nonce(0)
1099 .set_max_fee(300)
1100 .clone(),
1101 ),
1102 ];
1103
1104 let expected_affordable = vec![txs[0].clone(), txs[1].clone()]; for tx in txs {
1106 pool.add_transaction(tx);
1107 }
1108
1109 let mut processed_txs = Vec::new();
1111 let mut handler_call_count = 0;
1112
1113 pool.enforce_basefee_with(400, |tx| {
1114 processed_txs.push(tx);
1115 handler_call_count += 1;
1116 });
1117
1118 assert_eq!(handler_call_count, 2);
1120 assert_eq!(processed_txs.len(), 2);
1121
1122 let processed_ids: Vec<_> = processed_txs.iter().map(|tx| *tx.id()).collect();
1124 for expected_tx in expected_affordable {
1125 assert!(processed_ids.contains(expected_tx.id()));
1126 }
1127
1128 assert_eq!(pool.len(), 1); }
1131}