hopr_transport_network/
config.rs1use std::time::Duration;
2
3use serde::{Deserialize, Serialize};
4use smart_default::SmartDefault;
5use validator::Validate;
6
7pub const DEFAULT_NETWORK_OFFLINE_QUALITY_THRESHOLD: f64 = 0.0;
10pub const DEFAULT_NETWORK_BAD_QUALITY_THRESHOLD: f64 = 0.1;
11pub const DEFAULT_NETWORK_QUALITY_STEP: f64 = 0.1;
12pub const DEFAULT_NETWORK_QUALITY_AVERAGE_WINDOW_SIZE: u32 = 25;
13pub const DEFAULT_NETWORK_BACKOFF_EXPONENT: f64 = 1.5;
14pub const DEFAULT_NETWORK_BACKOFF_MIN: f64 = 2.0;
15
16pub const DEFAULT_AUTO_PATH_QUALITY_THRESHOLD: f64 = 0.95;
17
18pub const DEFAULT_MAX_FIRST_HOP_LATENCY_THRESHOLD: Duration = Duration::from_millis(250);
19
20pub const DEFAULT_CANNOT_DIAL_PENALTY: Duration = Duration::from_secs(60 * 60); #[derive(Debug, Clone, Copy, Serialize, Deserialize, SmartDefault, PartialEq)]
24#[serde(deny_unknown_fields)]
25pub struct NetworkConfig {
26 #[serde(default = "duration_1_s", with = "humantime_serde")]
28 #[default(duration_1_s())]
29 pub min_delay: Duration,
30
31 #[serde(default = "duration_5_min", with = "humantime_serde")]
33 #[default(duration_5_min())]
34 pub max_delay: Duration,
35
36 #[serde(default = "quality_bad_threshold")]
37 #[default(quality_bad_threshold())]
38 pub quality_bad_threshold: f64,
39
40 #[serde(default = "quality_offline_threshold")]
41 #[default(quality_offline_threshold())]
42 pub quality_offline_threshold: f64,
43
44 #[serde(default = "node_score_auto_path_threshold")]
45 #[default(node_score_auto_path_threshold())]
46 pub node_score_auto_path_threshold: f64,
47
48 #[serde(default = "max_first_hop_latency_threshold", with = "humantime_serde")]
49 #[default(max_first_hop_latency_threshold())]
50 pub max_first_hop_latency_threshold: Option<Duration>,
51
52 #[serde(default = "quality_step")]
53 #[default(quality_step())]
54 pub quality_step: f64,
55
56 #[serde(default = "quality_average_window_size")]
57 #[default(quality_average_window_size())]
58 pub quality_avg_window_size: u32,
59
60 #[serde(default = "duration_2_min", with = "humantime_serde")]
61 #[default(duration_2_min())]
62 pub ignore_timeframe: Duration,
63
64 #[serde(default = "backoff_exponent")]
65 #[default(backoff_exponent())]
66 pub backoff_exponent: f64,
67
68 #[serde(default = "backoff_min")]
69 #[default(backoff_min())]
70 pub backoff_min: f64,
71
72 #[serde(default = "backoff_max")]
73 #[default(backoff_max())]
74 pub backoff_max: f64,
75
76 #[serde(default)]
77 pub allow_private_addresses_in_store: bool,
78}
79
80impl Validate for NetworkConfig {
81 fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
82 let mut errors = validator::ValidationErrors::new();
83
84 if self.min_delay >= self.max_delay {
85 errors.add(
86 "min_delay and max_delay",
87 validator::ValidationError::new("min_delay must be less than max_delay"),
88 );
89 }
90
91 if !(0.0..=1.0).contains(&self.quality_bad_threshold) {
93 errors.add(
94 "quality_bad_threshold",
95 validator::ValidationError::new("quality_bad_threshold must be between 0 and 1"),
96 );
97 }
98
99 if !(0.0..=1.0).contains(&self.node_score_auto_path_threshold) {
100 errors.add(
101 "node_score_auto_path_threshold",
102 validator::ValidationError::new("node_score_auto_path_threshold must be between 0 and 1"),
103 );
104 }
105
106 if !(0.0..=1.0).contains(&self.quality_offline_threshold) {
108 errors.add(
109 "quality_offline_threshold",
110 validator::ValidationError::new("quality_offline_threshold must be between 0 and 1"),
111 );
112 }
113
114 if self.quality_bad_threshold < self.quality_offline_threshold {
115 errors.add(
116 "quality_bad_threshold and quality_offline_threshold",
117 validator::ValidationError::new("quality_bad_threshold must be greater than quality_offline_threshold"),
118 );
119 }
120
121 if !(0.0..=1.0).contains(&self.quality_step) {
123 errors.add(
124 "quality_step",
125 validator::ValidationError::new("quality_step must be between 0 and 1"),
126 );
127 }
128
129 if self.quality_avg_window_size < 1 {
131 errors.add(
132 "quality_avg_window_size",
133 validator::ValidationError::new("quality_avg_window_size must be greater than 0"),
134 );
135 }
136
137 if self.backoff_min < 0.0 {
139 errors.add(
140 "backoff_min",
141 validator::ValidationError::new("backoff_min must be greater or equal 0"),
142 );
143 }
144
145 if self.backoff_min >= self.backoff_max {
146 errors.add(
147 "backoff_min and backoff_max",
148 validator::ValidationError::new("backoff_min must be less than backoff_max"),
149 );
150 }
151
152 if errors.is_empty() { Ok(()) } else { Err(errors) }
153 }
154}
155
156#[inline]
157fn duration_1_s() -> Duration {
158 Duration::from_secs(1)
159}
160
161#[inline]
162fn duration_5_min() -> Duration {
163 Duration::from_secs(300)
164}
165
166#[inline]
167fn quality_bad_threshold() -> f64 {
168 DEFAULT_NETWORK_BAD_QUALITY_THRESHOLD
169}
170
171#[inline]
172fn quality_offline_threshold() -> f64 {
173 DEFAULT_NETWORK_OFFLINE_QUALITY_THRESHOLD
174}
175
176#[inline]
177fn node_score_auto_path_threshold() -> f64 {
178 DEFAULT_AUTO_PATH_QUALITY_THRESHOLD
179}
180
181#[inline]
182fn max_first_hop_latency_threshold() -> Option<Duration> {
183 Some(DEFAULT_MAX_FIRST_HOP_LATENCY_THRESHOLD)
184}
185
186#[inline]
187fn quality_step() -> f64 {
188 DEFAULT_NETWORK_QUALITY_STEP
189}
190
191#[inline]
192fn quality_average_window_size() -> u32 {
193 DEFAULT_NETWORK_QUALITY_AVERAGE_WINDOW_SIZE
194}
195
196#[inline]
197fn duration_2_min() -> Duration {
198 Duration::from_secs(2 * 60)
199}
200
201#[inline]
202fn backoff_exponent() -> f64 {
203 DEFAULT_NETWORK_BACKOFF_EXPONENT
204}
205
206#[inline]
207fn backoff_min() -> f64 {
208 DEFAULT_NETWORK_BACKOFF_MIN
209}
210
211#[inline]
212fn backoff_max() -> f64 {
213 duration_5_min().as_millis() as f64 / duration_1_s().as_millis() as f64
214}