Skip to main content

reth_eth_wire_types/
blocks.rs

1//! Implements the `GetBlockHeaders`, `GetBlockBodies`, `BlockHeaders`, and `BlockBodies` message
2//! types.
3
4use crate::HeadersDirection;
5use alloc::vec::Vec;
6use alloy_eips::BlockHashOrNumber;
7use alloy_primitives::B256;
8use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};
9use derive_more::{Deref, IntoIterator};
10use reth_codecs_derive::{add_arbitrary_tests, generate_tests};
11
12/// A request for a peer to return block headers starting at the requested block.
13/// The peer must return at most [`limit`](#structfield.limit) headers.
14/// If the [`reverse`](#structfield.reverse) field is `true`, the headers will be returned starting
15/// at [`start_block`](#structfield.start_block), traversing towards the genesis block.
16/// Otherwise, headers will be returned starting at [`start_block`](#structfield.start_block),
17/// traversing towards the latest block.
18///
19/// If the [`skip`](#structfield.skip) field is non-zero, the peer must skip that amount of headers
20/// in the direction specified by [`reverse`](#structfield.reverse).
21#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
24#[add_arbitrary_tests(rlp)]
25pub struct GetBlockHeaders {
26    /// The block number or hash that the peer should start returning headers from.
27    pub start_block: BlockHashOrNumber,
28
29    /// The maximum number of headers to return.
30    pub limit: u64,
31
32    /// The number of blocks that the node should skip while traversing and returning headers.
33    /// A skip value of zero denotes that the peer should return contiguous headers, starting from
34    /// [`start_block`](#structfield.start_block) and returning at most
35    /// [`limit`](#structfield.limit) headers.
36    pub skip: u32,
37
38    /// The direction in which the headers should be returned in.
39    pub direction: HeadersDirection,
40}
41
42/// The response to [`GetBlockHeaders`], containing headers if any headers were found.
43#[derive(
44    Clone,
45    Debug,
46    PartialEq,
47    Eq,
48    RlpEncodableWrapper,
49    RlpDecodableWrapper,
50    Default,
51    Deref,
52    IntoIterator,
53)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
55#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
56pub struct BlockHeaders<H = alloy_consensus::Header>(
57    /// The requested headers.
58    pub Vec<H>,
59);
60
61generate_tests!(#[rlp, 10] BlockHeaders<alloy_consensus::Header>, EthBlockHeadersTests);
62
63impl<H> From<Vec<H>> for BlockHeaders<H> {
64    fn from(headers: Vec<H>) -> Self {
65        Self(headers)
66    }
67}
68
69/// A request for a peer to return block bodies for the given block hashes.
70#[derive(
71    Clone,
72    Debug,
73    PartialEq,
74    Eq,
75    RlpEncodableWrapper,
76    RlpDecodableWrapper,
77    Default,
78    Deref,
79    IntoIterator,
80)]
81#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
82#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
83#[add_arbitrary_tests(rlp)]
84pub struct GetBlockBodies(
85    /// The block hashes to request bodies for.
86    pub Vec<B256>,
87);
88
89impl From<Vec<B256>> for GetBlockBodies {
90    fn from(hashes: Vec<B256>) -> Self {
91        Self(hashes)
92    }
93}
94
95/// The response to [`GetBlockBodies`], containing the block bodies that the peer knows about if
96/// any were found.
97#[derive(
98    Clone,
99    Debug,
100    PartialEq,
101    Eq,
102    RlpEncodableWrapper,
103    RlpDecodableWrapper,
104    Default,
105    Deref,
106    IntoIterator,
107)]
108#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
109#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
110pub struct BlockBodies<B = reth_ethereum_primitives::BlockBody>(
111    /// The requested block bodies, each of which should correspond to a hash in the request.
112    pub Vec<B>,
113);
114
115generate_tests!(#[rlp, 16] BlockBodies<reth_ethereum_primitives::BlockBody>, EthBlockBodiesTests);
116
117impl<B> From<Vec<B>> for BlockBodies<B> {
118    fn from(bodies: Vec<B>) -> Self {
119        Self(bodies)
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use crate::{
126        message::RequestPair, BlockBodies, BlockHeaders, GetBlockBodies, GetBlockHeaders,
127        HeadersDirection,
128    };
129    use alloy_consensus::{Header, TxLegacy};
130    use alloy_eips::BlockHashOrNumber;
131    use alloy_primitives::{b256, hex, Address, Bloom, Signature, TxKind, B256, U256};
132    use alloy_rlp::{Decodable, Encodable};
133    use reth_ethereum_primitives::{BlockBody, Transaction, TransactionSigned};
134    use std::str::FromStr;
135
136    #[test]
137    fn decode_hash() {
138        // this is a valid 32 byte rlp string
139        let rlp = hex!("a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
140        let decoded_number = BlockHashOrNumber::decode(&mut &rlp[..]).unwrap();
141        let full_bytes = [0xff; 32].into();
142        let expected = BlockHashOrNumber::Hash(full_bytes);
143        assert_eq!(expected, decoded_number);
144    }
145
146    #[test]
147    fn decode_number() {
148        // this is a valid 64 bit number
149        let rlp = hex!("88ffffffffffffffff");
150        let decoded_number = BlockHashOrNumber::decode(&mut &rlp[..]).unwrap();
151        let expected = BlockHashOrNumber::Number(u64::MAX);
152        assert_eq!(expected, decoded_number);
153    }
154
155    #[test]
156    fn decode_largest_single_byte() {
157        // the largest single byte is 0x7f, so we should be able to decode this into a u64
158        let rlp = hex!("7f");
159        let decoded_number = BlockHashOrNumber::decode(&mut &rlp[..]).unwrap();
160        let expected = BlockHashOrNumber::Number(0x7fu64);
161        assert_eq!(expected, decoded_number);
162    }
163
164    #[test]
165    fn decode_long_hash() {
166        // let's try a 33 byte long string
167        // 0xa1 = 0x80 (start of string) + 0x21 (33, length of string)
168        let long_rlp = hex!("a1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
169        let decode_result = BlockHashOrNumber::decode(&mut &long_rlp[..]);
170        assert!(
171            decode_result.is_err(),
172            "Decoding a bytestring longer than 32 bytes should not decode successfully"
173        );
174    }
175
176    #[test]
177    fn decode_long_number() {
178        // let's try a 72 bit number
179        // 0x89 = 0x80 (start of string) + 0x09 (9, length of string)
180        let long_number = hex!("89ffffffffffffffffff");
181        let decode_result = BlockHashOrNumber::decode(&mut &long_number[..]);
182        assert!(
183            decode_result.is_err(),
184            "Decoding a number longer than 64 bits (but not exactly 32 bytes) should not decode successfully"
185        );
186    }
187
188    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
189    #[test]
190    fn encode_get_block_header() {
191        let expected = hex!(
192            "e8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580"
193        );
194        let mut data = vec![];
195        RequestPair::<GetBlockHeaders> {
196            request_id: 1111,
197            message: GetBlockHeaders {
198                start_block: BlockHashOrNumber::Hash(b256!(
199                    "00000000000000000000000000000000000000000000000000000000deadc0de"
200                )),
201                limit: 5,
202                skip: 5,
203                direction: HeadersDirection::Rising,
204            },
205        }
206        .encode(&mut data);
207        assert_eq!(data, expected);
208    }
209
210    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
211    #[test]
212    fn decode_get_block_header() {
213        let data = hex!(
214            "e8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580"
215        );
216        let expected = RequestPair::<GetBlockHeaders> {
217            request_id: 1111,
218            message: GetBlockHeaders {
219                start_block: BlockHashOrNumber::Hash(b256!(
220                    "00000000000000000000000000000000000000000000000000000000deadc0de"
221                )),
222                limit: 5,
223                skip: 5,
224                direction: HeadersDirection::Rising,
225            },
226        };
227        let result = RequestPair::decode(&mut &data[..]);
228        assert_eq!(result.unwrap(), expected);
229    }
230
231    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
232    #[test]
233    fn encode_get_block_header_number() {
234        let expected = hex!("ca820457c682270f050580");
235        let mut data = vec![];
236        RequestPair {
237            request_id: 1111,
238            message: GetBlockHeaders {
239                start_block: BlockHashOrNumber::Number(9999),
240                limit: 5,
241                skip: 5,
242                direction: HeadersDirection::Rising,
243            },
244        }
245        .encode(&mut data);
246        assert_eq!(data, expected);
247    }
248
249    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
250    #[test]
251    fn decode_get_block_header_number() {
252        let data = hex!("ca820457c682270f050580");
253        let expected = RequestPair {
254            request_id: 1111,
255            message: GetBlockHeaders {
256                start_block: BlockHashOrNumber::Number(9999),
257                limit: 5,
258                skip: 5,
259                direction: HeadersDirection::Rising,
260            },
261        };
262        let result = RequestPair::decode(&mut &data[..]);
263        assert_eq!(result.unwrap(), expected);
264    }
265
266    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
267    #[test]
268    fn encode_block_header() {
269        // [ (f90202) 0x0457 = 1111, [ (f901fc) [ (f901f9) header ] ] ]
270        let expected = hex!(
271            "f90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"
272        );
273        let mut data = vec![];
274        RequestPair {
275            request_id: 1111,
276            message: BlockHeaders(vec![Header {
277                parent_hash: B256::ZERO,
278                ommers_hash: B256::ZERO,
279                beneficiary: Address::ZERO,
280                state_root: B256::ZERO,
281                transactions_root: B256::ZERO,
282                receipts_root: B256::ZERO,
283                logs_bloom: Bloom::ZERO,
284                difficulty: U256::from(0x8aeu64),
285                number: 0xd05u64,
286                gas_limit: 0x115c,
287                gas_used: 0x15b3,
288                timestamp: 0x1a0au64,
289                extra_data: hex!("7788")[..].into(),
290                mix_hash: B256::ZERO,
291                nonce: 0x0000000000000000u64.into(),
292                base_fee_per_gas: None,
293                withdrawals_root: None,
294                blob_gas_used: None,
295                excess_blob_gas: None,
296                parent_beacon_block_root: None,
297                requests_hash: None,
298                block_access_list_hash: None,
299                slot_number: None,
300            }]),
301        }
302        .encode(&mut data);
303        assert_eq!(data, expected);
304    }
305
306    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
307    #[test]
308    fn decode_block_header() {
309        let data = hex!(
310            "f90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"
311        );
312        let expected = RequestPair {
313            request_id: 1111,
314            message: BlockHeaders(vec![Header {
315                parent_hash: B256::ZERO,
316                ommers_hash: B256::ZERO,
317                beneficiary: Address::ZERO,
318                state_root: B256::ZERO,
319                transactions_root: B256::ZERO,
320                receipts_root: B256::ZERO,
321                logs_bloom: Bloom::ZERO,
322                difficulty: U256::from(0x8aeu64),
323                number: 0xd05u64,
324                gas_limit: 0x115c,
325                gas_used: 0x15b3,
326                timestamp: 0x1a0au64,
327                extra_data: hex!("7788")[..].into(),
328                mix_hash: B256::ZERO,
329                nonce: 0x0000000000000000u64.into(),
330                base_fee_per_gas: None,
331                withdrawals_root: None,
332                blob_gas_used: None,
333                excess_blob_gas: None,
334                parent_beacon_block_root: None,
335                requests_hash: None,
336                block_access_list_hash: None,
337                slot_number: None,
338            }]),
339        };
340        let result = RequestPair::decode(&mut &data[..]);
341        assert_eq!(result.unwrap(), expected);
342    }
343
344    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
345    #[test]
346    fn encode_get_block_bodies() {
347        let expected = hex!(
348            "f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"
349        );
350        let mut data = vec![];
351        RequestPair {
352            request_id: 1111,
353            message: GetBlockBodies(vec![
354                b256!("00000000000000000000000000000000000000000000000000000000deadc0de"),
355                b256!("00000000000000000000000000000000000000000000000000000000feedbeef"),
356            ]),
357        }
358        .encode(&mut data);
359        assert_eq!(data, expected);
360    }
361
362    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
363    #[test]
364    fn decode_get_block_bodies() {
365        let data = hex!(
366            "f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"
367        );
368        let expected = RequestPair {
369            request_id: 1111,
370            message: GetBlockBodies(vec![
371                b256!("00000000000000000000000000000000000000000000000000000000deadc0de"),
372                b256!("00000000000000000000000000000000000000000000000000000000feedbeef"),
373            ]),
374        };
375        let result = RequestPair::decode(&mut &data[..]);
376        assert_eq!(result.unwrap(), expected);
377    }
378
379    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
380    #[test]
381    fn encode_block_bodies() {
382        let expected = hex!(
383            "f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"
384        );
385        let mut data = vec![];
386        let request = RequestPair {
387            request_id: 1111,
388            message: BlockBodies(vec![
389                BlockBody {
390                    transactions: vec![
391                        TransactionSigned::new_unhashed(Transaction::Legacy(TxLegacy {
392                            chain_id: Some(1),
393                            nonce: 0x8u64,
394                            gas_price: 0x4a817c808,
395                            gas_limit: 0x2e248,
396                            to: TxKind::Call(Address::repeat_byte(0x35)),
397                            value: U256::from(0x200u64),
398                            input: Default::default(),
399                        }), Signature::new(
400                                U256::from_str("0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12").unwrap(),
401                                U256::from_str("0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10").unwrap(),
402                                false,
403                            ),
404                        ),
405                        TransactionSigned::new_unhashed(Transaction::Legacy(TxLegacy {
406                            chain_id: Some(1),
407                            nonce: 0x9u64,
408                            gas_price: 0x4a817c809,
409                            gas_limit: 0x33450,
410                            to: TxKind::Call(Address::repeat_byte(0x35)),
411                            value: U256::from(0x2d9u64),
412                            input: Default::default(),
413                        }), Signature::new(
414                                U256::from_str("0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb").unwrap(),
415                                U256::from_str("0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb").unwrap(),
416                                false,
417                            ),
418                        ),
419                    ],
420                    ommers: vec![
421                        Header {
422                            parent_hash: B256::ZERO,
423                            ommers_hash: B256::ZERO,
424                            beneficiary: Address::ZERO,
425                            state_root: B256::ZERO,
426                            transactions_root: B256::ZERO,
427                            receipts_root: B256::ZERO,
428                            logs_bloom: Bloom::ZERO,
429                            difficulty: U256::from(0x8aeu64),
430                            number: 0xd05u64,
431                            gas_limit: 0x115c,
432                            gas_used: 0x15b3,
433                            timestamp: 0x1a0au64,
434                            extra_data: hex!("7788")[..].into(),
435                            mix_hash: B256::ZERO,
436                            nonce: 0x0000000000000000u64.into(),
437                            base_fee_per_gas: None,
438                            withdrawals_root: None,
439                            blob_gas_used: None,
440                            excess_blob_gas: None,
441                            parent_beacon_block_root: None,
442                            requests_hash: None,
443                            block_access_list_hash: None,
444                            slot_number: None,
445                        },
446                    ],
447                    withdrawals: None,
448                }
449            ]),
450        };
451        request.encode(&mut data);
452        assert_eq!(data, expected);
453    }
454
455    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
456    #[test]
457    fn decode_block_bodies() {
458        let data = hex!(
459            "f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"
460        );
461        let expected = RequestPair {
462            request_id: 1111,
463            message: BlockBodies(vec![
464                BlockBody {
465                    transactions: vec![
466                        TransactionSigned::new_unhashed(Transaction::Legacy(
467                            TxLegacy {
468                                chain_id: Some(1),
469                                nonce: 0x8u64,
470                                gas_price: 0x4a817c808,
471                                gas_limit: 0x2e248,
472                                to: TxKind::Call(Address::repeat_byte(0x35)),
473                                value: U256::from(0x200u64),
474                                input: Default::default(),
475                            }),
476                                                        Signature::new(
477                                U256::from_str("0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12").unwrap(),
478                                U256::from_str("0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10").unwrap(),
479                                false,
480                            ),
481                        ),
482                        TransactionSigned::new_unhashed(
483                            Transaction::Legacy(TxLegacy {
484                                chain_id: Some(1),
485                                nonce: 0x9u64,
486                                gas_price: 0x4a817c809,
487                                gas_limit: 0x33450,
488                                to: TxKind::Call(Address::repeat_byte(0x35)),
489                                value: U256::from(0x2d9u64),
490                                input: Default::default(),
491                            }),
492                            Signature::new(
493                                U256::from_str("0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb").unwrap(),
494                                U256::from_str("0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb").unwrap(),
495                                false,
496                            ),
497                        ),
498                    ],
499                    ommers: vec![
500                        Header {
501                            parent_hash: B256::ZERO,
502                            ommers_hash: B256::ZERO,
503                            beneficiary: Address::ZERO,
504                            state_root: B256::ZERO,
505                            transactions_root: B256::ZERO,
506                            receipts_root: B256::ZERO,
507                            logs_bloom: Bloom::ZERO,
508                            difficulty: U256::from(0x8aeu64),
509                            number: 0xd05u64,
510                            gas_limit: 0x115c,
511                            gas_used: 0x15b3,
512                            timestamp: 0x1a0au64,
513                            extra_data: hex!("7788")[..].into(),
514                            mix_hash: B256::ZERO,
515                            nonce: 0x0000000000000000u64.into(),
516                            base_fee_per_gas: None,
517                            withdrawals_root: None,
518                            blob_gas_used: None,
519                            excess_blob_gas: None,
520                            parent_beacon_block_root: None,
521                            requests_hash: None,
522                            block_access_list_hash: None,
523                            slot_number: None,
524                        },
525                    ],
526                    withdrawals: None,
527                }
528            ]),
529        };
530        let result = RequestPair::decode(&mut &data[..]).unwrap();
531        assert_eq!(result, expected);
532    }
533
534    #[test]
535    fn empty_block_bodies_rlp() {
536        let body = BlockBodies::default();
537        let mut buf = Vec::new();
538        body.encode(&mut buf);
539        let decoded = BlockBodies::<BlockBody>::decode(&mut buf.as_slice()).unwrap();
540        assert_eq!(body, decoded);
541    }
542}