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