Skip to main content

reth_primitives_traits/transaction/
recover.rs

1//! Helpers for recovering signers from a set of transactions
2
3use crate::{transaction::signed::RecoveryError, Recovered, SignedTransaction};
4use alloc::vec::Vec;
5use alloy_consensus::transaction::SignerRecoverable;
6use alloy_primitives::Address;
7
8#[cfg(feature = "rayon")]
9use rayon::prelude::{IntoParallelIterator, ParallelIterator};
10
11/// Recovers a list of signers from a transaction list iterator.
12///
13/// Returns `Err(RecoveryError)`, if some transaction's signature is invalid.
14///
15/// When the `rayon` feature is enabled, recovery is performed in parallel.
16#[cfg(feature = "rayon")]
17pub fn recover_signers<'a, I, T>(txes: I) -> Result<Vec<Address>, RecoveryError>
18where
19    T: SignedTransaction,
20    I: IntoParallelIterator<Item = &'a T>,
21{
22    txes.into_par_iter().map(|tx| tx.recover_signer()).collect()
23}
24
25/// Recovers a list of signers from a transaction list iterator.
26///
27/// Returns `Err(RecoveryError)`, if some transaction's signature is invalid.
28#[cfg(not(feature = "rayon"))]
29pub fn recover_signers<'a, I, T>(txes: I) -> Result<Vec<Address>, RecoveryError>
30where
31    T: SignedTransaction,
32    I: IntoIterator<Item = &'a T>,
33{
34    txes.into_iter().map(|tx| tx.recover_signer()).collect()
35}
36
37/// Recovers a list of signers from a transaction list iterator _without ensuring that the
38/// signature has a low `s` value_.
39///
40/// Returns `Err(RecoveryError)`, if some transaction's signature is invalid.
41///
42/// When the `rayon` feature is enabled, recovery is performed in parallel.
43#[cfg(feature = "rayon")]
44pub fn recover_signers_unchecked<'a, I, T>(txes: I) -> Result<Vec<Address>, RecoveryError>
45where
46    T: SignedTransaction,
47    I: IntoParallelIterator<Item = &'a T>,
48{
49    txes.into_par_iter().map(|tx| tx.recover_signer_unchecked()).collect()
50}
51
52/// Recovers a list of signers from a transaction list iterator _without ensuring that the
53/// signature has a low `s` value_.
54///
55/// Returns `Err(RecoveryError)`, if some transaction's signature is invalid.
56#[cfg(not(feature = "rayon"))]
57pub fn recover_signers_unchecked<'a, I, T>(txes: I) -> Result<Vec<Address>, RecoveryError>
58where
59    T: SignedTransaction,
60    I: IntoIterator<Item = &'a T>,
61{
62    txes.into_iter().map(|tx| tx.recover_signer_unchecked()).collect()
63}
64
65/// Trait for items that can be used with [`try_recover_signers`].
66#[cfg(feature = "rayon")]
67pub trait TryRecoverItems: IntoParallelIterator {}
68
69/// Trait for items that can be used with [`try_recover_signers`].
70#[cfg(not(feature = "rayon"))]
71pub trait TryRecoverItems: IntoIterator {}
72
73#[cfg(feature = "rayon")]
74impl<I: IntoParallelIterator> TryRecoverItems for I {}
75
76#[cfg(not(feature = "rayon"))]
77impl<I: IntoIterator> TryRecoverItems for I {}
78
79/// Trait for decode functions that can be used with [`try_recover_signers`].
80#[cfg(feature = "rayon")]
81pub trait TryRecoverFn<Item, T>: Fn(Item) -> Result<T, RecoveryError> + Sync {}
82
83/// Trait for decode functions that can be used with [`try_recover_signers`].
84#[cfg(not(feature = "rayon"))]
85pub trait TryRecoverFn<Item, T>: Fn(Item) -> Result<T, RecoveryError> {}
86
87#[cfg(feature = "rayon")]
88impl<Item, T, F: Fn(Item) -> Result<T, RecoveryError> + Sync> TryRecoverFn<Item, T> for F {}
89
90#[cfg(not(feature = "rayon"))]
91impl<Item, T, F: Fn(Item) -> Result<T, RecoveryError>> TryRecoverFn<Item, T> for F {}
92
93/// Decodes and recovers a list of [`Recovered`] transactions from an iterator.
94///
95/// The `decode` closure transforms each item into a [`SignedTransaction`], which is then
96/// recovered.
97///
98/// Returns an error if decoding or signature recovery fails for any transaction.
99///
100/// When the `rayon` feature is enabled, recovery is performed in parallel.
101#[cfg(feature = "rayon")]
102pub fn try_recover_signers<I, F, T>(items: I, decode: F) -> Result<Vec<Recovered<T>>, RecoveryError>
103where
104    I: IntoParallelIterator,
105    F: Fn(I::Item) -> Result<T, RecoveryError> + Sync,
106    T: SignedTransaction,
107{
108    items
109        .into_par_iter()
110        .map(|item| {
111            let tx = decode(item)?;
112            SignerRecoverable::try_into_recovered(tx)
113        })
114        .collect()
115}
116
117/// Decodes and recovers a list of [`Recovered`] transactions from an iterator.
118///
119/// The `decode` closure transforms each item into a [`SignedTransaction`], which is then
120/// recovered.
121///
122/// Returns an error if decoding or signature recovery fails for any transaction.
123#[cfg(not(feature = "rayon"))]
124pub fn try_recover_signers<I, F, T>(items: I, decode: F) -> Result<Vec<Recovered<T>>, RecoveryError>
125where
126    I: IntoIterator,
127    F: Fn(I::Item) -> Result<T, RecoveryError>,
128    T: SignedTransaction,
129{
130    items
131        .into_iter()
132        .map(|item| {
133            let tx = decode(item)?;
134            SignerRecoverable::try_into_recovered(tx)
135        })
136        .collect()
137}