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::TxEip4844;
149 use alloy_eips::eip4895::Withdrawals;
150 use serde::{Deserialize, Deserializer, Serialize, Serializer};
151 use serde_with::{DeserializeAs, SerializeAs};
152
153 #[derive(derive_more::Debug, Serialize, Deserialize)]
170 #[debug(bound())]
171 pub struct Block<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
172 header: H::BincodeRepr<'a>,
173 #[serde(bound = "BlockBody<'a, T, H>: Serialize + serde::de::DeserializeOwned")]
174 body: BlockBody<'a, T, H>,
175 }
176
177 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<&'a alloy_consensus::Block<T, H>>
178 for Block<'a, T, H>
179 {
180 fn from(value: &'a alloy_consensus::Block<T, H>) -> Self {
181 Self { header: value.header.as_repr(), body: (&value.body).into() }
182 }
183 }
184
185 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<Block<'a, T, H>>
186 for alloy_consensus::Block<T, H>
187 {
188 fn from(value: Block<'a, T, H>) -> Self {
189 Self { header: SerdeBincodeCompat::from_repr(value.header), body: value.body.into() }
190 }
191 }
192
193 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::Block<T, H>>
194 for Block<'_, T, H>
195 {
196 fn serialize_as<S>(
197 source: &alloy_consensus::Block<T, H>,
198 serializer: S,
199 ) -> Result<S::Ok, S::Error>
200 where
201 S: Serializer,
202 {
203 Block::from(source).serialize(serializer)
204 }
205 }
206
207 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
208 DeserializeAs<'de, alloy_consensus::Block<T, H>> for Block<'de, T, H>
209 {
210 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::Block<T, H>, D::Error>
211 where
212 D: Deserializer<'de>,
213 {
214 Block::deserialize(deserializer).map(Into::into)
215 }
216 }
217
218 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
219 for alloy_consensus::Block<T, H>
220 {
221 type BincodeRepr<'a> = Block<'a, T, H>;
222
223 fn as_repr(&self) -> Self::BincodeRepr<'_> {
224 self.into()
225 }
226
227 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
228 repr.into()
229 }
230 }
231
232 #[derive(derive_more::Debug, Serialize, Deserialize)]
248 #[debug(bound())]
249 pub struct BlockBody<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
250 transactions: Vec<T::BincodeRepr<'a>>,
251 ommers: Vec<H::BincodeRepr<'a>>,
252 withdrawals: Cow<'a, Option<Withdrawals>>,
253 }
254
255 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
256 From<&'a alloy_consensus::BlockBody<T, H>> for BlockBody<'a, T, H>
257 {
258 fn from(value: &'a alloy_consensus::BlockBody<T, H>) -> Self {
259 Self {
260 transactions: value.transactions.iter().map(|tx| tx.as_repr()).collect(),
261 ommers: value.ommers.iter().map(|h| h.as_repr()).collect(),
262 withdrawals: Cow::Borrowed(&value.withdrawals),
263 }
264 }
265 }
266
267 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<BlockBody<'a, T, H>>
268 for alloy_consensus::BlockBody<T, H>
269 {
270 fn from(value: BlockBody<'a, T, H>) -> Self {
271 Self {
272 transactions: value
273 .transactions
274 .into_iter()
275 .map(SerdeBincodeCompat::from_repr)
276 .collect(),
277 ommers: value.ommers.into_iter().map(SerdeBincodeCompat::from_repr).collect(),
278 withdrawals: value.withdrawals.into_owned(),
279 }
280 }
281 }
282
283 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::BlockBody<T, H>>
284 for BlockBody<'_, T, H>
285 {
286 fn serialize_as<S>(
287 source: &alloy_consensus::BlockBody<T, H>,
288 serializer: S,
289 ) -> Result<S::Ok, S::Error>
290 where
291 S: Serializer,
292 {
293 BlockBody::from(source).serialize(serializer)
294 }
295 }
296
297 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
298 DeserializeAs<'de, alloy_consensus::BlockBody<T, H>> for BlockBody<'de, T, H>
299 {
300 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::BlockBody<T, H>, D::Error>
301 where
302 D: Deserializer<'de>,
303 {
304 BlockBody::deserialize(deserializer).map(Into::into)
305 }
306 }
307
308 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
309 for alloy_consensus::BlockBody<T, H>
310 {
311 type BincodeRepr<'a> = BlockBody<'a, T, H>;
312
313 fn as_repr(&self) -> Self::BincodeRepr<'_> {
314 self.into()
315 }
316
317 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
318 repr.into()
319 }
320 }
321
322 impl super::SerdeBincodeCompat for alloy_consensus::EthereumTxEnvelope<TxEip4844> {
323 type BincodeRepr<'a> =
324 alloy_consensus::serde_bincode_compat::transaction::EthereumTxEnvelope<'a>;
325
326 fn as_repr(&self) -> Self::BincodeRepr<'_> {
327 self.into()
328 }
329
330 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
331 repr.into()
332 }
333 }
334
335 #[cfg(feature = "op")]
336 impl super::SerdeBincodeCompat for op_alloy_consensus::OpTxEnvelope {
337 type BincodeRepr<'a> =
338 op_alloy_consensus::serde_bincode_compat::transaction::OpTxEnvelope<'a>;
339
340 fn as_repr(&self) -> Self::BincodeRepr<'_> {
341 self.into()
342 }
343
344 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
345 repr.into()
346 }
347 }
348}