alloy_consensus/transaction/
recovered.rs1use crate::crypto::RecoveryError;
2use alloc::{borrow::Cow, vec::Vec};
3use alloy_eips::{
4 eip2718::{Encodable2718, WithEncoded},
5 Typed2718,
6};
7use alloy_primitives::{bytes, Address, Bytes, Sealed, B256};
8use alloy_rlp::{Decodable, Encodable};
9use derive_more::{AsRef, Deref};
10
11#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, AsRef, Deref)]
13#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Recovered<T> {
16 signer: Address,
18 #[deref]
20 #[as_ref]
21 #[cfg_attr(feature = "serde", serde(flatten))]
22 inner: T,
23}
24
25impl<T> Recovered<T> {
26 pub const fn signer(&self) -> Address {
28 self.signer
29 }
30
31 pub const fn signer_ref(&self) -> &Address {
33 &self.signer
34 }
35
36 pub const fn inner(&self) -> &T {
38 &self.inner
39 }
40
41 pub const fn inner_mut(&mut self) -> &mut T {
43 &mut self.inner
44 }
45
46 pub fn into_inner(self) -> T {
48 self.inner
49 }
50
51 pub fn clone_inner(&self) -> T
53 where
54 T: Clone,
55 {
56 self.inner.clone()
57 }
58
59 #[doc(alias = "split")]
61 pub fn into_parts(self) -> (T, Address) {
62 (self.inner, self.signer)
63 }
64
65 pub const fn as_recovered_ref(&self) -> Recovered<&T> {
67 Recovered { inner: &self.inner, signer: self.signer() }
68 }
69
70 #[inline]
74 pub const fn new_unchecked(inner: T, signer: Address) -> Self {
75 Self { inner, signer }
76 }
77
78 pub fn convert<Tx>(self) -> Recovered<Tx>
80 where
81 Tx: From<T>,
82 {
83 self.map(Tx::from)
84 }
85
86 pub fn try_convert<Tx>(self) -> Result<Recovered<Tx>, Tx::Error>
88 where
89 Tx: TryFrom<T>,
90 {
91 self.try_map(Tx::try_from)
92 }
93
94 pub fn map<Tx>(self, f: impl FnOnce(T) -> Tx) -> Recovered<Tx> {
96 Recovered::new_unchecked(f(self.inner), self.signer)
97 }
98
99 pub fn try_map<Tx, E>(self, f: impl FnOnce(T) -> Result<Tx, E>) -> Result<Recovered<Tx>, E> {
101 Ok(Recovered::new_unchecked(f(self.inner)?, self.signer))
102 }
103
104 pub fn into_encoded_with(self, encoding: impl Into<Bytes>) -> WithEncoded<Self> {
106 WithEncoded::new(encoding.into(), self)
107 }
108
109 pub fn into_encoded(self) -> WithEncoded<Self>
111 where
112 T: Encodable2718,
113 {
114 let mut out = alloc::vec![];
115 self.inner.encode_2718(&mut out);
116
117 self.into_encoded_with(out)
118 }
119}
120
121impl<T> Recovered<&T> {
122 pub fn cloned(self) -> Recovered<T>
124 where
125 T: Clone,
126 {
127 let Self { inner, signer } = self;
128 Recovered::new_unchecked(inner.clone(), signer)
129 }
130
131 pub const fn copied(&self) -> Self {
133 *self
134 }
135}
136
137impl<T: Clone> Recovered<Cow<'_, T>> {
138 pub fn into_owned(self) -> Recovered<T> {
141 let Self { inner, signer } = self;
142 Recovered::new_unchecked(inner.into_owned(), signer)
143 }
144}
145
146impl<T: Encodable> Encodable for Recovered<T> {
147 fn encode(&self, out: &mut dyn bytes::BufMut) {
149 self.inner.encode(out)
150 }
151
152 fn length(&self) -> usize {
153 self.inner.length()
154 }
155}
156
157impl<T: Decodable + SignerRecoverable> Decodable for Recovered<T> {
158 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
159 let tx = T::decode(buf)?;
160 let signer = tx.recover_signer().map_err(|_| {
161 alloy_rlp::Error::Custom("Unable to recover decoded transaction signer.")
162 })?;
163 Ok(Self::new_unchecked(tx, signer))
164 }
165}
166
167impl<T: Typed2718> Typed2718 for Recovered<T> {
168 fn ty(&self) -> u8 {
169 self.inner.ty()
170 }
171}
172
173impl<T: Encodable2718> Encodable2718 for Recovered<T> {
174 fn encode_2718_len(&self) -> usize {
175 self.inner.encode_2718_len()
176 }
177
178 fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) {
179 self.inner.encode_2718(out)
180 }
181
182 fn trie_hash(&self) -> B256 {
183 self.inner.trie_hash()
184 }
185}
186
187impl<T> AsRef<Self> for Recovered<T> {
188 fn as_ref(&self) -> &Self {
189 self
190 }
191}
192
193pub trait SignerRecoverable {
198 fn recover_signer(&self) -> Result<Address, RecoveryError>;
208
209 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError>;
214
215 fn recover_with_buf(&self, buf: &mut alloc::vec::Vec<u8>) -> Result<Address, RecoveryError> {
221 let _ = buf;
222 self.recover_signer()
223 }
224
225 fn recover_unchecked_with_buf(
231 &self,
232 buf: &mut alloc::vec::Vec<u8>,
233 ) -> Result<Address, RecoveryError> {
234 let _ = buf;
235 self.recover_signer()
236 }
237
238 fn try_into_recovered(self) -> Result<Recovered<Self>, RecoveryError>
241 where
242 Self: Sized,
243 {
244 let signer = self.recover_signer()?;
245 Ok(Recovered::new_unchecked(self, signer))
246 }
247
248 fn try_into_recovered_unchecked(self) -> Result<Recovered<Self>, RecoveryError>
251 where
252 Self: Sized,
253 {
254 let signer = self.recover_signer_unchecked()?;
255 Ok(Recovered::new_unchecked(self, signer))
256 }
257
258 fn try_into_recovered_with_buf(
264 self,
265 buf: &mut alloc::vec::Vec<u8>,
266 ) -> Result<Recovered<Self>, RecoveryError>
267 where
268 Self: Sized,
269 {
270 let signer = self.recover_with_buf(buf)?;
271 Ok(Recovered::new_unchecked(self, signer))
272 }
273 fn try_into_recovered_unchecked_with_buf(
279 self,
280 buf: &mut alloc::vec::Vec<u8>,
281 ) -> Result<Recovered<Self>, RecoveryError>
282 where
283 Self: Sized,
284 {
285 let signer = self.recover_unchecked_with_buf(buf)?;
286 Ok(Recovered::new_unchecked(self, signer))
287 }
288
289 fn try_to_recovered_ref(&self) -> Result<Recovered<&Self>, RecoveryError> {
292 let signer = self.recover_signer()?;
293 Ok(Recovered::new_unchecked(self, signer))
294 }
295
296 fn try_to_recovered_ref_with_buf(
302 &self,
303 buf: &mut alloc::vec::Vec<u8>,
304 ) -> Result<Recovered<&Self>, RecoveryError> {
305 let signer = self.recover_with_buf(buf)?;
306 Ok(Recovered::new_unchecked(self, signer))
307 }
308
309 fn try_to_recovered_ref_unchecked(&self) -> Result<Recovered<&Self>, RecoveryError> {
312 let signer = self.recover_signer_unchecked()?;
313 Ok(Recovered::new_unchecked(self, signer))
314 }
315
316 fn try_to_recovered_ref_unchecked_with_buf(
322 &self,
323 buf: &mut alloc::vec::Vec<u8>,
324 ) -> Result<Recovered<&Self>, RecoveryError> {
325 let signer = self.recover_unchecked_with_buf(buf)?;
326 Ok(Recovered::new_unchecked(self, signer))
327 }
328}
329
330impl<T> SignerRecoverable for WithEncoded<T>
331where
332 T: SignerRecoverable,
333{
334 fn recover_signer(&self) -> Result<Address, RecoveryError> {
335 self.1.recover_signer()
336 }
337
338 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
339 self.1.recover_signer_unchecked()
340 }
341
342 fn recover_with_buf(&self, buf: &mut Vec<u8>) -> Result<Address, RecoveryError> {
343 self.1.recover_with_buf(buf)
344 }
345
346 fn recover_unchecked_with_buf(
347 &self,
348 buf: &mut alloc::vec::Vec<u8>,
349 ) -> Result<Address, RecoveryError> {
350 self.1.recover_unchecked_with_buf(buf)
351 }
352}
353
354impl<T> SignerRecoverable for Sealed<T>
355where
356 T: SignerRecoverable,
357{
358 fn recover_signer(&self) -> Result<Address, RecoveryError> {
359 self.inner().recover_signer()
360 }
361
362 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
363 self.inner().recover_signer_unchecked()
364 }
365
366 fn recover_with_buf(&self, buf: &mut alloc::vec::Vec<u8>) -> Result<Address, RecoveryError> {
367 self.inner().recover_with_buf(buf)
368 }
369
370 fn recover_unchecked_with_buf(
371 &self,
372 buf: &mut alloc::vec::Vec<u8>,
373 ) -> Result<Address, RecoveryError> {
374 self.inner().recover_unchecked_with_buf(buf)
375 }
376}