reth_codecs/alloy/transaction/
optimism.rs1use 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, Sealed, Signature, 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#[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: match self.mint {
57 0 => None,
58 v => Some(v),
59 },
60 value: self.value,
61 gas_limit: self.gas_limit,
62 is_system_transaction: self.is_system_transaction,
63 input: self.input.clone(),
64 };
65 tx.to_compact(buf)
66 }
67
68 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
69 let (tx, remaining) = TxDeposit::from_compact(buf, len);
71 let alloy_tx = Self {
72 source_hash: tx.source_hash,
73 from: tx.from,
74 to: tx.to,
75 mint: tx.mint.unwrap_or_default(),
76 value: tx.value,
77 gas_limit: tx.gas_limit,
78 is_system_transaction: tx.is_system_transaction,
79 input: tx.input,
80 };
81 (alloy_tx, remaining)
82 }
83}
84
85impl crate::Compact for OpTxType {
86 fn to_compact<B>(&self, buf: &mut B) -> usize
87 where
88 B: bytes::BufMut + AsMut<[u8]>,
89 {
90 use crate::txtype::*;
91
92 match self {
93 Self::Legacy => COMPACT_IDENTIFIER_LEGACY,
94 Self::Eip2930 => COMPACT_IDENTIFIER_EIP2930,
95 Self::Eip1559 => COMPACT_IDENTIFIER_EIP1559,
96 Self::Eip7702 => {
97 buf.put_u8(EIP7702_TX_TYPE_ID);
98 COMPACT_EXTENDED_IDENTIFIER_FLAG
99 }
100 Self::Deposit => {
101 buf.put_u8(op_alloy_consensus::DEPOSIT_TX_TYPE_ID);
102 COMPACT_EXTENDED_IDENTIFIER_FLAG
103 }
104 }
105 }
106
107 fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
111 use bytes::Buf;
112 (
113 match identifier {
114 COMPACT_IDENTIFIER_LEGACY => Self::Legacy,
115 COMPACT_IDENTIFIER_EIP2930 => Self::Eip2930,
116 COMPACT_IDENTIFIER_EIP1559 => Self::Eip1559,
117 COMPACT_EXTENDED_IDENTIFIER_FLAG => {
118 let extended_identifier = buf.get_u8();
119 match extended_identifier {
120 EIP7702_TX_TYPE_ID => Self::Eip7702,
121 op_alloy_consensus::DEPOSIT_TX_TYPE_ID => Self::Deposit,
122 _ => panic!("Unsupported OpTxType identifier: {extended_identifier}"),
123 }
124 }
125 _ => panic!("Unknown identifier for TxType: {identifier}"),
126 },
127 buf,
128 )
129 }
130}
131
132impl Compact for OpTypedTransaction {
133 fn to_compact<B>(&self, out: &mut B) -> usize
134 where
135 B: bytes::BufMut + AsMut<[u8]>,
136 {
137 let identifier = self.tx_type().to_compact(out);
138 match self {
139 Self::Legacy(tx) => tx.to_compact(out),
140 Self::Eip2930(tx) => tx.to_compact(out),
141 Self::Eip1559(tx) => tx.to_compact(out),
142 Self::Eip7702(tx) => tx.to_compact(out),
143 Self::Deposit(tx) => tx.to_compact(out),
144 };
145 identifier
146 }
147
148 fn from_compact(buf: &[u8], identifier: usize) -> (Self, &[u8]) {
149 let (tx_type, buf) = OpTxType::from_compact(buf, identifier);
150 match tx_type {
151 OpTxType::Legacy => {
152 let (tx, buf) = Compact::from_compact(buf, buf.len());
153 (Self::Legacy(tx), buf)
154 }
155 OpTxType::Eip2930 => {
156 let (tx, buf) = Compact::from_compact(buf, buf.len());
157 (Self::Eip2930(tx), buf)
158 }
159 OpTxType::Eip1559 => {
160 let (tx, buf) = Compact::from_compact(buf, buf.len());
161 (Self::Eip1559(tx), buf)
162 }
163 OpTxType::Eip7702 => {
164 let (tx, buf) = Compact::from_compact(buf, buf.len());
165 (Self::Eip7702(tx), buf)
166 }
167 OpTxType::Deposit => {
168 let (tx, buf) = Compact::from_compact(buf, buf.len());
169 (Self::Deposit(tx), buf)
170 }
171 }
172 }
173}
174
175impl ToTxCompact for OpTxEnvelope {
176 fn to_tx_compact(&self, buf: &mut (impl BufMut + AsMut<[u8]>)) {
177 match self {
178 Self::Legacy(tx) => tx.tx().to_compact(buf),
179 Self::Eip2930(tx) => tx.tx().to_compact(buf),
180 Self::Eip1559(tx) => tx.tx().to_compact(buf),
181 Self::Eip7702(tx) => tx.tx().to_compact(buf),
182 Self::Deposit(tx) => tx.to_compact(buf),
183 };
184 }
185}
186
187impl FromTxCompact for OpTxEnvelope {
188 type TxType = OpTxType;
189
190 fn from_tx_compact(buf: &[u8], tx_type: OpTxType, signature: Signature) -> (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 = Signature::new(U256::ZERO, U256::ZERO, false);
222
223impl Envelope for OpTxEnvelope {
224 fn signature(&self) -> &Signature {
225 match self {
226 Self::Legacy(tx) => tx.signature(),
227 Self::Eip2930(tx) => tx.signature(),
228 Self::Eip1559(tx) => tx.signature(),
229 Self::Eip7702(tx) => tx.signature(),
230 Self::Deposit(_) => &DEPOSIT_SIGNATURE,
231 }
232 }
233
234 fn tx_type(&self) -> Self::TxType {
235 Self::tx_type(self)
236 }
237}
238
239impl Compact for OpTxEnvelope {
240 fn to_compact<B>(&self, buf: &mut B) -> usize
241 where
242 B: BufMut + AsMut<[u8]>,
243 {
244 CompactEnvelope::to_compact(self, buf)
245 }
246
247 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
248 CompactEnvelope::from_compact(buf, len)
249 }
250}
251
252generate_tests!(#[crate, compact] OpTypedTransaction, OpTypedTransactionTests);