1use crate::{
2 download::DownloadClient,
3 error::{PeerRequestResult, RequestError},
4 full_block::NoopFullBlockClient,
5 priority::Priority,
6};
7use futures::Future;
8use reth_eth_wire_types::{
9 snap::{
10 AccountRangeMessage, BlockAccessListsMessage, ByteCodesMessage, GetAccountRangeMessage,
11 GetBlockAccessListsMessage, GetByteCodesMessage, GetStorageRangesMessage,
12 SnapProtocolMessage, StorageRangesMessage,
13 },
14 NetworkPrimitives,
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum SnapResponse {
20 AccountRange(AccountRangeMessage),
22 StorageRanges(StorageRangesMessage),
24 ByteCodes(ByteCodesMessage),
26 BlockAccessLists(BlockAccessListsMessage),
30}
31
32impl TryFrom<SnapProtocolMessage> for SnapResponse {
33 type Error = SnapProtocolMessage;
35
36 fn try_from(msg: SnapProtocolMessage) -> Result<Self, Self::Error> {
37 match msg {
38 SnapProtocolMessage::AccountRange(m) => Ok(Self::AccountRange(m)),
39 SnapProtocolMessage::StorageRanges(m) => Ok(Self::StorageRanges(m)),
40 SnapProtocolMessage::ByteCodes(m) => Ok(Self::ByteCodes(m)),
41 SnapProtocolMessage::BlockAccessLists(m) => Ok(Self::BlockAccessLists(m)),
42 request => Err(request),
43 }
44 }
45}
46
47impl From<SnapResponse> for SnapProtocolMessage {
48 fn from(response: SnapResponse) -> Self {
49 match response {
50 SnapResponse::AccountRange(m) => Self::AccountRange(m),
51 SnapResponse::StorageRanges(m) => Self::StorageRanges(m),
52 SnapResponse::ByteCodes(m) => Self::ByteCodes(m),
53 SnapResponse::BlockAccessLists(m) => Self::BlockAccessLists(m),
54 }
55 }
56}
57
58#[auto_impl::auto_impl(&, Arc, Box)]
60pub trait SnapClient: DownloadClient {
61 type Output: Future<Output = PeerRequestResult<SnapResponse>> + Send + Sync + Unpin;
63
64 fn get_account_range(&self, request: GetAccountRangeMessage) -> Self::Output {
67 self.get_account_range_with_priority(request, Priority::Normal)
68 }
69
70 fn get_account_range_with_priority(
73 &self,
74 request: GetAccountRangeMessage,
75 priority: Priority,
76 ) -> Self::Output;
77
78 fn get_storage_ranges(&self, request: GetStorageRangesMessage) -> Self::Output;
81
82 fn get_storage_ranges_with_priority(
85 &self,
86 request: GetStorageRangesMessage,
87 priority: Priority,
88 ) -> Self::Output;
89
90 fn get_byte_codes(&self, request: GetByteCodesMessage) -> Self::Output;
93
94 fn get_byte_codes_with_priority(
97 &self,
98 request: GetByteCodesMessage,
99 priority: Priority,
100 ) -> Self::Output;
101
102 fn get_block_access_lists(&self, request: GetBlockAccessListsMessage) -> Self::Output {
107 self.get_block_access_lists_with_priority(request, Priority::Normal)
108 }
109
110 fn get_block_access_lists_with_priority(
115 &self,
116 request: GetBlockAccessListsMessage,
117 priority: Priority,
118 ) -> Self::Output;
119}
120
121impl<Net> SnapClient for NoopFullBlockClient<Net>
124where
125 Net: NetworkPrimitives,
126{
127 type Output = futures::future::Ready<PeerRequestResult<SnapResponse>>;
128
129 fn get_account_range_with_priority(
131 &self,
132 _request: GetAccountRangeMessage,
133 _priority: Priority,
134 ) -> Self::Output {
135 unsupported()
136 }
137
138 fn get_storage_ranges(&self, _request: GetStorageRangesMessage) -> Self::Output {
140 unsupported()
141 }
142
143 fn get_storage_ranges_with_priority(
145 &self,
146 _request: GetStorageRangesMessage,
147 _priority: Priority,
148 ) -> Self::Output {
149 unsupported()
150 }
151
152 fn get_byte_codes(&self, _request: GetByteCodesMessage) -> Self::Output {
154 unsupported()
155 }
156
157 fn get_byte_codes_with_priority(
159 &self,
160 _request: GetByteCodesMessage,
161 _priority: Priority,
162 ) -> Self::Output {
163 unsupported()
164 }
165
166 fn get_block_access_lists_with_priority(
168 &self,
169 _request: GetBlockAccessListsMessage,
170 _priority: Priority,
171 ) -> Self::Output {
172 unsupported()
173 }
174}
175
176fn unsupported() -> futures::future::Ready<PeerRequestResult<SnapResponse>> {
178 futures::future::ready(Err(RequestError::UnsupportedCapability))
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184 use reth_eth_wire_types::BlockAccessLists;
185 use test_case::test_case;
186
187 #[test_case(
188 SnapProtocolMessage::GetAccountRange(GetAccountRangeMessage {
189 request_id: 1, root_hash: Default::default(), starting_hash: Default::default(),
190 limit_hash: Default::default(), response_bytes: 0,
191 }), false ; "account range request is not a response"
192 )]
193 #[test_case(
194 SnapProtocolMessage::GetBlockAccessLists(GetBlockAccessListsMessage {
195 request_id: 1, block_hashes: vec![], response_bytes: 0,
196 }), false ; "block access lists request is not a response"
197 )]
198 #[test_case(
199 SnapProtocolMessage::AccountRange(AccountRangeMessage {
200 request_id: 1, accounts: vec![], proof: vec![],
201 }), true ; "account range response converts"
202 )]
203 #[test_case(
204 SnapProtocolMessage::ByteCodes(ByteCodesMessage { request_id: 1, codes: vec![] }),
205 true ; "byte codes response converts"
206 )]
207 #[test_case(
208 SnapProtocolMessage::BlockAccessLists(BlockAccessListsMessage {
209 request_id: 1, block_access_lists: BlockAccessLists(vec![]),
210 }), true ; "block access lists response converts"
211 )]
212 fn try_from_snap_message(msg: SnapProtocolMessage, is_response: bool) {
213 let original = msg.clone();
214 match SnapResponse::try_from(msg) {
215 Ok(_) => assert!(is_response),
216 Err(returned) => {
218 assert!(!is_response);
219 assert_eq!(returned, original);
220 }
221 }
222 }
223}