1use alloc::vec::Vec;
35use alloy_primitives::Bytes;
36use core::fmt::Debug;
37use serde::{de::DeserializeOwned, Serialize};
38
39pub use super::{
40 block::{serde_bincode_compat as block, serde_bincode_compat::*},
41 header::{serde_bincode_compat as header, serde_bincode_compat::*},
42};
43pub use block_bincode::{Block, BlockBody};
44
45pub trait SerdeBincodeCompat: Sized + 'static {
68 type BincodeRepr<'a>: Debug + Serialize + DeserializeOwned;
72
73 fn as_repr(&self) -> Self::BincodeRepr<'_>;
75
76 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self;
78}
79
80impl SerdeBincodeCompat for alloy_consensus::Header {
81 type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::Header<'a>;
82
83 fn as_repr(&self) -> Self::BincodeRepr<'_> {
84 self.into()
85 }
86
87 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
88 repr.into()
89 }
90}
91
92pub type BincodeReprFor<'a, T> = <T as SerdeBincodeCompat>::BincodeRepr<'a>;
106
107pub trait RlpBincode: alloy_rlp::Encodable + alloy_rlp::Decodable {}
130
131impl<T: RlpBincode + 'static> SerdeBincodeCompat for T {
132 type BincodeRepr<'a> = Bytes;
133
134 fn as_repr(&self) -> Self::BincodeRepr<'_> {
135 let mut buf = Vec::new();
136 self.encode(&mut buf);
137 buf.into()
138 }
139
140 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
141 Self::decode(&mut repr.as_ref()).expect("Failed to decode bincode rlp representation")
142 }
143}
144
145mod block_bincode {
146 use crate::serde_bincode_compat::SerdeBincodeCompat;
147 use alloc::{borrow::Cow, vec::Vec};
148 use alloy_consensus::TxTy;
149 use alloy_eips::eip4895::Withdrawals;
150 use core::fmt::Debug;
151 use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer};
152 use serde_with::{DeserializeAs, SerializeAs};
153
154 #[derive(derive_more::Debug, Serialize, Deserialize)]
171 #[debug(bound())]
172 pub struct Block<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
173 header: H::BincodeRepr<'a>,
174 #[serde(bound = "BlockBody<'a, T, H>: Serialize + serde::de::DeserializeOwned")]
175 body: BlockBody<'a, T, H>,
176 }
177
178 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<&'a alloy_consensus::Block<T, H>>
179 for Block<'a, T, H>
180 {
181 fn from(value: &'a alloy_consensus::Block<T, H>) -> Self {
182 Self { header: value.header.as_repr(), body: (&value.body).into() }
183 }
184 }
185
186 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<Block<'a, T, H>>
187 for alloy_consensus::Block<T, H>
188 {
189 fn from(value: Block<'a, T, H>) -> Self {
190 Self { header: SerdeBincodeCompat::from_repr(value.header), body: value.body.into() }
191 }
192 }
193
194 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::Block<T, H>>
195 for Block<'_, T, H>
196 {
197 fn serialize_as<S>(
198 source: &alloy_consensus::Block<T, H>,
199 serializer: S,
200 ) -> Result<S::Ok, S::Error>
201 where
202 S: Serializer,
203 {
204 Block::from(source).serialize(serializer)
205 }
206 }
207
208 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
209 DeserializeAs<'de, alloy_consensus::Block<T, H>> for Block<'de, T, H>
210 {
211 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::Block<T, H>, D::Error>
212 where
213 D: Deserializer<'de>,
214 {
215 Block::deserialize(deserializer).map(Into::into)
216 }
217 }
218
219 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
220 for alloy_consensus::Block<T, H>
221 {
222 type BincodeRepr<'a> = Block<'a, T, H>;
223
224 fn as_repr(&self) -> Self::BincodeRepr<'_> {
225 self.into()
226 }
227
228 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
229 repr.into()
230 }
231 }
232
233 #[derive(derive_more::Debug, Serialize, Deserialize)]
249 #[debug(bound())]
250 pub struct BlockBody<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
251 transactions: Vec<T::BincodeRepr<'a>>,
252 ommers: Vec<H::BincodeRepr<'a>>,
253 withdrawals: Cow<'a, Option<Withdrawals>>,
254 }
255
256 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
257 From<&'a alloy_consensus::BlockBody<T, H>> for BlockBody<'a, T, H>
258 {
259 fn from(value: &'a alloy_consensus::BlockBody<T, H>) -> Self {
260 Self {
261 transactions: value.transactions.iter().map(|tx| tx.as_repr()).collect(),
262 ommers: value.ommers.iter().map(|h| h.as_repr()).collect(),
263 withdrawals: Cow::Borrowed(&value.withdrawals),
264 }
265 }
266 }
267
268 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<BlockBody<'a, T, H>>
269 for alloy_consensus::BlockBody<T, H>
270 {
271 fn from(value: BlockBody<'a, T, H>) -> Self {
272 Self {
273 transactions: value
274 .transactions
275 .into_iter()
276 .map(SerdeBincodeCompat::from_repr)
277 .collect(),
278 ommers: value.ommers.into_iter().map(SerdeBincodeCompat::from_repr).collect(),
279 withdrawals: value.withdrawals.into_owned(),
280 }
281 }
282 }
283
284 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::BlockBody<T, H>>
285 for BlockBody<'_, T, H>
286 {
287 fn serialize_as<S>(
288 source: &alloy_consensus::BlockBody<T, H>,
289 serializer: S,
290 ) -> Result<S::Ok, S::Error>
291 where
292 S: Serializer,
293 {
294 BlockBody::from(source).serialize(serializer)
295 }
296 }
297
298 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
299 DeserializeAs<'de, alloy_consensus::BlockBody<T, H>> for BlockBody<'de, T, H>
300 {
301 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::BlockBody<T, H>, D::Error>
302 where
303 D: Deserializer<'de>,
304 {
305 BlockBody::deserialize(deserializer).map(Into::into)
306 }
307 }
308
309 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
310 for alloy_consensus::BlockBody<T, H>
311 {
312 type BincodeRepr<'a> = BlockBody<'a, T, H>;
313
314 fn as_repr(&self) -> Self::BincodeRepr<'_> {
315 self.into()
316 }
317
318 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
319 repr.into()
320 }
321 }
322
323 impl<T: Clone + Serialize + DeserializeOwned + Debug + 'static> super::SerdeBincodeCompat
324 for alloy_consensus::EthereumTxEnvelope<T>
325 {
326 type BincodeRepr<'a> =
327 alloy_consensus::serde_bincode_compat::transaction::EthereumTxEnvelope<'a, T>;
328
329 fn as_repr(&self) -> Self::BincodeRepr<'_> {
330 self.into()
331 }
332
333 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
334 repr.into()
335 }
336 }
337
338 #[cfg(feature = "op")]
339 impl super::SerdeBincodeCompat for op_alloy_consensus::OpTxEnvelope {
340 type BincodeRepr<'a> =
341 op_alloy_consensus::serde_bincode_compat::transaction::OpTxEnvelope<'a>;
342
343 fn as_repr(&self) -> Self::BincodeRepr<'_> {
344 self.into()
345 }
346
347 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
348 repr.into()
349 }
350 }
351
352 impl<T: TxTy + Serialize + DeserializeOwned> super::SerdeBincodeCompat
353 for alloy_consensus::EthereumReceipt<T>
354 {
355 type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::EthereumReceipt<'a, T>;
356
357 fn as_repr(&self) -> Self::BincodeRepr<'_> {
358 self.into()
359 }
360
361 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
362 repr.into()
363 }
364 }
365
366 #[cfg(feature = "op")]
367 impl super::SerdeBincodeCompat for op_alloy_consensus::OpReceipt {
368 type BincodeRepr<'a> = op_alloy_consensus::serde_bincode_compat::OpReceipt<'a>;
369
370 fn as_repr(&self) -> Self::BincodeRepr<'_> {
371 self.into()
372 }
373
374 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
375 repr.into()
376 }
377 }
378}