reth_primitives_traits/transaction/
signed.rs
1use crate::{
4 crypto::secp256k1::{recover_signer, recover_signer_unchecked},
5 InMemorySize, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat,
6};
7use alloc::{fmt, vec::Vec};
8use alloy_consensus::{
9 transaction::{PooledTransaction, Recovered},
10 SignableTransaction,
11};
12use alloy_eips::eip2718::{Decodable2718, Encodable2718};
13use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHash, B256};
14use core::hash::Hash;
15
16pub trait FullSignedTx: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {}
18impl<T> FullSignedTx for T where T: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {}
19
20#[auto_impl::auto_impl(&, Arc)]
22pub trait SignedTransaction:
23 Send
24 + Sync
25 + Unpin
26 + Clone
27 + fmt::Debug
28 + PartialEq
29 + Eq
30 + Hash
31 + alloy_rlp::Encodable
32 + alloy_rlp::Decodable
33 + Encodable2718
34 + Decodable2718
35 + alloy_consensus::Transaction
36 + MaybeSerde
37 + InMemorySize
38{
39 fn tx_hash(&self) -> &TxHash;
41
42 fn signature(&self) -> &Signature;
44
45 fn is_broadcastable_in_full(&self) -> bool {
51 !self.is_eip4844()
53 }
54
55 fn recover_signer(&self) -> Result<Address, RecoveryError>;
65
66 fn try_recover(&self) -> Result<Address, RecoveryError> {
70 self.recover_signer()
71 }
72
73 fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
79 self.recover_signer_unchecked_with_buf(&mut Vec::new())
80 }
81
82 fn try_recover_unchecked(&self) -> Result<Address, RecoveryError> {
87 self.recover_signer_unchecked()
88 }
89
90 fn recover_signer_unchecked_with_buf(
93 &self,
94 buf: &mut Vec<u8>,
95 ) -> Result<Address, RecoveryError>;
96
97 fn recalculate_hash(&self) -> B256 {
100 keccak256(self.encoded_2718())
101 }
102
103 #[auto_impl(keep_default_for(&, Arc))]
105 fn try_clone_into_recovered(&self) -> Result<Recovered<Self>, RecoveryError> {
106 self.recover_signer().map(|signer| Recovered::new_unchecked(self.clone(), signer))
107 }
108
109 #[auto_impl(keep_default_for(&, Arc))]
114 fn try_into_recovered(self) -> Result<Recovered<Self>, Self> {
115 match self.recover_signer() {
116 Ok(signer) => Ok(Recovered::new_unchecked(self, signer)),
117 Err(_) => Err(self),
118 }
119 }
120
121 #[auto_impl(keep_default_for(&, Arc))]
126 fn into_recovered_unchecked(self) -> Result<Recovered<Self>, RecoveryError> {
127 self.recover_signer_unchecked().map(|signer| Recovered::new_unchecked(self, signer))
128 }
129
130 #[auto_impl(keep_default_for(&, Arc))]
134 fn with_signer(self, signer: Address) -> Recovered<Self> {
135 Recovered::new_unchecked(self, signer)
136 }
137}
138
139impl SignedTransaction for PooledTransaction {
140 fn tx_hash(&self) -> &TxHash {
141 match self {
142 Self::Legacy(tx) => tx.hash(),
143 Self::Eip2930(tx) => tx.hash(),
144 Self::Eip1559(tx) => tx.hash(),
145 Self::Eip7702(tx) => tx.hash(),
146 Self::Eip4844(tx) => tx.hash(),
147 }
148 }
149
150 fn signature(&self) -> &Signature {
151 match self {
152 Self::Legacy(tx) => tx.signature(),
153 Self::Eip2930(tx) => tx.signature(),
154 Self::Eip1559(tx) => tx.signature(),
155 Self::Eip7702(tx) => tx.signature(),
156 Self::Eip4844(tx) => tx.signature(),
157 }
158 }
159
160 fn recover_signer(&self) -> Result<Address, RecoveryError> {
161 let signature_hash = self.signature_hash();
162 recover_signer(self.signature(), signature_hash)
163 }
164
165 fn recover_signer_unchecked_with_buf(
166 &self,
167 buf: &mut Vec<u8>,
168 ) -> Result<Address, RecoveryError> {
169 match self {
170 Self::Legacy(tx) => tx.tx().encode_for_signing(buf),
171 Self::Eip2930(tx) => tx.tx().encode_for_signing(buf),
172 Self::Eip1559(tx) => tx.tx().encode_for_signing(buf),
173 Self::Eip7702(tx) => tx.tx().encode_for_signing(buf),
174 Self::Eip4844(tx) => tx.tx().encode_for_signing(buf),
175 }
176 let signature_hash = keccak256(buf);
177 recover_signer_unchecked(self.signature(), signature_hash)
178 }
179}
180
181#[cfg(feature = "op")]
182impl SignedTransaction for op_alloy_consensus::OpPooledTransaction {
183 fn tx_hash(&self) -> &TxHash {
184 match self {
185 Self::Legacy(tx) => tx.hash(),
186 Self::Eip2930(tx) => tx.hash(),
187 Self::Eip1559(tx) => tx.hash(),
188 Self::Eip7702(tx) => tx.hash(),
189 }
190 }
191
192 fn signature(&self) -> &Signature {
193 match self {
194 Self::Legacy(tx) => tx.signature(),
195 Self::Eip2930(tx) => tx.signature(),
196 Self::Eip1559(tx) => tx.signature(),
197 Self::Eip7702(tx) => tx.signature(),
198 }
199 }
200
201 fn recover_signer(&self) -> Result<Address, RecoveryError> {
202 let signature_hash = self.signature_hash();
203 recover_signer(self.signature(), signature_hash)
204 }
205
206 fn recover_signer_unchecked_with_buf(
207 &self,
208 buf: &mut Vec<u8>,
209 ) -> Result<Address, RecoveryError> {
210 match self {
211 Self::Legacy(tx) => tx.tx().encode_for_signing(buf),
212 Self::Eip2930(tx) => tx.tx().encode_for_signing(buf),
213 Self::Eip1559(tx) => tx.tx().encode_for_signing(buf),
214 Self::Eip7702(tx) => tx.tx().encode_for_signing(buf),
215 }
216 let signature_hash = keccak256(buf);
217 recover_signer_unchecked(self.signature(), signature_hash)
218 }
219}
220
221#[derive(Debug, Default, thiserror::Error)]
223#[error("Failed to recover the signer")]
224pub struct RecoveryError;