1use crate::{
3 RpcHeader, RpcLog, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, SignableTxRequest,
4 TryIntoTxEnv,
5};
6use alloy_consensus::{error::ValueError, transaction::Recovered};
7use alloy_primitives::Address;
8use alloy_rpc_types_eth::{Log, TransactionInfo};
9use core::error;
10use dyn_clone::DynClone;
11use reth_evm::{BlockEnvFor, ConfigureEvm, EvmEnvFor, SpecFor, TxEnvFor};
12use reth_primitives_traits::{
13 BlockTy, HeaderTy, NodePrimitives, SealedBlock, SealedHeader, SealedHeaderFor, TransactionMeta,
14 TxTy,
15};
16use reth_rpc_traits::{FromConsensusHeader, FromConsensusTx, TryIntoSimTx, TxInfoMapper};
17use std::{convert::Infallible, error::Error, fmt, fmt::Debug, marker::PhantomData};
18
19#[derive(Debug, Clone)]
21pub struct ConvertReceiptInput<'a, N: NodePrimitives> {
22 pub receipt: N::Receipt,
24 pub tx: Recovered<&'a N::SignedTx>,
26 pub gas_used: u64,
28 pub next_log_index: usize,
30 pub meta: TransactionMeta,
32}
33
34pub trait ReceiptConverter<N: NodePrimitives>: Debug + 'static {
36 type RpcReceipt;
38
39 type RpcLog;
41
42 type Error;
44
45 fn convert_log(
47 &self,
48 log: Log,
49 receipt: &N::Receipt,
50 header: &SealedHeaderFor<N>,
51 ) -> Result<Self::RpcLog, Self::Error>;
52
53 fn convert_receipts(
56 &self,
57 receipts: Vec<ConvertReceiptInput<'_, N>>,
58 ) -> Result<Vec<Self::RpcReceipt>, Self::Error>;
59
60 fn convert_receipts_with_block(
62 &self,
63 receipts: Vec<ConvertReceiptInput<'_, N>>,
64 _block: &SealedBlock<N::Block>,
65 ) -> Result<Vec<Self::RpcReceipt>, Self::Error> {
66 self.convert_receipts(receipts)
67 }
68}
69
70pub trait HeaderConverter<Consensus, Rpc>: Send + Sync + Unpin + Clone + 'static {
72 type Err: error::Error;
74
75 fn convert_header(
77 &self,
78 header: SealedHeader<Consensus>,
79 block_size: usize,
80 ) -> Result<Rpc, Self::Err>;
81}
82
83impl<Consensus, Rpc> HeaderConverter<Consensus, Rpc> for ()
86where
87 Rpc: FromConsensusHeader<Consensus>,
88{
89 type Err = Infallible;
90
91 fn convert_header(
92 &self,
93 header: SealedHeader<Consensus>,
94 block_size: usize,
95 ) -> Result<Rpc, Self::Err> {
96 Ok(Rpc::from_consensus_header(header, block_size))
97 }
98}
99
100impl<Consensus, Rpc, F> HeaderConverter<Consensus, Rpc> for F
101where
102 F: Fn(SealedHeader<Consensus>, usize) -> Rpc + Send + Sync + Unpin + Clone + 'static,
103{
104 type Err = Infallible;
105
106 fn convert_header(
107 &self,
108 header: SealedHeader<Consensus>,
109 block_size: usize,
110 ) -> Result<Rpc, Self::Err> {
111 Ok(self(header, block_size))
112 }
113}
114
115#[auto_impl::auto_impl(&, Box, Arc)]
124pub trait RpcConvert: Send + Sync + Unpin + Debug + DynClone + 'static {
125 type Primitives: NodePrimitives;
127
128 type Evm: ConfigureEvm<Primitives = Self::Primitives>;
130
131 type Network: RpcTypes<TransactionRequest: SignableTxRequest<TxTy<Self::Primitives>>>;
134
135 type Error: error::Error + Into<jsonrpsee_types::ErrorObject<'static>>;
137
138 fn fill_pending(
142 &self,
143 tx: Recovered<TxTy<Self::Primitives>>,
144 ) -> Result<RpcTransaction<Self::Network>, Self::Error> {
145 self.fill(tx, TransactionInfo::default())
146 }
147
148 fn fill(
154 &self,
155 tx: Recovered<TxTy<Self::Primitives>>,
156 tx_info: TransactionInfo,
157 ) -> Result<RpcTransaction<Self::Network>, Self::Error>;
158
159 fn build_simulate_v1_transaction(
162 &self,
163 request: RpcTxReq<Self::Network>,
164 ) -> Result<TxTy<Self::Primitives>, Self::Error>;
165
166 fn tx_env(
169 &self,
170 request: RpcTxReq<Self::Network>,
171 evm_env: &EvmEnvFor<Self::Evm>,
172 ) -> Result<TxEnvFor<Self::Evm>, Self::Error>;
173
174 fn convert_log(
176 &self,
177 log: Log,
178 receipt: &<Self::Primitives as NodePrimitives>::Receipt,
179 header: &SealedHeaderFor<Self::Primitives>,
180 ) -> Result<RpcLog<Self::Network>, Self::Error>;
181
182 fn convert_receipts(
185 &self,
186 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
187 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error>;
188
189 fn convert_receipts_with_block(
191 &self,
192 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
193 block: &SealedBlock<BlockTy<Self::Primitives>>,
194 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error>;
195
196 fn convert_header(
198 &self,
199 header: SealedHeaderFor<Self::Primitives>,
200 block_size: usize,
201 ) -> Result<RpcHeader<Self::Network>, Self::Error>;
202}
203
204dyn_clone::clone_trait_object!(
205 <Primitives, Network, Error, Evm>
206 RpcConvert<Primitives = Primitives, Network = Network, Error = Error, Evm = Evm>
207);
208
209pub trait RpcTxConverter<Tx, RpcTx, TxInfo>: Clone + Unpin + Send + Sync + 'static {
229 type Err;
231
232 fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err>;
236}
237
238impl<Tx, RpcTx> RpcTxConverter<Tx, RpcTx, <RpcTx as FromConsensusTx<Tx>>::TxInfo> for ()
239where
240 RpcTx: FromConsensusTx<Tx>,
241{
242 type Err = RpcTx::Err;
243
244 fn convert_rpc_tx(
245 &self,
246 tx: Tx,
247 signer: Address,
248 tx_info: <RpcTx as FromConsensusTx<Tx>>::TxInfo,
249 ) -> Result<RpcTx, Self::Err> {
250 RpcTx::from_consensus_tx(tx, signer, tx_info)
251 }
252}
253
254impl<Tx, RpcTx, F, TxInfo, E> RpcTxConverter<Tx, RpcTx, TxInfo> for F
255where
256 F: Fn(Tx, Address, TxInfo) -> Result<RpcTx, E> + Clone + Unpin + Send + Sync + 'static,
257{
258 type Err = E;
259
260 fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err> {
261 self(tx, signer, tx_info)
262 }
263}
264
265pub trait SimTxConverter<TxReq, SimTx>: Clone + Unpin + Send + Sync + 'static {
281 type Err: Error;
283
284 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err>;
288}
289
290impl<TxReq, SimTx> SimTxConverter<TxReq, SimTx> for ()
291where
292 TxReq: TryIntoSimTx<SimTx> + Debug,
293{
294 type Err = ValueError<TxReq>;
295
296 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err> {
297 tx_req.try_into_sim_tx()
298 }
299}
300
301impl<TxReq, SimTx, F, E> SimTxConverter<TxReq, SimTx> for F
302where
303 TxReq: Debug,
304 E: Error,
305 F: Fn(TxReq) -> Result<SimTx, E> + Clone + Unpin + Send + Sync + 'static,
306{
307 type Err = E;
308
309 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err> {
310 self(tx_req)
311 }
312}
313
314pub trait TxEnvConverter<TxReq, Evm: ConfigureEvm>:
330 Debug + Send + Sync + Unpin + Clone + 'static
331{
332 type Error;
334
335 fn convert_tx_env(
339 &self,
340 tx_req: TxReq,
341 evm_env: &EvmEnvFor<Evm>,
342 ) -> Result<TxEnvFor<Evm>, Self::Error>;
343}
344
345impl<TxReq, Evm> TxEnvConverter<TxReq, Evm> for ()
346where
347 TxReq: TryIntoTxEnv<TxEnvFor<Evm>, SpecFor<Evm>, BlockEnvFor<Evm>>,
348 Evm: ConfigureEvm,
349{
350 type Error = TxReq::Err;
351
352 fn convert_tx_env(
353 &self,
354 tx_req: TxReq,
355 evm_env: &EvmEnvFor<Evm>,
356 ) -> Result<TxEnvFor<Evm>, Self::Error> {
357 tx_req.try_into_tx_env(evm_env)
358 }
359}
360
361impl<F, TxReq, E, Evm> TxEnvConverter<TxReq, Evm> for F
363where
364 F: Fn(TxReq, &EvmEnvFor<Evm>) -> Result<TxEnvFor<Evm>, E>
365 + Debug
366 + Send
367 + Sync
368 + Unpin
369 + Clone
370 + 'static,
371 TxReq: Clone,
372 Evm: ConfigureEvm,
373 E: error::Error + Send + Sync + 'static,
374{
375 type Error = E;
376
377 fn convert_tx_env(
378 &self,
379 tx_req: TxReq,
380 evm_env: &EvmEnvFor<Evm>,
381 ) -> Result<TxEnvFor<Evm>, Self::Error> {
382 self(tx_req, evm_env)
383 }
384}
385
386#[derive(Debug, thiserror::Error)]
388pub enum TransactionConversionError {
389 #[error("Failed to convert transaction into RPC response: {0}")]
391 FromTxReq(String),
392
393 #[error("{0}")]
395 Other(String),
396}
397pub struct RpcConverter<
413 Network,
414 Evm,
415 Receipt,
416 Header = (),
417 Map = (),
418 SimTx = (),
419 RpcTx = (),
420 TxEnv = (),
421> {
422 network: PhantomData<Network>,
423 evm: PhantomData<Evm>,
424 receipt_converter: Receipt,
425 header_converter: Header,
426 mapper: Map,
427 tx_env_converter: TxEnv,
428 sim_tx_converter: SimTx,
429 rpc_tx_converter: RpcTx,
430}
431
432impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> fmt::Debug
433 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
434{
435 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436 f.debug_struct("RpcConverter").finish_non_exhaustive()
437 }
438}
439
440impl<Network, Evm, Receipt> RpcConverter<Network, Evm, Receipt> {
441 pub const fn new(receipt_converter: Receipt) -> Self {
443 Self {
444 network: PhantomData,
445 evm: PhantomData,
446 receipt_converter,
447 header_converter: (),
448 mapper: (),
449 tx_env_converter: (),
450 sim_tx_converter: (),
451 rpc_tx_converter: (),
452 }
453 }
454}
455
456impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
457 RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
458{
459 pub fn with_network<N>(
461 self,
462 ) -> RpcConverter<N, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> {
463 let Self {
464 receipt_converter,
465 header_converter,
466 mapper,
467 evm,
468 sim_tx_converter,
469 rpc_tx_converter,
470 tx_env_converter,
471 ..
472 } = self;
473 RpcConverter {
474 receipt_converter,
475 header_converter,
476 mapper,
477 network: Default::default(),
478 evm,
479 sim_tx_converter,
480 rpc_tx_converter,
481 tx_env_converter,
482 }
483 }
484
485 pub fn with_tx_env_converter<TxEnvNew>(
487 self,
488 tx_env_converter: TxEnvNew,
489 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnvNew> {
490 let Self {
491 receipt_converter,
492 header_converter,
493 mapper,
494 network,
495 evm,
496 sim_tx_converter,
497 rpc_tx_converter,
498 ..
499 } = self;
500 RpcConverter {
501 receipt_converter,
502 header_converter,
503 mapper,
504 network,
505 evm,
506 sim_tx_converter,
507 rpc_tx_converter,
508 tx_env_converter,
509 }
510 }
511
512 pub fn with_header_converter<HeaderNew>(
514 self,
515 header_converter: HeaderNew,
516 ) -> RpcConverter<Network, Evm, Receipt, HeaderNew, Map, SimTx, RpcTx, TxEnv> {
517 let Self {
518 receipt_converter,
519 header_converter: _,
520 mapper,
521 network,
522 evm,
523 sim_tx_converter,
524 rpc_tx_converter,
525 tx_env_converter,
526 } = self;
527 RpcConverter {
528 receipt_converter,
529 header_converter,
530 mapper,
531 network,
532 evm,
533 sim_tx_converter,
534 rpc_tx_converter,
535 tx_env_converter,
536 }
537 }
538
539 pub fn with_mapper<MapNew>(
541 self,
542 mapper: MapNew,
543 ) -> RpcConverter<Network, Evm, Receipt, Header, MapNew, SimTx, RpcTx, TxEnv> {
544 let Self {
545 receipt_converter,
546 header_converter,
547 mapper: _,
548 network,
549 evm,
550 sim_tx_converter,
551 rpc_tx_converter,
552 tx_env_converter,
553 } = self;
554 RpcConverter {
555 receipt_converter,
556 header_converter,
557 mapper,
558 network,
559 evm,
560 sim_tx_converter,
561 rpc_tx_converter,
562 tx_env_converter,
563 }
564 }
565
566 pub fn with_sim_tx_converter<SimTxNew>(
568 self,
569 sim_tx_converter: SimTxNew,
570 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTxNew, RpcTx, TxEnv> {
571 let Self {
572 receipt_converter,
573 header_converter,
574 mapper,
575 network,
576 evm,
577 rpc_tx_converter,
578 tx_env_converter,
579 ..
580 } = self;
581 RpcConverter {
582 receipt_converter,
583 header_converter,
584 mapper,
585 network,
586 evm,
587 sim_tx_converter,
588 rpc_tx_converter,
589 tx_env_converter,
590 }
591 }
592
593 pub fn with_rpc_tx_converter<RpcTxNew>(
595 self,
596 rpc_tx_converter: RpcTxNew,
597 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTxNew, TxEnv> {
598 let Self {
599 receipt_converter,
600 header_converter,
601 mapper,
602 network,
603 evm,
604 sim_tx_converter,
605 tx_env_converter,
606 ..
607 } = self;
608 RpcConverter {
609 receipt_converter,
610 header_converter,
611 mapper,
612 network,
613 evm,
614 sim_tx_converter,
615 rpc_tx_converter,
616 tx_env_converter,
617 }
618 }
619
620 pub fn erased(
622 self,
623 ) -> Box<
624 dyn RpcConvert<
625 Primitives = <Self as RpcConvert>::Primitives,
626 Network = <Self as RpcConvert>::Network,
627 Error = <Self as RpcConvert>::Error,
628 Evm = <Self as RpcConvert>::Evm,
629 >,
630 >
631 where
632 Self: RpcConvert,
633 {
634 Box::new(self)
635 }
636}
637
638impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> Default
639 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
640where
641 Receipt: Default,
642 Header: Default,
643 Map: Default,
644 SimTx: Default,
645 RpcTx: Default,
646 TxEnv: Default,
647{
648 fn default() -> Self {
649 Self {
650 network: Default::default(),
651 evm: Default::default(),
652 receipt_converter: Default::default(),
653 header_converter: Default::default(),
654 mapper: Default::default(),
655 sim_tx_converter: Default::default(),
656 rpc_tx_converter: Default::default(),
657 tx_env_converter: Default::default(),
658 }
659 }
660}
661
662impl<
663 Network,
664 Evm,
665 Receipt: Clone,
666 Header: Clone,
667 Map: Clone,
668 SimTx: Clone,
669 RpcTx: Clone,
670 TxEnv: Clone,
671 > Clone for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
672{
673 fn clone(&self) -> Self {
674 Self {
675 network: Default::default(),
676 evm: Default::default(),
677 receipt_converter: self.receipt_converter.clone(),
678 header_converter: self.header_converter.clone(),
679 mapper: self.mapper.clone(),
680 sim_tx_converter: self.sim_tx_converter.clone(),
681 rpc_tx_converter: self.rpc_tx_converter.clone(),
682 tx_env_converter: self.tx_env_converter.clone(),
683 }
684 }
685}
686
687impl<N, Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> RpcConvert
688 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
689where
690 N: NodePrimitives,
691 Network: RpcTypes<TransactionRequest: SignableTxRequest<N::SignedTx>>,
692 Evm: ConfigureEvm<Primitives = N> + 'static,
693 Receipt: ReceiptConverter<
694 N,
695 RpcReceipt = RpcReceipt<Network>,
696 RpcLog = RpcLog<Network>,
697 Error: From<TransactionConversionError>
698 + From<TxEnv::Error>
699 + From<<Map as TxInfoMapper<TxTy<N>>>::Err>
700 + From<RpcTx::Err>
701 + From<Header::Err>
702 + Error
703 + Unpin
704 + Sync
705 + Send
706 + Into<jsonrpsee_types::ErrorObject<'static>>,
707 > + Send
708 + Sync
709 + Unpin
710 + Clone
711 + Debug,
712 Header: HeaderConverter<HeaderTy<N>, RpcHeader<Network>>,
713 Map: TxInfoMapper<TxTy<N>> + Clone + Debug + Unpin + Send + Sync + 'static,
714 SimTx: SimTxConverter<RpcTxReq<Network>, TxTy<N>>,
715 RpcTx:
716 RpcTxConverter<TxTy<N>, Network::TransactionResponse, <Map as TxInfoMapper<TxTy<N>>>::Out>,
717 TxEnv: TxEnvConverter<RpcTxReq<Network>, Evm>,
718{
719 type Primitives = N;
720 type Evm = Evm;
721 type Network = Network;
722 type Error = Receipt::Error;
723
724 fn fill(
725 &self,
726 tx: Recovered<TxTy<N>>,
727 tx_info: TransactionInfo,
728 ) -> Result<Network::TransactionResponse, Self::Error> {
729 let (tx, signer) = tx.into_parts();
730 let tx_info = self.mapper.try_map(&tx, tx_info)?;
731
732 self.rpc_tx_converter.convert_rpc_tx(tx, signer, tx_info).map_err(Into::into)
733 }
734
735 fn build_simulate_v1_transaction(
736 &self,
737 request: RpcTxReq<Network>,
738 ) -> Result<TxTy<N>, Self::Error> {
739 Ok(self
740 .sim_tx_converter
741 .convert_sim_tx(request)
742 .map_err(|e| TransactionConversionError::FromTxReq(e.to_string()))?)
743 }
744
745 fn tx_env(
746 &self,
747 request: RpcTxReq<Network>,
748 evm_env: &EvmEnvFor<Evm>,
749 ) -> Result<TxEnvFor<Evm>, Self::Error> {
750 self.tx_env_converter.convert_tx_env(request, evm_env).map_err(Into::into)
751 }
752
753 fn convert_log(
754 &self,
755 log: Log,
756 receipt: &<Self::Primitives as NodePrimitives>::Receipt,
757 header: &SealedHeaderFor<Self::Primitives>,
758 ) -> Result<RpcLog<Self::Network>, Self::Error> {
759 self.receipt_converter.convert_log(log, receipt, header)
760 }
761
762 fn convert_receipts(
763 &self,
764 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
765 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
766 self.receipt_converter.convert_receipts(receipts)
767 }
768
769 fn convert_receipts_with_block(
770 &self,
771 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
772 block: &SealedBlock<BlockTy<Self::Primitives>>,
773 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
774 self.receipt_converter.convert_receipts_with_block(receipts, block)
775 }
776
777 fn convert_header(
778 &self,
779 header: SealedHeaderFor<Self::Primitives>,
780 block_size: usize,
781 ) -> Result<RpcHeader<Self::Network>, Self::Error> {
782 Ok(self.header_converter.convert_header(header, block_size)?)
783 }
784}