diff --git a/crates/net/discv4/src/config.rs b/crates/net/discv4/src/config.rs index 27e04a3721..764b70cefb 100644 --- a/crates/net/discv4/src/config.rs +++ b/crates/net/discv4/src/config.rs @@ -23,19 +23,19 @@ pub struct Discv4Config { pub udp_ingress_message_buffer: usize, /// The number of allowed failures for `FindNode` requests. Default: 1. pub max_find_node_failures: u8, - /// The time between pings to ensure connectivity amongst connected nodes. Default: 300 - /// seconds. + /// The interval to use when checking for expired nodes that need to be re-pinged. Default: + /// 300sec, 5min. pub ping_interval: Duration, /// The duration of we consider a ping timed out. - pub ping_timeout: Duration, + pub ping_expiration: Duration, /// The rate at which lookups should be triggered. pub lookup_interval: Duration, /// The duration of we consider a FindNode request timed out. pub request_timeout: Duration, /// The duration after which we consider an enr request timed out. - pub enr_timeout: Duration, + pub enr_expiration: Duration, /// The duration we set for neighbours responses - pub neighbours_timeout: Duration, + pub neighbours_expiration: Duration, /// Provides a way to ban peers and ips. pub ban_list: BanList, /// Set the default duration for which nodes are banned for. This timeouts are checked every 5 @@ -99,10 +99,12 @@ impl Default for Discv4Config { udp_ingress_message_buffer: 1024, max_find_node_failures: 2, ping_interval: Duration::from_secs(300), - ping_timeout: Duration::from_secs(5), + /// unified expiration and timeout durations, mirrors geth's `expiration` duration + ping_expiration: Duration::from_secs(20), + enr_expiration: Duration::from_secs(20), + neighbours_expiration: Duration::from_secs(20), request_timeout: Duration::from_secs(20), - enr_timeout: Duration::from_secs(5), - neighbours_timeout: Duration::from_secs(5), + lookup_interval: Duration::from_secs(20), ban_list: Default::default(), ban_duration: Some(Duration::from_secs(3600)), // 1 hour @@ -152,15 +154,21 @@ impl Discv4ConfigBuilder { self } - /// Sets the timeout for pings - pub fn ping_timeout(&mut self, duration: Duration) -> &mut Self { - self.config.ping_timeout = duration; + /// Sets the timeout after which requests are considered timed out + pub fn request_timeout(&mut self, duration: Duration) -> &mut Self { + self.config.request_timeout = duration; self } - /// Sets the timeout for enr requests - pub fn enr_request_timeout(&mut self, duration: Duration) -> &mut Self { - self.config.enr_timeout = duration; + /// Sets the expiration duration for pings + pub fn ping_expiration(&mut self, duration: Duration) -> &mut Self { + self.config.ping_expiration = duration; + self + } + + /// Sets the expiration duration for enr requests + pub fn enr_request_expiration(&mut self, duration: Duration) -> &mut Self { + self.config.enr_expiration = duration; self } diff --git a/crates/net/discv4/src/lib.rs b/crates/net/discv4/src/lib.rs index 3f2885003d..f9c0330ce7 100644 --- a/crates/net/discv4/src/lib.rs +++ b/crates/net/discv4/src/lib.rs @@ -91,8 +91,10 @@ const MAX_NODES_PING: usize = 2 * MAX_NODES_PER_BUCKET; /// rlp overhead) / size(rlp(Node_IPv6))` const SAFE_MAX_DATAGRAM_NEIGHBOUR_RECORDS: usize = (MAX_PACKET_SIZE - 109) / 91; -/// The timeout used to identify expired nodes -const NODE_LAST_SEEN_TIMEOUT: Duration = Duration::from_secs(24 * 60 * 60); +/// The timeout used to identify expired nodes, 24h +/// +/// Mirrors geth's `bondExpiration` of 24h +const ENDPOINT_PROOF_EXPIRATION: Duration = Duration::from_secs(24 * 60 * 60); type EgressSender = mpsc::Sender<(Bytes, SocketAddr)>; type EgressReceiver = mpsc::Receiver<(Bytes, SocketAddr)>; @@ -593,7 +595,7 @@ impl Discv4Service { trace!(target : "discv4", ?node, lookup=?ctx.target(), "Sending FindNode"); ctx.mark_queried(node.id); let id = ctx.target(); - let msg = Message::FindNode(FindNode { id, expire: self.find_node_timeout() }); + let msg = Message::FindNode(FindNode { id, expire: self.find_node_expiration() }); self.send_packet(msg, node.udp_addr()); self.pending_find_nodes.insert(node.id, FindNodeRequest::new(ctx)); } @@ -858,7 +860,7 @@ impl Discv4Service { let ping = Ping { from: self.local_node_record.into(), to: node.into(), - expire: self.ping_timeout(), + expire: self.ping_expiration(), enr_sq: self.enr_seq(), }; trace!(target : "discv4", ?ping, "sending ping"); @@ -877,7 +879,7 @@ impl Discv4Service { return } let remote_addr = node.udp_addr(); - let enr_request = EnrRequest { expire: self.enr_request_timeout() }; + let enr_request = EnrRequest { expire: self.enr_request_expiration() }; trace!(target : "discv4", ?enr_request, "sending enr request"); let echo_hash = self.send_packet(Message::EnrRequest(enr_request), remote_addr); @@ -1093,7 +1095,7 @@ impl Discv4Service { /// Sends a Neighbours packet for `target` to the given addr fn respond_closest(&mut self, target: PeerId, to: SocketAddr) { let key = kad_key(target); - let expire = self.send_neighbours_timeout(); + let expire = self.send_neighbours_expiration(); let all_nodes = self.kbuckets.closest_values(&key).collect::>(); for nodes in all_nodes.chunks(SAFE_MAX_DATAGRAM_NEIGHBOUR_RECORDS) { @@ -1106,12 +1108,12 @@ impl Discv4Service { fn evict_expired_requests(&mut self, now: Instant) { self.pending_enr_requests.retain(|_node_id, enr_request| { - now.duration_since(enr_request.sent_at) < self.config.ping_timeout + now.duration_since(enr_request.sent_at) < self.config.ping_expiration }); let mut failed_pings = Vec::new(); self.pending_pings.retain(|node_id, ping_request| { - if now.duration_since(ping_request.sent_at) > self.config.ping_timeout { + if now.duration_since(ping_request.sent_at) > self.config.ping_expiration { failed_pings.push(*node_id); return false } @@ -1161,8 +1163,11 @@ impl Discv4Service { } } - /// Send some pings - fn reping_oldest(&mut self) { + /// Re-pings all nodes which endpoint proofs are considered expired: [``NodeEntry::is_expired] + /// + /// This will send a `Ping` to the nodes, if a node fails to respond with a `Pong` to renew the + /// endpoint proof it will be removed from the table. + fn re_ping_oldest(&mut self) { let mut nodes = self .kbuckets .iter_ref() @@ -1201,21 +1206,23 @@ impl Discv4Service { } } - fn ping_timeout(&self) -> u64 { - (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.ping_timeout).as_secs() + fn ping_expiration(&self) -> u64 { + (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.ping_expiration) + .as_secs() } - fn find_node_timeout(&self) -> u64 { + fn find_node_expiration(&self) -> u64 { (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.request_timeout) .as_secs() } - fn enr_request_timeout(&self) -> u64 { - (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.enr_timeout).as_secs() + fn enr_request_expiration(&self) -> u64 { + (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.enr_expiration) + .as_secs() } - fn send_neighbours_timeout(&self) -> u64 { - (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.neighbours_timeout) + fn send_neighbours_expiration(&self) -> u64 { + (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + self.config.neighbours_expiration) .as_secs() } @@ -1238,7 +1245,7 @@ impl Discv4Service { // re-ping some peers if self.ping_interval.poll_tick(cx).is_ready() { - self.reping_oldest(); + self.re_ping_oldest(); } // process all incoming commands @@ -1694,9 +1701,9 @@ impl NodeEntry { // === impl NodeEntry === impl NodeEntry { - /// Returns true if the node is considered expired. + /// Returns true if the node should be re-pinged. fn is_expired(&self) -> bool { - self.last_seen.elapsed() > NODE_LAST_SEEN_TIMEOUT + self.last_seen.elapsed() > ENDPOINT_PROOF_EXPIRATION } }