reth_eth_wire_types/
blocks.rs

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