1use alloy_primitives::bytes::Bytes;
7use alloy_rlp::Encodable;
8use reth_net_banlist::BanList;
9use reth_net_nat::{NatResolver, ResolveNatInterval};
10use reth_network_peers::NodeRecord;
11use std::{
12 collections::{HashMap, HashSet},
13 time::Duration,
14};
15
16#[derive(Clone, Debug)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct Discv4Config {
20 pub enable_packet_filter: bool,
22 pub udp_egress_message_buffer: usize,
24 pub udp_ingress_message_buffer: usize,
26 pub max_find_node_failures: u8,
28 pub ping_interval: Duration,
31 pub ping_expiration: Duration,
33 pub lookup_interval: Duration,
35 pub request_timeout: Duration,
37 pub enr_expiration: Duration,
39 pub neighbours_expiration: Duration,
41 #[cfg_attr(feature = "serde", serde(skip))]
43 pub ban_list: BanList,
44 pub ban_duration: Option<Duration>,
48 pub bootstrap_nodes: HashSet<NodeRecord>,
50 pub enable_dht_random_walk: bool,
54 pub enable_lookup: bool,
56 pub enable_eip868: bool,
58 pub enforce_expiration_timestamps: bool,
60 pub additional_eip868_rlp_pairs: HashMap<Vec<u8>, Bytes>,
62 pub external_ip_resolver: Option<NatResolver>,
64 pub resolve_external_ip_interval: Option<Duration>,
67 pub bond_expiration: Duration,
69}
70
71impl Discv4Config {
72 pub fn builder() -> Discv4ConfigBuilder {
74 Default::default()
75 }
76
77 pub fn add_eip868_pair(&mut self, key: impl Into<Vec<u8>>, value: impl Encodable) -> &mut Self {
79 self.add_eip868_rlp_pair(key, Bytes::from(alloy_rlp::encode(&value)))
80 }
81
82 pub fn add_eip868_rlp_pair(&mut self, key: impl Into<Vec<u8>>, rlp: Bytes) -> &mut Self {
84 self.additional_eip868_rlp_pairs.insert(key.into(), rlp);
85 self
86 }
87
88 pub fn extend_eip868_rlp_pairs(
90 &mut self,
91 pairs: impl IntoIterator<Item = (impl Into<Vec<u8>>, Bytes)>,
92 ) -> &mut Self {
93 for (k, v) in pairs {
94 self.add_eip868_rlp_pair(k, v);
95 }
96 self
97 }
98
99 pub fn resolve_external_ip_interval(&self) -> Option<ResolveNatInterval> {
102 let resolver = self.external_ip_resolver?;
103 let interval = self.resolve_external_ip_interval?;
104 Some(ResolveNatInterval::interval(resolver, interval))
105 }
106}
107
108impl Default for Discv4Config {
109 fn default() -> Self {
110 Self {
111 enable_packet_filter: false,
112 udp_egress_message_buffer: 1024,
116 udp_ingress_message_buffer: 1024,
118 max_find_node_failures: 5,
119 ping_interval: Duration::from_secs(10),
120 ping_expiration: Duration::from_secs(20),
122 bond_expiration: Duration::from_secs(60 * 60),
123 enr_expiration: Duration::from_secs(20),
124 neighbours_expiration: Duration::from_secs(20),
125 request_timeout: Duration::from_secs(20),
126
127 lookup_interval: Duration::from_secs(20),
128 ban_list: Default::default(),
129 ban_duration: Some(Duration::from_secs(60 * 60)), bootstrap_nodes: Default::default(),
131 enable_dht_random_walk: true,
132 enable_lookup: true,
133 enable_eip868: true,
134 enforce_expiration_timestamps: true,
135 additional_eip868_rlp_pairs: Default::default(),
136 external_ip_resolver: Some(Default::default()),
137 resolve_external_ip_interval: Some(Duration::from_secs(60 * 5)),
139 }
140 }
141}
142
143#[derive(Clone, Debug, Default)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
146pub struct Discv4ConfigBuilder {
147 config: Discv4Config,
148}
149
150impl Discv4ConfigBuilder {
151 pub fn enable_packet_filter(&mut self) -> &mut Self {
153 self.config.enable_packet_filter = true;
154 self
155 }
156
157 pub fn udp_ingress_message_buffer(&mut self, udp_ingress_message_buffer: usize) -> &mut Self {
159 self.config.udp_ingress_message_buffer = udp_ingress_message_buffer;
160 self
161 }
162
163 pub fn udp_egress_message_buffer(&mut self, udp_egress_message_buffer: usize) -> &mut Self {
165 self.config.udp_egress_message_buffer = udp_egress_message_buffer;
166 self
167 }
168
169 pub fn max_find_node_failures(&mut self, max_find_node_failures: u8) -> &mut Self {
171 self.config.max_find_node_failures = max_find_node_failures;
172 self
173 }
174
175 pub fn ping_interval(&mut self, interval: Duration) -> &mut Self {
177 self.config.ping_interval = interval;
178 self
179 }
180
181 pub fn request_timeout(&mut self, duration: Duration) -> &mut Self {
183 self.config.request_timeout = duration;
184 self
185 }
186
187 pub fn ping_expiration(&mut self, duration: Duration) -> &mut Self {
189 self.config.ping_expiration = duration;
190 self
191 }
192
193 pub fn enr_request_expiration(&mut self, duration: Duration) -> &mut Self {
195 self.config.enr_expiration = duration;
196 self
197 }
198
199 pub fn lookup_neighbours_expiration(&mut self, duration: Duration) -> &mut Self {
201 self.config.neighbours_expiration = duration;
202 self
203 }
204
205 pub fn bond_expiration(&mut self, duration: Duration) -> &mut Self {
207 self.config.bond_expiration = duration;
208 self
209 }
210
211 pub fn enable_dht_random_walk(&mut self, enable_dht_random_walk: bool) -> &mut Self {
213 self.config.enable_dht_random_walk = enable_dht_random_walk;
214 self
215 }
216
217 pub fn enable_lookup(&mut self, enable_lookup: bool) -> &mut Self {
219 self.config.enable_lookup = enable_lookup;
220 self
221 }
222
223 pub fn enable_eip868(&mut self, enable_eip868: bool) -> &mut Self {
225 self.config.enable_eip868 = enable_eip868;
226 self
227 }
228
229 pub fn enforce_expiration_timestamps(
231 &mut self,
232 enforce_expiration_timestamps: bool,
233 ) -> &mut Self {
234 self.config.enforce_expiration_timestamps = enforce_expiration_timestamps;
235 self
236 }
237
238 pub fn add_eip868_pair(&mut self, key: impl Into<Vec<u8>>, value: impl Encodable) -> &mut Self {
240 self.add_eip868_rlp_pair(key, Bytes::from(alloy_rlp::encode(&value)))
241 }
242
243 pub fn add_eip868_rlp_pair(&mut self, key: impl Into<Vec<u8>>, rlp: Bytes) -> &mut Self {
245 self.config.additional_eip868_rlp_pairs.insert(key.into(), rlp);
246 self
247 }
248
249 pub fn extend_eip868_rlp_pairs(
251 &mut self,
252 pairs: impl IntoIterator<Item = (impl Into<Vec<u8>>, Bytes)>,
253 ) -> &mut Self {
254 for (k, v) in pairs {
255 self.add_eip868_rlp_pair(k, v);
256 }
257 self
258 }
259
260 pub fn ban_list(&mut self, ban_list: BanList) -> &mut Self {
263 self.config.ban_list = ban_list;
264 self
265 }
266
267 pub fn lookup_interval(&mut self, lookup_interval: Duration) -> &mut Self {
269 self.config.lookup_interval = lookup_interval;
270 self
271 }
272
273 pub fn ban_duration(&mut self, ban_duration: Option<Duration>) -> &mut Self {
277 self.config.ban_duration = ban_duration;
278 self
279 }
280
281 pub fn add_boot_node(&mut self, node: NodeRecord) -> &mut Self {
283 self.config.bootstrap_nodes.insert(node);
284 self
285 }
286
287 pub fn add_boot_nodes(&mut self, nodes: impl IntoIterator<Item = NodeRecord>) -> &mut Self {
289 self.config.bootstrap_nodes.extend(nodes);
290 self
291 }
292
293 pub fn external_ip_resolver(&mut self, external_ip_resolver: Option<NatResolver>) -> &mut Self {
295 self.config.external_ip_resolver = external_ip_resolver;
296 self
297 }
298
299 pub fn resolve_external_ip_interval(
301 &mut self,
302 resolve_external_ip_interval: Option<Duration>,
303 ) -> &mut Self {
304 self.config.resolve_external_ip_interval = resolve_external_ip_interval;
305 self
306 }
307
308 pub fn build(&self) -> Discv4Config {
310 self.config.clone()
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn test_config_builder() {
320 let mut builder = Discv4Config::builder();
321 let _ = builder
322 .enable_lookup(true)
323 .enable_dht_random_walk(true)
324 .add_boot_nodes(HashSet::new())
325 .ban_duration(None)
326 .lookup_interval(Duration::from_secs(3))
327 .enable_lookup(true)
328 .build();
329 }
330}