Skip to main content

ethrex_p2p/discovery/
mod.rs

1//! Discovery protocol implementation for running both discv4 and discv5 on a shared UDP port.
2//!
3//! ## Packet Discrimination Strategy
4//!
5//! DiscV4 packets have a deterministic structure:
6//! `hash (32 bytes) || signature (65 bytes) || type (1 byte) || data`
7//! where `hash == keccak256(rest_of_packet)`.
8//!
9//! **Discrimination logic:**
10//! 1. If packet length >= 98 bytes AND `packet[0..32] == keccak256(packet[32..])` → DiscV4
11//! 2. Otherwise → DiscV5
12
13pub mod codec;
14mod discv4_handlers;
15mod discv5_handlers;
16pub mod lookup;
17pub mod server;
18
19pub use server::{DiscoveryServer, DiscoveryServerError, is_discv4_packet};
20
21use std::time::Duration;
22
23/// Configuration for which discovery protocols to enable.
24#[derive(Debug, Clone)]
25pub struct DiscoveryConfig {
26    pub discv4_enabled: bool,
27    pub discv5_enabled: bool,
28    pub initial_lookup_interval: f64,
29}
30
31impl Default for DiscoveryConfig {
32    fn default() -> Self {
33        Self {
34            discv4_enabled: true,
35            discv5_enabled: true,
36            initial_lookup_interval: INITIAL_LOOKUP_INTERVAL_MS,
37        }
38    }
39}
40
41/// Lookup interval constants shared by discv4, discv5, and RLPx initiator.
42pub const INITIAL_LOOKUP_INTERVAL_MS: f64 = 100.0; // 10 per second
43pub const LOOKUP_INTERVAL_MS: f64 = 600.0; // 100 per minute
44
45/// Smooth easing curve for discovery lookup intervals based on peer completion progress.
46///
47/// Shared by discv4, discv5, and RLPx initiator.
48pub fn lookup_interval_function(progress: f64, lower_limit: f64, upper_limit: f64) -> Duration {
49    // Smooth progression curve
50    // See https://easings.net/#easeInOutCubic
51    let ease_in_out_cubic = if progress < 0.5 {
52        4.0 * progress.powf(3.0)
53    } else {
54        1.0 - ((-2.0 * progress + 2.0).powf(3.0)) / 2.0
55    };
56    Duration::from_micros(
57        (1000f64 * (ease_in_out_cubic * (upper_limit - lower_limit) + lower_limit)).round() as u64,
58    )
59}