reth_eth_wire_types/
receipts.rs

1//! Implements the `GetReceipts` and `Receipts` message types.
2
3use alloy_consensus::{RlpDecodableReceipt, RlpEncodableReceipt};
4use alloy_primitives::B256;
5use alloy_rlp::{RlpDecodableWrapper, RlpEncodableWrapper};
6use reth_codecs_derive::add_arbitrary_tests;
7use reth_primitives::{Receipt, ReceiptWithBloom};
8
9/// A request for transaction receipts from the given block hashes.
10#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
13#[add_arbitrary_tests(rlp)]
14pub struct GetReceipts(
15    /// The block hashes to request receipts for.
16    pub Vec<B256>,
17);
18
19/// The response to [`GetReceipts`], containing receipt lists that correspond to each block
20/// requested.
21#[derive(Clone, Debug, PartialEq, Eq, Default)]
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 Receipts<T = Receipt>(
26    /// Each receipt hash should correspond to a block hash in the request.
27    pub Vec<Vec<ReceiptWithBloom<T>>>,
28);
29
30impl<T: RlpEncodableReceipt> alloy_rlp::Encodable for Receipts<T> {
31    #[inline]
32    fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
33        self.0.encode(out)
34    }
35    #[inline]
36    fn length(&self) -> usize {
37        self.0.length()
38    }
39}
40
41impl<T: RlpDecodableReceipt> alloy_rlp::Decodable for Receipts<T> {
42    #[inline]
43    fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
44        alloy_rlp::Decodable::decode(buf).map(Self)
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use crate::{message::RequestPair, GetReceipts, Receipts};
51    use alloy_primitives::{hex, Log};
52    use alloy_rlp::{Decodable, Encodable};
53    use reth_primitives::{Receipt, ReceiptWithBloom, TxType};
54
55    #[test]
56    fn roundtrip_eip1559() {
57        let receipts = Receipts(vec![vec![ReceiptWithBloom {
58            receipt: Receipt { tx_type: TxType::Eip1559, ..Default::default() },
59            logs_bloom: Default::default(),
60        }]]);
61
62        let mut out = vec![];
63        receipts.encode(&mut out);
64
65        let mut out = out.as_slice();
66        let decoded = Receipts::decode(&mut out).unwrap();
67
68        assert_eq!(receipts, decoded);
69    }
70
71    #[test]
72    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
73    fn encode_get_receipts() {
74        let expected = hex!("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef");
75        let mut data = vec![];
76        let request = RequestPair {
77            request_id: 1111,
78            message: GetReceipts(vec![
79                hex!("00000000000000000000000000000000000000000000000000000000deadc0de").into(),
80                hex!("00000000000000000000000000000000000000000000000000000000feedbeef").into(),
81            ]),
82        };
83        request.encode(&mut data);
84        assert_eq!(data, expected);
85    }
86
87    #[test]
88    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
89    fn decode_get_receipts() {
90        let data = hex!("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef");
91        let request = RequestPair::<GetReceipts>::decode(&mut &data[..]).unwrap();
92        assert_eq!(
93            request,
94            RequestPair {
95                request_id: 1111,
96                message: GetReceipts(vec![
97                    hex!("00000000000000000000000000000000000000000000000000000000deadc0de").into(),
98                    hex!("00000000000000000000000000000000000000000000000000000000feedbeef").into(),
99                ]),
100            }
101        );
102    }
103
104    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
105    #[test]
106    #[allow(clippy::needless_update)]
107    fn encode_receipts() {
108        let expected = hex!("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff");
109        let mut data = vec![];
110        let request = RequestPair {
111            request_id: 1111,
112            message: Receipts(vec![vec![
113                ReceiptWithBloom {
114                    receipt: Receipt {
115                        tx_type: TxType::Legacy,
116                        cumulative_gas_used: 0x1u64,
117                        logs: vec![
118                            Log::new_unchecked(
119                                hex!("0000000000000000000000000000000000000011").into(),
120                                vec![
121                                    hex!("000000000000000000000000000000000000000000000000000000000000dead").into(),
122                                    hex!("000000000000000000000000000000000000000000000000000000000000beef").into(),
123                                ],
124                                hex!("0100ff")[..].into(),
125                            ),
126                        ],
127                        success: false,
128                        ..Default::default()
129                    },
130                    logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(),
131                },
132            ]]),
133        };
134        request.encode(&mut data);
135        assert_eq!(data, expected);
136    }
137
138    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
139    #[test]
140    #[allow(clippy::needless_update)]
141    fn decode_receipts() {
142        let data = hex!("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff");
143        let request = RequestPair::<Receipts>::decode(&mut &data[..]).unwrap();
144        assert_eq!(
145            request,
146            RequestPair {
147                request_id: 1111,
148                message: Receipts(vec![
149                    vec![
150                        ReceiptWithBloom {
151                            receipt: Receipt {
152                                tx_type: TxType::Legacy,
153                                cumulative_gas_used: 0x1u64,
154                                logs: vec![
155                                    Log::new_unchecked(
156                                        hex!("0000000000000000000000000000000000000011").into(),
157                                        vec![
158                                            hex!("000000000000000000000000000000000000000000000000000000000000dead").into(),
159                                            hex!("000000000000000000000000000000000000000000000000000000000000beef").into(),
160                                        ],
161                                        hex!("0100ff")[..].into(),
162                                    ),
163                                ],
164                                success: false,
165                                ..Default::default()
166                            },
167                            logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(),
168                        },
169                    ],
170                ]),
171            }
172        );
173    }
174}