reth_eth_wire_types/
receipts.rs

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