reth_codecs/alloy/transaction/
seismic.rs1use crate::Compact;
4use alloy_consensus::{transaction::TxSeismicElements, TxSeismic as AlloyTxSeismic};
5use alloy_primitives::{aliases::U96, Bytes, ChainId, TxKind, U256};
6use bytes::{Buf, BytesMut};
7
8#[derive(Debug, Clone, PartialEq, Eq, Default, Compact)]
10#[reth_codecs(crate = "crate")]
11#[cfg_attr(
12 any(test, feature = "test-utils"),
13 derive(arbitrary::Arbitrary, serde::Serialize, serde::Deserialize),
14 crate::add_arbitrary_tests(crate, compact)
15)]
16#[cfg_attr(feature = "test-utils", allow(unreachable_pub), visibility::make(pub))]
17pub(crate) struct TxSeismic {
18 chain_id: ChainId,
20 nonce: u64,
22 gas_price: u128,
30 gas_limit: u64,
36 to: TxKind,
39 value: U256,
44 seismic_elements: TxSeismicElements,
46 input: Bytes,
52}
53
54impl Compact for TxSeismicElements {
55 fn to_compact<B>(&self, buf: &mut B) -> usize
56 where
57 B: bytes::BufMut + AsMut<[u8]>,
58 {
59 let mut len = 0;
60 len += self.encryption_pubkey.serialize().to_compact(buf);
61
62 buf.put_u8(self.message_version);
63 len += core::mem::size_of::<u8>();
64
65 let mut cache = BytesMut::new();
66 let nonce_len = self.encryption_nonce.to_compact(&mut cache);
67 buf.put_u8(nonce_len as u8);
68 buf.put_slice(&cache);
69 len += nonce_len + 1;
70
71 len
72 }
73
74 fn from_compact(mut buf: &[u8], _len: usize) -> (Self, &[u8]) {
75 let encryption_pubkey_compressed_bytes =
76 &buf[..seismic_enclave::constants::PUBLIC_KEY_SIZE];
77 let encryption_pubkey =
78 seismic_enclave::PublicKey::from_slice(encryption_pubkey_compressed_bytes).unwrap();
79 buf.advance(seismic_enclave::constants::PUBLIC_KEY_SIZE);
80
81 let (message_version, buf) = (buf[0], &buf[1..]);
82
83 let (nonce_len, buf) = (buf[0], &buf[1..]);
84 let (encryption_nonce, buf) = U96::from_compact(buf, nonce_len as usize);
85 (Self { encryption_pubkey, encryption_nonce, message_version }, buf)
86 }
87}
88
89impl Compact for AlloyTxSeismic {
90 fn to_compact<B>(&self, buf: &mut B) -> usize
91 where
92 B: bytes::BufMut + AsMut<[u8]>,
93 {
94 let tx = TxSeismic {
95 chain_id: self.chain_id,
96 nonce: self.nonce,
97 gas_price: self.gas_price,
98 gas_limit: self.gas_limit,
99 to: self.to,
100 value: self.value,
101 seismic_elements: self.seismic_elements,
102 input: self.input.clone(),
103 };
104
105 tx.to_compact(buf)
106 }
107
108 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
109 let (tx, _) = TxSeismic::from_compact(buf, len);
110
111 let alloy_tx = Self {
112 chain_id: tx.chain_id,
113 nonce: tx.nonce,
114 gas_price: tx.gas_price,
115 gas_limit: tx.gas_limit,
116 to: tx.to,
117 value: tx.value,
118 seismic_elements: tx.seismic_elements,
119 input: tx.input,
120 };
121
122 (alloy_tx, buf)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use alloy_primitives::{hex, Bytes, TxKind};
130 use bytes::BytesMut;
131 use seismic_enclave::PublicKey;
132
133 #[test]
134 fn test_seismic_tx_compact_roundtrip() {
135 let tx = AlloyTxSeismic {
137 chain_id: 1166721750861005481,
138 nonce: 13985005159674441909,
139 gas_price: 296133358425745351516777806240018869443,
140 gas_limit: 6091425913586946366,
141 to: TxKind::Create,
142 value: U256::from_str_radix(
143 "30997721070913355446596643088712595347117842472993214294164452566768407578853",
144 10,
145 )
146 .unwrap(),
147 seismic_elements: TxSeismicElements {
148 encryption_pubkey: PublicKey::from_slice(
149 &hex::decode(
150 "02d211b6b0a191b9469bb3674e9c609f453d3801c3e3fd7e0bb00c6cc1e1d941df",
151 )
152 .unwrap(),
153 )
154 .unwrap(),
155 encryption_nonce: U96::from_str_radix("11856476099097235301", 10).unwrap(),
156 message_version: 85,
157 },
158 input: Bytes::from_static(&[0x24]),
159 };
160
161 let mut buf = BytesMut::new();
163 let encoded_size = tx.to_compact(&mut buf);
164
165 let (decoded_tx, _) = AlloyTxSeismic::from_compact(&buf, encoded_size);
167
168 assert_eq!(tx.chain_id, decoded_tx.chain_id);
170 assert_eq!(tx.nonce, decoded_tx.nonce);
171 assert_eq!(tx.gas_price, decoded_tx.gas_price);
172 assert_eq!(tx.gas_limit, decoded_tx.gas_limit);
173 assert_eq!(tx.to, decoded_tx.to);
174 assert_eq!(tx.value, decoded_tx.value);
175 assert_eq!(tx.input, decoded_tx.input);
176
177 assert_eq!(
179 tx.seismic_elements.encryption_pubkey.serialize(),
180 decoded_tx.seismic_elements.encryption_pubkey.serialize()
181 );
182 assert_eq!(
183 tx.seismic_elements.encryption_nonce,
184 decoded_tx.seismic_elements.encryption_nonce
185 );
186 assert_eq!(
187 tx.seismic_elements.message_version,
188 decoded_tx.seismic_elements.message_version
189 );
190 }
191}