mirror of
https://github.com/0glabs/0g-storage-node.git
synced 2024-11-10 10:05:17 +00:00
340 lines
14 KiB
Rust
340 lines
14 KiB
Rust
use crate::{
|
|
kbucket::MAX_NODES_PER_BUCKET, 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 gossipsub 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: 2 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>>,
|
|
}
|
|
|
|
impl Default for Discv5Config {
|
|
fn default() -> 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"),
|
|
);
|
|
|
|
Self {
|
|
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,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct Discv5ConfigBuilder {
|
|
config: Discv5Config,
|
|
}
|
|
|
|
impl Discv5ConfigBuilder {
|
|
// set default values
|
|
pub fn new() -> Self {
|
|
Discv5ConfigBuilder::default()
|
|
}
|
|
|
|
/// 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::new(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 {
|
|
let mut builder = f.debug_struct("Discv5Config");
|
|
let _ = builder.field("filter_enabled", &self.enable_packet_filter);
|
|
let _ = builder.field("request_timeout", &self.request_timeout);
|
|
let _ = builder.field("vote_duration", &self.vote_duration);
|
|
let _ = builder.field("query_timeout", &self.query_timeout);
|
|
let _ = builder.field("query_peer_timeout", &self.query_peer_timeout);
|
|
let _ = builder.field("request_retries", &self.request_retries);
|
|
let _ = builder.field("session_timeout", &self.session_timeout);
|
|
let _ = builder.field("session_cache_capacity", &self.session_cache_capacity);
|
|
let _ = builder.field("enr_update", &self.enr_update);
|
|
let _ = builder.field("query_parallelism", &self.query_parallelism);
|
|
let _ = builder.field("report_discovered_peers", &self.report_discovered_peers);
|
|
let _ = builder.field("ip_limit", &self.ip_limit);
|
|
let _ = builder.field("filter_max_nodes_per_ip", &self.filter_max_nodes_per_ip);
|
|
let _ = builder.field("filter_max_bans_per_ip", &self.filter_max_bans_per_ip);
|
|
let _ = builder.field("ip_limit", &self.ip_limit);
|
|
let _ = builder.field("incoming_bucket_limit", &self.incoming_bucket_limit);
|
|
let _ = builder.field("ping_interval", &self.ping_interval);
|
|
let _ = builder.field("ban_duration", &self.ban_duration);
|
|
builder.finish()
|
|
}
|
|
}
|