-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathconfig.rs
341 lines (286 loc) · 14.1 KB
/
config.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
use crate::{
kbucket::MAX_NODES_PER_BUCKET, socket::ListenConfig, Enr, Executor, PermitBanList, RateLimiter,
RateLimiterBuilder,
};
///! A set of configuration parameters to tune the discovery protocol.
use std::time::Duration;
/// Configuration parameters that define the performance of the discovery network.
#[derive(Clone)]
pub struct Discv5Config {
/// Whether to enable the incoming packet filter. Default: false.
pub enable_packet_filter: bool,
/// The request timeout for each UDP request. Default: 1 seconds.
pub request_timeout: Duration,
/// The interval over which votes are remembered when determining our external IP. A lower
/// interval will respond faster to IP changes. Default is 30 seconds.
pub vote_duration: Duration,
/// The timeout after which a `QueryPeer` in an ongoing query is marked unresponsive.
/// Unresponsive peers don't count towards the parallelism limits for a query.
/// Hence, we may potentially end up making more requests to good peers. Default: 2 seconds.
pub query_peer_timeout: Duration,
/// The timeout for an entire query. Any peers discovered for this query are returned. Default 60 seconds.
pub query_timeout: Duration,
/// The number of retries for each UDP request. Default: 1.
pub request_retries: u8,
/// The session timeout for each node. Default: 1 day.
pub session_timeout: Duration,
/// The maximum number of established sessions to maintain. Default: 1000.
pub session_cache_capacity: usize,
/// Updates the local ENR IP and port based on PONG responses from peers. Default: true.
pub enr_update: bool,
/// The maximum number of nodes we return to a find nodes request. The default is 16.
pub max_nodes_response: usize,
/// The minimum number of peer's who agree on an external IP port before updating the
/// local ENR. Default: 10.
pub enr_peer_update_min: usize,
/// The number of peers to request in parallel in a single query. Default: 3.
pub query_parallelism: usize,
/// Limits the number of IP addresses from the same
/// /24 subnet in the kbuckets table. This is to mitigate eclipse attacks. Default: false.
pub ip_limit: bool,
/// Sets a maximum limit to the number of incoming nodes (nodes that have dialed us) to exist per-bucket. This cannot be larger
/// than the bucket size (16). By default this is disabled (set to the maximum bucket size, 16).
pub incoming_bucket_limit: usize,
/// A filter used to decide whether to insert nodes into our local routing table. Nodes can be
/// excluded if they do not pass this filter. The default is to accept all nodes.
pub table_filter: fn(&Enr) -> bool,
/// The time between pings to ensure connectivity amongst connected nodes. Default: 300
/// seconds.
pub ping_interval: Duration,
/// Reports all discovered ENR's when traversing the DHT to the event stream. Default true.
pub report_discovered_peers: bool,
/// A set of configuration parameters for setting inbound request rate limits. See
/// [`RateLimiterBuilder`] for options. This is only functional if the packet filter is
/// enabled via the `enable_packet_filter` option. See the `Default` implementation for
/// default values. If set to None, inbound requests are not filtered.
pub filter_rate_limiter: Option<RateLimiter>,
/// The maximum number of node-ids allowed per IP address before the IP address gets banned.
/// Having this set to None, disables this feature. Default value is 10. This is only
/// applicable if the `enable_packet_filter` option is set.
pub filter_max_nodes_per_ip: Option<usize>,
/// The maximum number of nodes that can be banned by a single IP before that IP gets banned.
/// The default is 5. This is only
/// applicable if the `enable_packet_filter` option is set.
pub filter_max_bans_per_ip: Option<usize>,
/// A set of lists that permit or ban IP's or NodeIds from the server. See
/// `crate::PermitBanList`.
pub permit_ban_list: PermitBanList,
/// Set the default duration for which nodes are banned for. This timeouts are checked every 5 minutes,
/// so the precision will be to the nearest 5 minutes. If set to `None`, bans from the filter
/// will last indefinitely. Default is 1 hour.
pub ban_duration: Option<Duration>,
/// A custom executor which can spawn the discv5 tasks. This must be a tokio runtime, with
/// timing support. By default, the executor that created the discv5 struct will be used.
pub executor: Option<Box<dyn Executor + Send + Sync>>,
/// Configuration for the sockets to listen on.
pub listen_config: ListenConfig,
}
#[derive(Debug)]
pub struct Discv5ConfigBuilder {
config: Discv5Config,
}
impl Discv5ConfigBuilder {
pub fn new(listen_config: ListenConfig) -> Self {
// This is only applicable if enable_packet_filter is set.
let filter_rate_limiter = Some(
RateLimiterBuilder::new()
.total_n_every(10, Duration::from_secs(1)) // Allow bursts, average 10 per second
.node_n_every(8, Duration::from_secs(1)) // Allow bursts, average 8 per second
.ip_n_every(9, Duration::from_secs(1)) // Allow bursts, average 9 per second
.build()
.expect("The total rate limit has been specified"),
);
// set default values
let config = Discv5Config {
enable_packet_filter: false,
request_timeout: Duration::from_secs(1),
vote_duration: Duration::from_secs(30),
query_peer_timeout: Duration::from_secs(2),
query_timeout: Duration::from_secs(60),
request_retries: 1,
session_timeout: Duration::from_secs(86400),
session_cache_capacity: 1000,
enr_update: true,
max_nodes_response: 16,
enr_peer_update_min: 10,
query_parallelism: 3,
ip_limit: false,
incoming_bucket_limit: MAX_NODES_PER_BUCKET,
table_filter: |_| true,
ping_interval: Duration::from_secs(300),
report_discovered_peers: true,
filter_rate_limiter,
filter_max_nodes_per_ip: Some(10),
filter_max_bans_per_ip: Some(5),
permit_ban_list: PermitBanList::default(),
ban_duration: Some(Duration::from_secs(3600)), // 1 hour
executor: None,
listen_config,
};
Discv5ConfigBuilder { config }
}
/// Whether to enable the incoming packet filter.
pub fn enable_packet_filter(&mut self) -> &mut Self {
self.config.enable_packet_filter = true;
self
}
/// The request timeout for each UDP request.
pub fn request_timeout(&mut self, timeout: Duration) -> &mut Self {
self.config.request_timeout = timeout;
self
}
/// The interval over which votes are remembered when determining our external IP. A lower
/// interval will respond faster to IP changes. Default is 30 seconds.
pub fn vote_duration(&mut self, vote_duration: Duration) -> &mut Self {
self.config.vote_duration = vote_duration;
self
}
/// The timeout after which a `QueryPeer` in an ongoing query is marked unresponsive.
/// Unresponsive peers don't count towards the parallelism limits for a query.
/// Hence, we may potentially end up making more requests to good peers.
pub fn query_peer_timeout(&mut self, timeout: Duration) -> &mut Self {
self.config.query_peer_timeout = timeout;
self
}
/// The timeout for an entire query. Any peers discovered before this timeout are returned.
pub fn query_timeout(&mut self, timeout: Duration) -> &mut Self {
self.config.query_timeout = timeout;
self
}
/// The number of retries for each UDP request.
pub fn request_retries(&mut self, retries: u8) -> &mut Self {
self.config.request_retries = retries;
self
}
/// The session timeout for each node.
pub fn session_timeout(&mut self, timeout: Duration) -> &mut Self {
self.config.session_timeout = timeout;
self
}
/// The maximum number of established sessions to maintain.
pub fn session_cache_capacity(&mut self, capacity: usize) -> &mut Self {
self.config.session_cache_capacity = capacity;
self
}
/// Disables the auto-update of the local ENR IP and port based on PONG responses from peers.
pub fn disable_enr_update(&mut self) -> &mut Self {
self.config.enr_update = false;
self
}
/// The maximum number of nodes we response to a find nodes request.
pub fn max_nodes_response(&mut self, max: usize) -> &mut Self {
self.config.max_nodes_response = max;
self
}
/// The minimum number of peer's who agree on an external IP port before updating the
/// local ENR.
pub fn enr_peer_update_min(&mut self, min: usize) -> &mut Self {
if min < 2 {
panic!("Setting enr_peer_update_min to a value less than 2 will cause issues with discovery with peers behind NAT");
}
self.config.enr_peer_update_min = min;
self
}
/// The number of peers to request in parallel in a single query.
pub fn query_parallelism(&mut self, parallelism: usize) -> &mut Self {
self.config.query_parallelism = parallelism;
self
}
/// Limits the number of IP addresses from the same
/// /24 subnet in the kbuckets table. This is to mitigate eclipse attacks.
pub fn ip_limit(&mut self) -> &mut Self {
self.config.ip_limit = true;
self
}
/// Sets a maximum limit to the number of incoming nodes (nodes that have dialed us) to exist per-bucket. This cannot be larger
/// than the bucket size (16). By default, half of every bucket (8 positions) is the largest number of nodes that we accept that dial us.
pub fn incoming_bucket_limit(&mut self, limit: usize) -> &mut Self {
self.config.incoming_bucket_limit = limit;
self
}
/// A filter used to decide whether to insert nodes into our local routing table. Nodes can be
/// excluded if they do not pass this filter.
pub fn table_filter(&mut self, filter: fn(&Enr) -> bool) -> &mut Self {
self.config.table_filter = filter;
self
}
/// The time between pings to ensure connectivity amongst connected nodes.
pub fn ping_interval(&mut self, interval: Duration) -> &mut Self {
self.config.ping_interval = interval;
self
}
/// Disables reporting of discovered peers through the event stream.
pub fn disable_report_discovered_peers(&mut self) -> &mut Self {
self.config.report_discovered_peers = false;
self
}
/// A rate limiter for limiting inbound requests.
pub fn filter_rate_limiter(&mut self, rate_limiter: Option<RateLimiter>) -> &mut Self {
self.config.filter_rate_limiter = rate_limiter;
self
}
/// If the filter is enabled, sets the maximum number of nodes per IP before banning
/// the IP.
pub fn filter_max_nodes_per_ip(&mut self, max_nodes_per_ip: Option<usize>) -> &mut Self {
self.config.filter_max_nodes_per_ip = max_nodes_per_ip;
self
}
/// The maximum number of times nodes from a single IP can be banned, before the IP itself
/// gets banned.
pub fn filter_max_bans_per_ip(&mut self, max_bans_per_ip: Option<usize>) -> &mut Self {
self.config.filter_max_bans_per_ip = max_bans_per_ip;
self
}
/// A set of lists that permit or ban IP's or NodeIds from the server. See
/// `crate::PermitBanList`.
pub fn permit_ban_list(&mut self, list: PermitBanList) -> &mut Self {
self.config.permit_ban_list = list;
self
}
/// Set the default duration for which nodes are banned for. This timeouts are checked every 5 minutes,
/// so the precision will be to the nearest 5 minutes. If set to `None`, bans from the filter
/// will last indefinitely. Default is 1 hour.
pub fn ban_duration(&mut self, ban_duration: Option<Duration>) -> &mut Self {
self.config.ban_duration = ban_duration;
self
}
/// A custom executor which can spawn the discv5 tasks. This must be a tokio runtime, with
/// timing support.
pub fn executor(&mut self, executor: Box<dyn Executor + Send + Sync>) -> &mut Self {
self.config.executor = Some(executor);
self
}
pub fn build(&mut self) -> Discv5Config {
// If an executor is not provided, assume a current tokio runtime is running.
if self.config.executor.is_none() {
self.config.executor = Some(Box::<crate::executor::TokioExecutor>::default());
};
assert!(self.config.incoming_bucket_limit <= MAX_NODES_PER_BUCKET);
self.config.clone()
}
}
impl std::fmt::Debug for Discv5Config {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Discv5Config")
.field("filter_enabled", &self.enable_packet_filter)
.field("request_timeout", &self.request_timeout)
.field("vote_duration", &self.vote_duration)
.field("query_timeout", &self.query_timeout)
.field("query_peer_timeout", &self.query_peer_timeout)
.field("request_retries", &self.request_retries)
.field("session_timeout", &self.session_timeout)
.field("session_cache_capacity", &self.session_cache_capacity)
.field("enr_update", &self.enr_update)
.field("query_parallelism", &self.query_parallelism)
.field("report_discovered_peers", &self.report_discovered_peers)
.field("ip_limit", &self.ip_limit)
.field("filter_max_nodes_per_ip", &self.filter_max_nodes_per_ip)
.field("filter_max_bans_per_ip", &self.filter_max_bans_per_ip)
.field("ip_limit", &self.ip_limit)
.field("incoming_bucket_limit", &self.incoming_bucket_limit)
.field("ping_interval", &self.ping_interval)
.field("ban_duration", &self.ban_duration)
.field("listen_config", &self.listen_config)
.finish()
}
}