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)]
16#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub struct Recovered<T> {
19 signer: Address,
21 #[deref]
23 #[as_ref]
24 #[cfg_attr(feature = "serde", serde(flatten))]
25 inner: T,
26}
27
28impl<T> Recovered<T> {
29 pub const fn signer(&self) -> Address {
31 self.signer
32 }
33
34 pub const fn signer_ref(&self) -> &Address {
36 &self.signer
37 }
38
39 pub const fn inner(&self) -> &T {
41 &self.inner
42 }
43
44 pub const fn inner_mut(&mut self) -> &mut T {
48 &mut self.inner
49 }
50
51 pub fn into_inner(self) -> T {
53 self.inner
54 }
55
56 pub fn clone_inner(&self) -> T
58 where
59 T: Clone,
60 {
61 self.inner.clone()
62 }
63
64 #[doc(alias = "split")]
66 pub fn into_parts(self) -> (T, Address) {
67 (self.inner, self.signer)
68 }
69
70 pub const fn as_recovered_ref(&self) -> Recovered<&T> {
72 Recovered { inner: &self.inner, signer: self.signer() }
73 }
74
75 #[inline]
79 pub const fn new_unchecked(inner: T, signer: Address) -> Self {
80 Self { inner, signer }
81 }
82
83 pub fn convert<Tx>(self) -> Recovered<Tx>
85 where
86 Tx: From<T>,
87 {
88 self.map(Tx::from)
89 }
90
91 pub fn try_convert<Tx>(self) -> Result<Recovered<Tx>, Tx::Error>
93 where
94 Tx: TryFrom<T>,
95 {
96 self.try_map(Tx::try_from)
97 }
98
99 pub fn map<Tx>(self, f: impl FnOnce(T) -> Tx) -> Recovered<Tx> {
101 Recovered::new_unchecked(f(self.inner), self.signer)
102 }
103
104 pub fn try_map<Tx, E>(self, f: impl FnOnce(T) -> Result<Tx, E>) -> Result<Recovered<Tx>, E> {
106 Ok(Recovered::new_unchecked(f(self.inner)?, self.signer))
107 }
108
109 pub fn into_encoded_with(self, encoding: impl Into<Bytes>) -> WithEncoded<Self> {
111 WithEncoded::new(encoding.into(), self)
112 }
113
114 pub fn into_encoded(self) -> WithEncoded<Self>
116 where
117 T: Encodable2718,
118 {
119 let mut out = alloc::vec![];
120 self.inner.encode_2718(&mut out);
121
122 self.into_encoded_with(out)
123 }
124}
125
126impl<T> Recovered<&T> {
127 pub fn cloned(self) -> Recovered<T>
129 where
130 T: Clone,
131 {
132 let Self { inner, signer } = self;
133 Recovered::new_unchecked(inner.clone(), signer)
134 }
135
136 pub const fn copied(&self) -> Self {
138 *self
139 }
140}
141
142impl<T: Clone> Recovered<Cow<'_, T>> {
143 pub fn into_owned(self) -> Recovered<T> {
146 let Self { inner, signer } = self;
147 Recovered::new_unchecked(inner.into_owned(), signer)
148 }
149}
150
151impl<T: Encodable> Encodable for Recovered<T> {
152 fn encode(&self, out: &mut dyn bytes::BufMut) {
154 self.inner.encode(out)
155 }
156
157 fn length(&self) -> usize {
158 self.inner.length()
159 }
160}
161
162impl<T: Decodable + SignerRecoverable> Decodable for Recovered<T> {
163 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
164 let tx = T::decode(buf)?;
165 let signer = tx.recover_signer().map_err(|_| {
166 alloy_rlp::Error::Custom("Unable to recover decoded transaction signer.")
167 })?;
168 Ok(Self::new_unchecked(tx, signer))
169 }
170}
171
172impl<T: Typed2718> Typed2718 for Recovered<T> {
173 fn ty(&self) -> u8 {
174 self.inner.ty()
175 }
176}
177
178impl<T: Encodable2718> Encodable2718 for Recovered<T> {
179 fn encode_2718_len(&self) -> usize {
180 self.inner.encode_2718_len()
181 }
182
183 fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) {
184 self.inner.encode_2718(out)
185 }
186
187 fn trie_hash(&self) -> B256 {
188 self.inner.trie_hash()
189 }
190}
191
192impl<T> AsRef<Self> for Recovered<T> {
193 fn as_ref(&self) -> &Self {
194 self
195 }
196}
197
198pub trait SignerRecoverable {
203 fn recover_signer(&self) -> Result<Address, RecoveryError>;
213
214 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError>;
219
220 fn recover_with_buf(&self, buf: &mut alloc::vec::Vec<u8>) -> Result<Address, RecoveryError> {
226 let _ = buf;
227 self.recover_signer()
228 }
229
230 fn recover_unchecked_with_buf(
236 &self,
237 buf: &mut alloc::vec::Vec<u8>,
238 ) -> Result<Address, RecoveryError> {
239 let _ = buf;
240 self.recover_signer_unchecked()
241 }
242
243 fn try_into_recovered(self) -> Result<Recovered<Self>, RecoveryError>
246 where
247 Self: Sized,
248 {
249 let signer = self.recover_signer()?;
250 Ok(Recovered::new_unchecked(self, signer))
251 }
252
253 fn try_into_recovered_unchecked(self) -> Result<Recovered<Self>, RecoveryError>
256 where
257 Self: Sized,
258 {
259 let signer = self.recover_signer_unchecked()?;
260 Ok(Recovered::new_unchecked(self, signer))
261 }
262
263 fn try_into_recovered_with_buf(
269 self,
270 buf: &mut alloc::vec::Vec<u8>,
271 ) -> Result<Recovered<Self>, RecoveryError>
272 where
273 Self: Sized,
274 {
275 let signer = self.recover_with_buf(buf)?;
276 Ok(Recovered::new_unchecked(self, signer))
277 }
278 fn try_into_recovered_unchecked_with_buf(
284 self,
285 buf: &mut alloc::vec::Vec<u8>,
286 ) -> Result<Recovered<Self>, RecoveryError>
287 where
288 Self: Sized,
289 {
290 let signer = self.recover_unchecked_with_buf(buf)?;
291 Ok(Recovered::new_unchecked(self, signer))
292 }
293
294 fn try_to_recovered_ref(&self) -> Result<Recovered<&Self>, RecoveryError> {
297 let signer = self.recover_signer()?;
298 Ok(Recovered::new_unchecked(self, signer))
299 }
300
301 fn try_to_recovered_ref_with_buf(
307 &self,
308 buf: &mut alloc::vec::Vec<u8>,
309 ) -> Result<Recovered<&Self>, RecoveryError> {
310 let signer = self.recover_with_buf(buf)?;
311 Ok(Recovered::new_unchecked(self, signer))
312 }
313
314 fn try_to_recovered_ref_unchecked(&self) -> Result<Recovered<&Self>, RecoveryError> {
317 let signer = self.recover_signer_unchecked()?;
318 Ok(Recovered::new_unchecked(self, signer))
319 }
320
321 fn try_to_recovered_ref_unchecked_with_buf(
327 &self,
328 buf: &mut alloc::vec::Vec<u8>,
329 ) -> Result<Recovered<&Self>, RecoveryError> {
330 let signer = self.recover_unchecked_with_buf(buf)?;
331 Ok(Recovered::new_unchecked(self, signer))
332 }
333}
334
335impl<T> SignerRecoverable for WithEncoded<T>
336where
337 T: SignerRecoverable,
338{
339 fn recover_signer(&self) -> Result<Address, RecoveryError> {
340 self.1.recover_signer()
341 }
342
343 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
344 self.1.recover_signer_unchecked()
345 }
346
347 fn recover_with_buf(&self, buf: &mut Vec<u8>) -> Result<Address, RecoveryError> {
348 self.1.recover_with_buf(buf)
349 }
350
351 fn recover_unchecked_with_buf(
352 &self,
353 buf: &mut alloc::vec::Vec<u8>,
354 ) -> Result<Address, RecoveryError> {
355 self.1.recover_unchecked_with_buf(buf)
356 }
357}
358
359impl<T> SignerRecoverable for Sealed<T>
360where
361 T: SignerRecoverable,
362{
363 fn recover_signer(&self) -> Result<Address, RecoveryError> {
364 self.inner().recover_signer()
365 }
366
367 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
368 self.inner().recover_signer_unchecked()
369 }
370
371 fn recover_with_buf(&self, buf: &mut alloc::vec::Vec<u8>) -> Result<Address, RecoveryError> {
372 self.inner().recover_with_buf(buf)
373 }
374
375 fn recover_unchecked_with_buf(
376 &self,
377 buf: &mut alloc::vec::Vec<u8>,
378 ) -> Result<Address, RecoveryError> {
379 self.inner().recover_unchecked_with_buf(buf)
380 }
381}