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!("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef");
77        let mut data = vec![];
78        let request = RequestPair {
79            request_id: 1111,
80            message: GetReceipts(vec![
81                hex!("00000000000000000000000000000000000000000000000000000000deadc0de").into(),
82                hex!("00000000000000000000000000000000000000000000000000000000feedbeef").into(),
83            ]),
84        };
85        request.encode(&mut data);
86        assert_eq!(data, expected);
87    }
88
89    #[test]
90    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
91    fn decode_get_receipts() {
92        let data = hex!("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef");
93        let request = RequestPair::<GetReceipts>::decode(&mut &data[..]).unwrap();
94        assert_eq!(
95            request,
96            RequestPair {
97                request_id: 1111,
98                message: GetReceipts(vec![
99                    hex!("00000000000000000000000000000000000000000000000000000000deadc0de").into(),
100                    hex!("00000000000000000000000000000000000000000000000000000000feedbeef").into(),
101                ]),
102            }
103        );
104    }
105
106    // Test vector from: https://eips.ethereum.org/EIPS/eip-2481
107    #[test]
108    fn encode_receipts() {
109        let expected = hex!("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff");
110        let mut data = vec![];
111        let request = RequestPair {
112            request_id: 1111,
113            message: Receipts(vec![vec![
114                ReceiptWithBloom {
115                    receipt: Receipt {
116                        tx_type: TxType::Legacy,
117                        cumulative_gas_used: 0x1u64,
118                        logs: vec![
119                            Log::new_unchecked(
120                                hex!("0000000000000000000000000000000000000011").into(),
121                                vec![
122                                    hex!("000000000000000000000000000000000000000000000000000000000000dead").into(),
123                                    hex!("000000000000000000000000000000000000000000000000000000000000beef").into(),
124                                ],
125                                hex!("0100ff")[..].into(),
126                            ),
127                        ],
128                        success: false,
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    fn decode_receipts() {
141        let data = hex!("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff");
142        let request = RequestPair::<Receipts>::decode(&mut &data[..]).unwrap();
143        assert_eq!(
144            request,
145            RequestPair {
146                request_id: 1111,
147                message: Receipts(vec![
148                    vec![
149                        ReceiptWithBloom {
150                            receipt: Receipt {
151                                tx_type: TxType::Legacy,
152                                cumulative_gas_used: 0x1u64,
153                                logs: vec![
154                                    Log::new_unchecked(
155                                        hex!("0000000000000000000000000000000000000011").into(),
156                                        vec![
157                                            hex!("000000000000000000000000000000000000000000000000000000000000dead").into(),
158                                            hex!("000000000000000000000000000000000000000000000000000000000000beef").into(),
159                                        ],
160                                        hex!("0100ff")[..].into(),
161                                    ),
162                                ],
163                                success: false,
164                            },
165                            logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(),
166                        },
167                    ],
168                ]),
169            }
170        );
171    }
172}