1use alloy_eips::{
17 eip2718::{Eip2718Envelope, Encodable2718},
18 Typed2718,
19};
20use alloy_primitives::{bytes::BufMut, hex, keccak256, Sealable, Sealed, B256};
21use alloy_rlp::{Decodable, Encodable};
22use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
23use std::{
24 fmt::{self, Debug},
25 ops,
26};
27
28#[derive(Clone, Debug)]
33pub struct RlpHeader<H: Encodable> {
34 inner: H,
35 rlp: Option<Box<[u8]>>,
36}
37
38impl<H: Encodable> ops::Deref for RlpHeader<H> {
39 type Target = H;
40
41 #[inline]
42 fn deref(&self) -> &Self::Target {
43 &self.inner
44 }
45}
46
47impl<H: Encodable> RlpHeader<H> {
48 #[must_use]
49 pub const fn new(inner: H) -> Self {
50 Self { inner, rlp: None }
51 }
52
53 pub fn inner(&self) -> &H {
54 &self.inner
55 }
56
57 pub fn inner_mut(&mut self) -> &mut H {
58 &mut self.inner
59 }
60
61 pub fn into_inner(self) -> H {
62 self.inner
63 }
64}
65
66impl<H: Encodable> Sealable for RlpHeader<H> {
67 #[inline]
68 fn hash_slow(&self) -> B256 {
69 match &self.rlp {
70 Some(rlp) => keccak256(rlp),
71 None => keccak256(alloy_rlp::encode(&self.inner)),
72 }
73 }
74
75 #[inline]
76 fn seal_unchecked(mut self, seal: B256) -> Sealed<Self> {
77 self.rlp = None;
78 Sealed::new_unchecked(self, seal)
79 }
80}
81
82impl<H: Encodable> Serialize for RlpHeader<H> {
83 #[inline]
84 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
85 let encoded = alloy_rlp::encode(&self.inner);
86 if serializer.is_human_readable() {
87 hex::serialize(&encoded, serializer)
88 } else {
89 serializer.serialize_bytes(&encoded)
90 }
91 }
92}
93
94impl<'de, H: Encodable + Decodable> Deserialize<'de> for RlpHeader<H> {
95 #[inline]
96 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
97 let rlp = if deserializer.is_human_readable() {
98 deserializer.deserialize_any(BytesVisitor)?
99 } else {
100 deserializer.deserialize_byte_buf(BytesVisitor)?
101 };
102 let inner = alloy_rlp::decode_exact(&rlp).map_err(de::Error::custom)?;
103
104 Ok(RlpHeader {
105 inner,
106 rlp: Some(rlp.into_boxed_slice()),
107 })
108 }
109}
110
111#[cfg(feature = "host")]
112impl<H, I> TryFrom<alloy::rpc::types::Header<H>> for RlpHeader<I>
113where
114 I: Encodable + Decodable + TryFrom<H>,
115{
116 type Error = <I as TryFrom<H>>::Error;
117
118 #[inline]
119 fn try_from(value: alloy::rpc::types::Header<H>) -> Result<Self, Self::Error> {
120 Ok(Self::new(value.inner.try_into()?))
121 }
122}
123
124#[derive(Clone, Debug)]
129pub struct Eip2718Wrapper<T: Eip2718Envelope> {
130 inner: T,
131 encoding: Option<Box<[u8]>>,
132}
133
134impl<T: Eip2718Envelope> Eip2718Wrapper<T> {
135 #[must_use]
136 pub const fn new(inner: T) -> Self {
137 Self {
138 inner,
139 encoding: None,
140 }
141 }
142
143 pub fn inner(&self) -> &T {
144 &self.inner
145 }
146
147 pub fn into_inner(self) -> T {
148 self.inner
149 }
150}
151
152impl<T: Eip2718Envelope> ops::Deref for Eip2718Wrapper<T> {
153 type Target = T;
154
155 #[inline]
156 fn deref(&self) -> &Self::Target {
157 &self.inner
158 }
159}
160
161impl<T: Eip2718Envelope> Encodable for Eip2718Wrapper<T> {
162 fn encode(&self, out: &mut dyn BufMut) {
163 self.encode_2718(out);
164 }
165
166 fn length(&self) -> usize {
167 self.encode_2718_len()
168 }
169}
170
171impl<T: Eip2718Envelope> Typed2718 for Eip2718Wrapper<T> {
172 fn ty(&self) -> u8 {
173 self.inner().ty()
174 }
175}
176
177impl<T: Eip2718Envelope> Encodable2718 for Eip2718Wrapper<T> {
178 fn type_flag(&self) -> Option<u8> {
179 self.inner.type_flag()
180 }
181
182 fn encode_2718_len(&self) -> usize {
183 match &self.encoding {
184 None => self.inner.encode_2718_len(),
185 Some(bytes) => bytes.len(),
186 }
187 }
188
189 fn encode_2718(&self, out: &mut dyn BufMut) {
190 match &self.encoding {
191 Some(bytes) => out.put_slice(bytes),
192 None => self.inner.encode_2718(out),
193 }
194 }
195}
196
197impl<T: Eip2718Envelope> Serialize for Eip2718Wrapper<T> {
198 #[inline]
199 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
200 let encoded = self.inner.encoded_2718();
201 if serializer.is_human_readable() {
202 hex::serialize(&encoded, serializer)
203 } else {
204 serializer.serialize_bytes(&encoded)
205 }
206 }
207}
208
209impl<'de, T: Eip2718Envelope> Deserialize<'de> for Eip2718Wrapper<T> {
210 #[inline]
211 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
212 let bytes = if deserializer.is_human_readable() {
213 deserializer.deserialize_any(BytesVisitor)?
214 } else {
215 deserializer.deserialize_byte_buf(BytesVisitor)?
216 };
217 let mut buf = bytes.as_slice();
218 let inner = T::decode_2718(&mut buf).map_err(de::Error::custom)?;
219 if !buf.is_empty() {
220 return Err(de::Error::custom("unexpected length"));
221 }
222
223 Ok(Eip2718Wrapper {
224 inner,
225 encoding: Some(bytes.into_boxed_slice()),
226 })
227 }
228}
229
230struct BytesVisitor;
231
232impl<'de> de::Visitor<'de> for BytesVisitor {
233 type Value = Vec<u8>;
234
235 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
236 formatter.write_str("bytes represented as a hex string, sequence or raw bytes")
237 }
238 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
239 hex::decode(v).map_err(de::Error::custom)
240 }
241 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
242 Ok(v.to_vec())
243 }
244 fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
245 Ok(v)
246 }
247 fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
248 let mut values = Vec::with_capacity(seq.size_hint().unwrap_or(0));
249 while let Some(value) = seq.next_element()? {
250 values.push(value);
251 }
252 Ok(values)
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259 use alloy_consensus::{Header, ReceiptEnvelope};
260 use alloy_primitives::Sealable;
261
262 #[test]
263 fn bincode_rlp_header() {
264 let value = RlpHeader::new(Header::default());
265 assert_eq!(value.hash_slow(), value.inner().hash_slow());
266
267 let bin = bincode::serialize(&value).unwrap();
268 let de: RlpHeader<Header> = bincode::deserialize(&bin).unwrap();
269 assert_eq!(de.inner(), value.inner());
270 assert_eq!(de.hash_slow(), value.inner().hash_slow());
271 }
272
273 #[test]
274 fn serde_rlp_header() {
275 let value = RlpHeader::new(Header::default());
276 assert_eq!(value.hash_slow(), value.inner().hash_slow());
277
278 let json = serde_json::to_string(&value).unwrap();
279 let de: RlpHeader<Header> = serde_json::from_str(&json).unwrap();
280 assert_eq!(de.inner(), value.inner());
281 assert_eq!(de.hash_slow(), value.inner().hash_slow());
282 }
283
284 #[test]
285 fn bincode_eip2718_wrapper() {
286 let value = Eip2718Wrapper::new(ReceiptEnvelope::Eip2930(Default::default()));
287 assert_eq!(value.encoded_2718(), value.inner().encoded_2718());
288
289 let bin = bincode::serialize(&value).unwrap();
290 let de: Eip2718Wrapper<ReceiptEnvelope> = bincode::deserialize(&bin).unwrap();
291 assert_eq!(de.inner(), value.inner());
292 assert_eq!(de.encoded_2718(), value.inner().encoded_2718());
293 }
294
295 #[test]
296 fn serde_eip2718_wrapper() {
297 let value = Eip2718Wrapper::new(ReceiptEnvelope::Eip2930(Default::default()));
298 assert_eq!(value.encoded_2718(), value.inner().encoded_2718());
299
300 let json = serde_json::to_string(&value).unwrap();
301 let de: Eip2718Wrapper<ReceiptEnvelope> = serde_json::from_str(&json).unwrap();
302 assert_eq!(de.inner(), value.inner());
303 assert_eq!(de.encoded_2718(), value.inner().encoded_2718());
304 }
305}