1use crate::{
7 blobstore::{BlobStore, BlobStoreError, NoopBlobStore},
8 error::{InvalidPoolTransactionError, PoolError},
9 pool::TransactionListenerKind,
10 traits::{BestTransactionsAttributes, GetPooledTransactionLimit, NewBlobSidecar},
11 validate::ValidTransaction,
12 AddedTransactionOutcome, AllPoolTransactions, AllTransactionsEvents, BestTransactions,
13 BlockInfo, EthPoolTransaction, EthPooledTransaction, NewTransactionEvent, PoolResult, PoolSize,
14 PoolTransaction, PropagatedTransactions, TransactionEvents, TransactionOrigin, TransactionPool,
15 TransactionValidationOutcome, TransactionValidator, ValidPoolTransaction,
16};
17use alloy_eips::{
18 eip1559::ETHEREUM_BLOCK_GAS_LIMIT_30M,
19 eip4844::{BlobAndProofV1, BlobAndProofV2, BlobCellsAndProofsV1},
20 eip7594::BlobTransactionSidecarVariant,
21};
22use alloy_primitives::{map::AddressSet, Address, TxHash, B128, B256, U256};
23use reth_eth_wire_types::HandleMempoolData;
24use reth_primitives_traits::Recovered;
25use std::{marker::PhantomData, sync::Arc};
26use tokio::sync::{mpsc, mpsc::Receiver};
27
28#[derive(Debug, Clone)]
33#[non_exhaustive]
34pub struct NoopTransactionPool<T = EthPooledTransaction> {
35 _marker: PhantomData<T>,
37}
38
39impl<T> NoopTransactionPool<T> {
40 pub fn new() -> Self {
42 Self { _marker: Default::default() }
43 }
44}
45
46impl Default for NoopTransactionPool<EthPooledTransaction> {
47 fn default() -> Self {
48 Self { _marker: Default::default() }
49 }
50}
51
52impl<T: EthPoolTransaction> TransactionPool for NoopTransactionPool<T> {
53 type Transaction = T;
54
55 fn pool_size(&self) -> PoolSize {
56 Default::default()
57 }
58
59 fn block_info(&self) -> BlockInfo {
60 BlockInfo {
61 block_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT_30M,
62 last_seen_block_hash: Default::default(),
63 last_seen_block_number: 0,
64 pending_basefee: 0,
65 pending_blob_fee: None,
66 }
67 }
68
69 async fn add_transaction_and_subscribe(
70 &self,
71 _origin: TransactionOrigin,
72 transaction: Self::Transaction,
73 ) -> PoolResult<TransactionEvents> {
74 let hash = *transaction.hash();
75 Err(PoolError::other(hash, Box::new(NoopInsertError::new(transaction))))
76 }
77
78 async fn add_transaction(
79 &self,
80 _origin: TransactionOrigin,
81 transaction: Self::Transaction,
82 ) -> PoolResult<AddedTransactionOutcome> {
83 let hash = *transaction.hash();
84 Err(PoolError::other(hash, Box::new(NoopInsertError::new(transaction))))
85 }
86
87 async fn add_transactions(
88 &self,
89 _origin: TransactionOrigin,
90 transactions: Vec<Self::Transaction>,
91 ) -> Vec<PoolResult<AddedTransactionOutcome>> {
92 transactions
93 .into_iter()
94 .map(|transaction| {
95 let hash = *transaction.hash();
96 Err(PoolError::other(hash, Box::new(NoopInsertError::new(transaction))))
97 })
98 .collect()
99 }
100
101 async fn add_transactions_with_origins(
102 &self,
103 transactions: Vec<(TransactionOrigin, Self::Transaction)>,
104 ) -> Vec<PoolResult<AddedTransactionOutcome>> {
105 transactions
106 .into_iter()
107 .map(|(_, transaction)| {
108 let hash = *transaction.hash();
109 Err(PoolError::other(hash, Box::new(NoopInsertError::new(transaction))))
110 })
111 .collect()
112 }
113
114 fn transaction_event_listener(&self, _tx_hash: TxHash) -> Option<TransactionEvents> {
115 None
116 }
117
118 fn all_transactions_event_listener(&self) -> AllTransactionsEvents<Self::Transaction> {
119 AllTransactionsEvents::new(mpsc::channel(1).1)
120 }
121
122 fn pending_transactions_listener_for(
123 &self,
124 _kind: TransactionListenerKind,
125 ) -> Receiver<TxHash> {
126 mpsc::channel(1).1
127 }
128
129 fn new_transactions_listener(&self) -> Receiver<NewTransactionEvent<Self::Transaction>> {
130 mpsc::channel(1).1
131 }
132
133 fn blob_transaction_sidecars_listener(&self) -> Receiver<NewBlobSidecar> {
134 mpsc::channel(1).1
135 }
136
137 fn new_transactions_listener_for(
138 &self,
139 _kind: TransactionListenerKind,
140 ) -> Receiver<NewTransactionEvent<Self::Transaction>> {
141 mpsc::channel(1).1
142 }
143
144 fn pooled_transaction_hashes(&self) -> Vec<TxHash> {
145 vec![]
146 }
147
148 fn pooled_transaction_hashes_max(&self, _max: usize) -> Vec<TxHash> {
149 vec![]
150 }
151
152 fn pooled_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
153 vec![]
154 }
155
156 fn pooled_transactions_max(
157 &self,
158 _max: usize,
159 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
160 vec![]
161 }
162
163 fn get_pooled_transaction_elements(
164 &self,
165 _tx_hashes: Vec<TxHash>,
166 _limit: GetPooledTransactionLimit,
167 ) -> Vec<<Self::Transaction as PoolTransaction>::Pooled> {
168 vec![]
169 }
170
171 fn append_pooled_transaction_elements(
172 &self,
173 _tx_hashes: &[TxHash],
174 _limit: GetPooledTransactionLimit,
175 _out: &mut Vec<<Self::Transaction as PoolTransaction>::Pooled>,
176 ) {
177 }
178
179 fn get_pooled_transaction_element(
180 &self,
181 _tx_hash: TxHash,
182 ) -> Option<Recovered<<Self::Transaction as PoolTransaction>::Pooled>> {
183 None
184 }
185
186 fn best_transactions(
187 &self,
188 ) -> Box<dyn BestTransactions<Item = Arc<ValidPoolTransaction<Self::Transaction>>>> {
189 Box::new(std::iter::empty())
190 }
191
192 fn best_transactions_with_attributes(
193 &self,
194 _: BestTransactionsAttributes,
195 ) -> Box<dyn BestTransactions<Item = Arc<ValidPoolTransaction<Self::Transaction>>>> {
196 Box::new(std::iter::empty())
197 }
198
199 fn pending_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
200 vec![]
201 }
202
203 fn pending_transactions_max(
204 &self,
205 _max: usize,
206 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
207 vec![]
208 }
209
210 fn queued_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
211 vec![]
212 }
213
214 fn pending_and_queued_txn_count(&self) -> (usize, usize) {
215 (0, 0)
216 }
217
218 fn all_transactions(&self) -> AllPoolTransactions<Self::Transaction> {
219 AllPoolTransactions::default()
220 }
221
222 fn all_transaction_hashes(&self) -> Vec<TxHash> {
223 vec![]
224 }
225
226 fn remove_transactions(
227 &self,
228 _hashes: Vec<TxHash>,
229 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
230 vec![]
231 }
232
233 fn remove_transactions_and_descendants(
234 &self,
235 _hashes: Vec<TxHash>,
236 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
237 vec![]
238 }
239
240 fn remove_transactions_by_sender(
241 &self,
242 _sender: Address,
243 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
244 vec![]
245 }
246
247 fn prune_transactions(
248 &self,
249 _hashes: Vec<TxHash>,
250 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
251 vec![]
252 }
253
254 fn retain_unknown<A>(&self, _announcement: &mut A)
255 where
256 A: HandleMempoolData,
257 {
258 }
259
260 fn retain_contains<A>(&self, _announcement: &mut A)
261 where
262 A: HandleMempoolData,
263 {
264 }
265
266 fn get(&self, _tx_hash: &TxHash) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
267 None
268 }
269
270 fn get_all(&self, _txs: Vec<TxHash>) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
271 vec![]
272 }
273
274 fn on_propagated(&self, _txs: PropagatedTransactions) {}
275
276 fn get_transactions_by_sender(
277 &self,
278 _sender: Address,
279 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
280 vec![]
281 }
282
283 fn get_pending_transactions_with_predicate(
284 &self,
285 _predicate: impl FnMut(&ValidPoolTransaction<Self::Transaction>) -> bool,
286 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
287 vec![]
288 }
289
290 fn get_pending_transactions_by_sender(
291 &self,
292 _sender: Address,
293 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
294 vec![]
295 }
296
297 fn get_queued_transactions_by_sender(
298 &self,
299 _sender: Address,
300 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
301 vec![]
302 }
303
304 fn get_highest_transaction_by_sender(
305 &self,
306 _sender: Address,
307 ) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
308 None
309 }
310
311 fn get_highest_consecutive_transaction_by_sender(
312 &self,
313 _sender: Address,
314 _on_chain_nonce: u64,
315 ) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
316 None
317 }
318
319 fn get_transaction_by_sender_and_nonce(
320 &self,
321 _sender: Address,
322 _nonce: u64,
323 ) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
324 None
325 }
326
327 fn get_transactions_by_origin(
328 &self,
329 _origin: TransactionOrigin,
330 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
331 vec![]
332 }
333
334 fn get_pending_transactions_by_origin(
335 &self,
336 _origin: TransactionOrigin,
337 ) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>> {
338 vec![]
339 }
340
341 fn unique_senders(&self) -> AddressSet {
342 Default::default()
343 }
344
345 fn get_blob(
346 &self,
347 _tx_hash: TxHash,
348 ) -> Result<Option<Arc<BlobTransactionSidecarVariant>>, BlobStoreError> {
349 Ok(None)
350 }
351
352 fn get_all_blobs(
353 &self,
354 _tx_hashes: Vec<TxHash>,
355 ) -> Result<Vec<(TxHash, Arc<BlobTransactionSidecarVariant>)>, BlobStoreError> {
356 Ok(vec![])
357 }
358
359 fn get_all_blobs_exact(
360 &self,
361 tx_hashes: Vec<TxHash>,
362 ) -> Result<Vec<Arc<BlobTransactionSidecarVariant>>, BlobStoreError> {
363 if tx_hashes.is_empty() {
364 return Ok(vec![])
365 }
366 Err(BlobStoreError::MissingSidecar(tx_hashes[0]))
367 }
368
369 fn get_blobs_for_versioned_hashes_v1(
370 &self,
371 versioned_hashes: &[B256],
372 ) -> Result<Vec<Option<BlobAndProofV1>>, BlobStoreError> {
373 Ok(vec![None; versioned_hashes.len()])
374 }
375
376 fn get_blobs_for_versioned_hashes_v2(
377 &self,
378 _versioned_hashes: &[B256],
379 ) -> Result<Option<Vec<BlobAndProofV2>>, BlobStoreError> {
380 Ok(None)
381 }
382
383 fn get_blobs_for_versioned_hashes_v3(
384 &self,
385 versioned_hashes: &[B256],
386 ) -> Result<Vec<Option<BlobAndProofV2>>, BlobStoreError> {
387 Ok(vec![None; versioned_hashes.len()])
388 }
389
390 fn get_blobs_for_versioned_hashes_v4(
391 &self,
392 versioned_hashes: &[B256],
393 _indices_bitarray: B128,
394 ) -> Result<Vec<Option<BlobCellsAndProofsV1>>, BlobStoreError> {
395 Ok(vec![None; versioned_hashes.len()])
396 }
397
398 fn blob_store(&self) -> Box<dyn BlobStore> {
399 Box::new(NoopBlobStore)
400 }
401}
402
403#[derive(Debug, Clone)]
405#[non_exhaustive]
406pub struct MockTransactionValidator<T> {
407 propagate_local: bool,
408 return_invalid: bool,
409 _marker: PhantomData<T>,
410}
411
412impl<T: EthPoolTransaction> TransactionValidator for MockTransactionValidator<T> {
413 type Transaction = T;
414 type Block = reth_ethereum_primitives::Block;
415
416 async fn validate_transaction(
417 &self,
418 origin: TransactionOrigin,
419 mut transaction: Self::Transaction,
420 ) -> TransactionValidationOutcome<Self::Transaction> {
421 if self.return_invalid {
422 return TransactionValidationOutcome::Invalid(
423 transaction,
424 InvalidPoolTransactionError::Underpriced,
425 );
426 }
427 let maybe_sidecar = transaction.take_blob().maybe_sidecar().cloned();
428 TransactionValidationOutcome::Valid {
431 balance: U256::MAX,
432 state_nonce: 0,
433 bytecode_hash: None,
434 transaction: ValidTransaction::new(transaction, maybe_sidecar),
435 propagate: match origin {
436 TransactionOrigin::External => true,
437 TransactionOrigin::Local => self.propagate_local,
438 TransactionOrigin::Private => false,
439 },
440 authorities: None,
441 }
442 }
443}
444
445impl<T> MockTransactionValidator<T> {
446 pub fn no_propagate_local() -> Self {
449 Self { propagate_local: false, return_invalid: false, _marker: Default::default() }
450 }
451 pub fn return_invalid() -> Self {
453 Self { propagate_local: false, return_invalid: true, _marker: Default::default() }
454 }
455}
456
457impl<T> Default for MockTransactionValidator<T> {
458 fn default() -> Self {
459 Self { propagate_local: true, return_invalid: false, _marker: Default::default() }
460 }
461}
462
463#[derive(Debug, Clone, thiserror::Error)]
465#[error("can't insert transaction into the noop pool that does nothing")]
466pub struct NoopInsertError<T: EthPoolTransaction = EthPooledTransaction> {
467 tx: T,
468}
469
470impl<T: EthPoolTransaction> NoopInsertError<T> {
471 const fn new(tx: T) -> Self {
472 Self { tx }
473 }
474
475 pub fn into_inner(self) -> T {
477 self.tx
478 }
479}