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 const fn enable_packet_filter(&mut self) -> &mut Self {
153 self.config.enable_packet_filter = true;
154 self
155 }
156
157 pub const fn udp_ingress_message_buffer(
159 &mut self,
160 udp_ingress_message_buffer: usize,
161 ) -> &mut Self {
162 self.config.udp_ingress_message_buffer = udp_ingress_message_buffer;
163 self
164 }
165
166 pub const fn udp_egress_message_buffer(
168 &mut self,
169 udp_egress_message_buffer: usize,
170 ) -> &mut Self {
171 self.config.udp_egress_message_buffer = udp_egress_message_buffer;
172 self
173 }
174
175 pub const fn max_find_node_failures(&mut self, max_find_node_failures: u8) -> &mut Self {
177 self.config.max_find_node_failures = max_find_node_failures;
178 self
179 }
180
181 pub const fn ping_interval(&mut self, interval: Duration) -> &mut Self {
183 self.config.ping_interval = interval;
184 self
185 }
186
187 pub const fn request_timeout(&mut self, duration: Duration) -> &mut Self {
189 self.config.request_timeout = duration;
190 self
191 }
192
193 pub const fn ping_expiration(&mut self, duration: Duration) -> &mut Self {
195 self.config.ping_expiration = duration;
196 self
197 }
198
199 pub const fn enr_request_expiration(&mut self, duration: Duration) -> &mut Self {
201 self.config.enr_expiration = duration;
202 self
203 }
204
205 pub const fn lookup_neighbours_expiration(&mut self, duration: Duration) -> &mut Self {
207 self.config.neighbours_expiration = duration;
208 self
209 }
210
211 pub const fn bond_expiration(&mut self, duration: Duration) -> &mut Self {
213 self.config.bond_expiration = duration;
214 self
215 }
216
217 pub const fn enable_dht_random_walk(&mut self, enable_dht_random_walk: bool) -> &mut Self {
219 self.config.enable_dht_random_walk = enable_dht_random_walk;
220 self
221 }
222
223 pub const fn enable_lookup(&mut self, enable_lookup: bool) -> &mut Self {
225 self.config.enable_lookup = enable_lookup;
226 self
227 }
228
229 pub const fn enable_eip868(&mut self, enable_eip868: bool) -> &mut Self {
231 self.config.enable_eip868 = enable_eip868;
232 self
233 }
234
235 pub const fn enforce_expiration_timestamps(
237 &mut self,
238 enforce_expiration_timestamps: bool,
239 ) -> &mut Self {
240 self.config.enforce_expiration_timestamps = enforce_expiration_timestamps;
241 self
242 }
243
244 pub fn add_eip868_pair(&mut self, key: impl Into<Vec<u8>>, value: impl Encodable) -> &mut Self {
246 self.add_eip868_rlp_pair(key, Bytes::from(alloy_rlp::encode(&value)))
247 }
248
249 pub fn add_eip868_rlp_pair(&mut self, key: impl Into<Vec<u8>>, rlp: Bytes) -> &mut Self {
251 self.config.additional_eip868_rlp_pairs.insert(key.into(), rlp);
252 self
253 }
254
255 pub fn extend_eip868_rlp_pairs(
257 &mut self,
258 pairs: impl IntoIterator<Item = (impl Into<Vec<u8>>, Bytes)>,
259 ) -> &mut Self {
260 for (k, v) in pairs {
261 self.add_eip868_rlp_pair(k, v);
262 }
263 self
264 }
265
266 pub fn ban_list(&mut self, ban_list: BanList) -> &mut Self {
269 self.config.ban_list = ban_list;
270 self
271 }
272
273 pub const fn lookup_interval(&mut self, lookup_interval: Duration) -> &mut Self {
275 self.config.lookup_interval = lookup_interval;
276 self
277 }
278
279 pub const fn ban_duration(&mut self, ban_duration: Option<Duration>) -> &mut Self {
283 self.config.ban_duration = ban_duration;
284 self
285 }
286
287 pub fn add_boot_node(&mut self, node: NodeRecord) -> &mut Self {
289 self.config.bootstrap_nodes.insert(node);
290 self
291 }
292
293 pub fn add_boot_nodes(&mut self, nodes: impl IntoIterator<Item = NodeRecord>) -> &mut Self {
295 self.config.bootstrap_nodes.extend(nodes);
296 self
297 }
298
299 pub const fn external_ip_resolver(
301 &mut self,
302 external_ip_resolver: Option<NatResolver>,
303 ) -> &mut Self {
304 self.config.external_ip_resolver = external_ip_resolver;
305 self
306 }
307
308 pub const fn resolve_external_ip_interval(
310 &mut self,
311 resolve_external_ip_interval: Option<Duration>,
312 ) -> &mut Self {
313 self.config.resolve_external_ip_interval = resolve_external_ip_interval;
314 self
315 }
316
317 pub fn build(&self) -> Discv4Config {
319 self.config.clone()
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 use super::*;
326
327 #[test]
328 fn test_config_builder() {
329 let mut builder = Discv4Config::builder();
330 let _ = builder
331 .enable_lookup(true)
332 .enable_dht_random_walk(true)
333 .add_boot_nodes(HashSet::new())
334 .ban_duration(None)
335 .lookup_interval(Duration::from_secs(3))
336 .enable_lookup(true)
337 .build();
338 }
339}