reth_codecs/alloy/transaction/
optimism.rs

1//! Compact implementation for [`AlloyTxDeposit`]
2
3use crate::{
4    alloy::transaction::ethereum::{CompactEnvelope, Envelope, FromTxCompact, ToTxCompact},
5    generate_tests,
6    txtype::{
7        COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930,
8        COMPACT_IDENTIFIER_LEGACY,
9    },
10    Compact,
11};
12use alloy_consensus::{
13    constants::EIP7702_TX_TYPE_ID, Signed, TxEip1559, TxEip2930, TxEip7702, TxLegacy,
14};
15use alloy_primitives::{Address, Bytes, Signature, Sealed, TxKind, B256, U256};
16use bytes::BufMut;
17use op_alloy_consensus::{OpTxEnvelope, OpTxType, OpTypedTransaction, TxDeposit as AlloyTxDeposit};
18use reth_codecs_derive::add_arbitrary_tests;
19
20/// Deposit transactions, also known as deposits are initiated on L1, and executed on L2.
21///
22/// This is a helper type to use derive on it instead of manually managing `bitfield`.
23///
24/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive
25/// will automatically apply to this type.
26///
27/// Notice: Make sure this struct is 1:1 with [`op_alloy_consensus::TxDeposit`]
28#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Compact)]
29#[cfg_attr(
30    any(test, feature = "test-utils"),
31    derive(arbitrary::Arbitrary, serde::Serialize, serde::Deserialize)
32)]
33#[cfg_attr(feature = "test-utils", allow(unreachable_pub), visibility::make(pub))]
34#[reth_codecs(crate = "crate")]
35#[add_arbitrary_tests(crate, compact)]
36pub(crate) struct TxDeposit {
37    source_hash: B256,
38    from: Address,
39    to: TxKind,
40    mint: Option<u128>,
41    value: U256,
42    gas_limit: u64,
43    is_system_transaction: bool,
44    input: Bytes,
45}
46
47impl Compact for AlloyTxDeposit {
48    fn to_compact<B>(&self, buf: &mut B) -> usize
49    where
50        B: bytes::BufMut + AsMut<[u8]>,
51    {
52        let tx = TxDeposit {
53            source_hash: self.source_hash,
54            from: self.from,
55            to: self.to,
56            mint: self.mint,
57            value: self.value,
58            gas_limit: self.gas_limit,
59            is_system_transaction: self.is_system_transaction,
60            input: self.input.clone(),
61        };
62        tx.to_compact(buf)
63    }
64
65    fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
66        let (tx, _) = TxDeposit::from_compact(buf, len);
67        let alloy_tx = Self {
68            source_hash: tx.source_hash,
69            from: tx.from,
70            to: tx.to,
71            mint: tx.mint,
72            value: tx.value,
73            gas_limit: tx.gas_limit,
74            is_system_transaction: tx.is_system_transaction,
75            input: tx.input,
76        };
77        (alloy_tx, buf)
78    }
79}
80
81impl crate::Compact for OpTxType {
82    fn to_compact<B>(&self, buf: &mut B) -> usize
83    where
84        B: bytes::BufMut + AsMut<[u8]>,
85    {
86        use crate::txtype::*;
87
88        match self {
89            Self::Legacy => COMPACT_IDENTIFIER_LEGACY,
90            Self::Eip2930 => COMPACT_IDENTIFIER_EIP2930,
91            Self::Eip1559 => COMPACT_IDENTIFIER_EIP1559,
92            Self::Eip7702 => {
93                buf.put_u8(EIP7702_TX_TYPE_ID);
94                COMPACT_EXTENDED_IDENTIFIER_FLAG
95            }
96            Self::Deposit => {
97                buf.put_u8(op_alloy_consensus::DEPOSIT_TX_TYPE_ID);
98                COMPACT_EXTENDED_IDENTIFIER_FLAG
99            }
100        }
101    }
102
103    // For backwards compatibility purposes only 2 bits of the type are encoded in the identifier
104    // parameter. In the case of a [`COMPACT_EXTENDED_IDENTIFIER_FLAG`], the full transaction type
105    // is read from the buffer as a single byte.
106    fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
107        use bytes::Buf;
108        (
109            match identifier {
110                COMPACT_IDENTIFIER_LEGACY => Self::Legacy,
111                COMPACT_IDENTIFIER_EIP2930 => Self::Eip2930,
112                COMPACT_IDENTIFIER_EIP1559 => Self::Eip1559,
113                COMPACT_EXTENDED_IDENTIFIER_FLAG => {
114                    let extended_identifier = buf.get_u8();
115                    match extended_identifier {
116                        EIP7702_TX_TYPE_ID => Self::Eip7702,
117                        op_alloy_consensus::DEPOSIT_TX_TYPE_ID => Self::Deposit,
118                        _ => panic!("Unsupported OpTxType identifier: {extended_identifier}"),
119                    }
120                }
121                _ => panic!("Unknown identifier for TxType: {identifier}"),
122            },
123            buf,
124        )
125    }
126}
127
128impl Compact for OpTypedTransaction {
129    fn to_compact<B>(&self, out: &mut B) -> usize
130    where
131        B: bytes::BufMut + AsMut<[u8]>,
132    {
133        let identifier = self.tx_type().to_compact(out);
134        match self {
135            Self::Legacy(tx) => tx.to_compact(out),
136            Self::Eip2930(tx) => tx.to_compact(out),
137            Self::Eip1559(tx) => tx.to_compact(out),
138            Self::Eip7702(tx) => tx.to_compact(out),
139            Self::Deposit(tx) => tx.to_compact(out),
140        };
141        identifier
142    }
143
144    fn from_compact(buf: &[u8], identifier: usize) -> (Self, &[u8]) {
145        let (tx_type, buf) = OpTxType::from_compact(buf, identifier);
146        match tx_type {
147            OpTxType::Legacy => {
148                let (tx, buf) = Compact::from_compact(buf, buf.len());
149                (Self::Legacy(tx), buf)
150            }
151            OpTxType::Eip2930 => {
152                let (tx, buf) = Compact::from_compact(buf, buf.len());
153                (Self::Eip2930(tx), buf)
154            }
155            OpTxType::Eip1559 => {
156                let (tx, buf) = Compact::from_compact(buf, buf.len());
157                (Self::Eip1559(tx), buf)
158            }
159            OpTxType::Eip7702 => {
160                let (tx, buf) = Compact::from_compact(buf, buf.len());
161                (Self::Eip7702(tx), buf)
162            }
163            OpTxType::Deposit => {
164                let (tx, buf) = Compact::from_compact(buf, buf.len());
165                (Self::Deposit(tx), buf)
166            }
167        }
168    }
169}
170
171impl ToTxCompact for OpTxEnvelope {
172    fn to_tx_compact(&self, buf: &mut (impl BufMut + AsMut<[u8]>)) {
173        match self {
174            Self::Legacy(tx) => tx.tx().to_compact(buf),
175            Self::Eip2930(tx) => tx.tx().to_compact(buf),
176            Self::Eip1559(tx) => tx.tx().to_compact(buf),
177            Self::Eip7702(tx) => tx.tx().to_compact(buf),
178            Self::Deposit(tx) => tx.to_compact(buf),
179        };
180    }
181}
182
183impl FromTxCompact for OpTxEnvelope {
184    type TxType = OpTxType;
185
186    fn from_tx_compact(
187        buf: &[u8],
188        tx_type: OpTxType,
189        signature: Signature,
190    ) -> (Self, &[u8]) {
191        match tx_type {
192            OpTxType::Legacy => {
193                let (tx, buf) = TxLegacy::from_compact(buf, buf.len());
194                let tx = Signed::new_unhashed(tx, signature);
195                (Self::Legacy(tx), buf)
196            }
197            OpTxType::Eip2930 => {
198                let (tx, buf) = TxEip2930::from_compact(buf, buf.len());
199                let tx = Signed::new_unhashed(tx, signature);
200                (Self::Eip2930(tx), buf)
201            }
202            OpTxType::Eip1559 => {
203                let (tx, buf) = TxEip1559::from_compact(buf, buf.len());
204                let tx = Signed::new_unhashed(tx, signature);
205                (Self::Eip1559(tx), buf)
206            }
207            OpTxType::Eip7702 => {
208                let (tx, buf) = TxEip7702::from_compact(buf, buf.len());
209                let tx = Signed::new_unhashed(tx, signature);
210                (Self::Eip7702(tx), buf)
211            }
212            OpTxType::Deposit => {
213                let (tx, buf) = op_alloy_consensus::TxDeposit::from_compact(buf, buf.len());
214                let tx = Sealed::new(tx);
215                (Self::Deposit(tx), buf)
216            }
217        }
218    }
219}
220
221const DEPOSIT_SIGNATURE: Signature =
222    Signature::new(U256::ZERO, U256::ZERO, false);
223
224impl Envelope for OpTxEnvelope {
225    fn signature(&self) -> &Signature {
226        match self {
227            Self::Legacy(tx) => tx.signature(),
228            Self::Eip2930(tx) => tx.signature(),
229            Self::Eip1559(tx) => tx.signature(),
230            Self::Eip7702(tx) => tx.signature(),
231            Self::Deposit(_) => &DEPOSIT_SIGNATURE,
232        }
233    }
234
235    fn tx_type(&self) -> Self::TxType {
236        Self::tx_type(self)
237    }
238}
239
240impl Compact for OpTxEnvelope {
241    fn to_compact<B>(&self, buf: &mut B) -> usize
242    where
243        B: BufMut + AsMut<[u8]>,
244    {
245        CompactEnvelope::to_compact(self, buf)
246    }
247
248    fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
249        CompactEnvelope::from_compact(buf, len)
250    }
251}
252
253generate_tests!(#[crate, compact] OpTypedTransaction, OpTypedTransactionTests);