1use tor_units::{
22 BoundedInt32, IntegerDays, IntegerMilliseconds, IntegerMinutes, IntegerSeconds, Percentage,
23 SendMeVersion,
24};
25
26pub const CHANNEL_PADDING_TIMEOUT_UPPER_BOUND: i32 = 60_000;
37
38pub trait FromInt32Saturating {
40 fn from_saturating(val: i32) -> Self;
46}
47
48impl FromInt32Saturating for i32 {
49 fn from_saturating(val: i32) -> Self {
50 val
51 }
52}
53impl<const L: i32, const H: i32> FromInt32Saturating for BoundedInt32<L, H> {
54 fn from_saturating(val: i32) -> Self {
55 Self::saturating_new(val)
56 }
57}
58impl<T: Copy + Into<f64> + FromInt32Saturating> FromInt32Saturating for Percentage<T> {
59 fn from_saturating(val: i32) -> Self {
60 Self::new(T::from_saturating(val))
61 }
62}
63impl<T: FromInt32Saturating + TryInto<u64>> FromInt32Saturating for IntegerMilliseconds<T> {
64 fn from_saturating(val: i32) -> Self {
65 Self::new(T::from_saturating(val))
66 }
67}
68impl<T: FromInt32Saturating + TryInto<u64>> FromInt32Saturating for IntegerSeconds<T> {
69 fn from_saturating(val: i32) -> Self {
70 Self::new(T::from_saturating(val))
71 }
72}
73impl<T: FromInt32Saturating + TryInto<u64>> FromInt32Saturating for IntegerMinutes<T> {
74 fn from_saturating(val: i32) -> Self {
75 Self::new(T::from_saturating(val))
76 }
77}
78impl<T: FromInt32Saturating + TryInto<u64>> FromInt32Saturating for IntegerDays<T> {
79 fn from_saturating(val: i32) -> Self {
80 Self::new(T::from_saturating(val))
81 }
82}
83impl FromInt32Saturating for SendMeVersion {
84 fn from_saturating(val: i32) -> Self {
85 Self::new(val.clamp(0, 255) as u8)
86 }
87}
88
89macro_rules! declare_net_parameters {
95 {
96 $(#[$s_meta:meta])* $s_v:vis struct $s_name:ident {
97 $(
98 $(#[$p_meta:meta])* $p_v:vis
99 $p_name:ident : $p_type:ty
100 = ($p_dflt:expr) from $p_string:literal
101 ),*
102 $( , )?
103 }
104 } =>
105 {
106 $(#[$s_meta])* $s_v struct $s_name {
107 $(
108 $(#[$p_meta])* $p_v $p_name : $p_type
109 ),*
110 }
111
112 impl $s_name {
113 fn default_values() -> Result<Self, tor_units::Error> {
118 Ok(Self {
119 $( $p_name : $p_dflt.try_into()? ),*
120 })
121 }
122 fn set_saturating(&mut self, key: &str, val: i32) -> bool {
129 match key {
130 $( $p_string => self.$p_name = {
131 type T = $p_type;
132 T::from_saturating(val)
133 }, )*
134 _ => return false,
135 }
136 true
137 }
138 }
139 }
140}
141
142declare_net_parameters! {
143
144#[derive(Clone, Debug)]
147#[non_exhaustive]
148pub struct NetParameters {
149 pub bw_weight_scale: BoundedInt32<1, { i32::MAX }> = (10_000)
151 from "bwweightscale",
152 pub cbt_learning_disabled: BoundedInt32<0, 1> = (0)
154 from "cbtdisabled",
155 pub cbt_num_xm_modes: BoundedInt32<1, 20> = (10)
158 from "cbtnummodes",
159 pub cbt_success_count: BoundedInt32<3, 1_000> = (20)
162 from "cbtrecentcount",
163 pub cbt_max_timeouts: BoundedInt32<3, 10_000> = (18)
166 from "cbtmaxtimeouts",
167 pub cbt_min_circs_for_estimate: BoundedInt32<1, 10_000> = (100)
170 from "cbtmincircs",
171 pub cbt_timeout_quantile: Percentage<BoundedInt32<10, 99>> = (80)
177 from "cbtquantile",
178 pub cbt_abandon_quantile: Percentage<BoundedInt32<10, 99>> = (99)
181 from "cbtclosequantile",
182 pub cbt_min_timeout: IntegerMilliseconds<BoundedInt32<10, { i32::MAX }>> = (10)
184 from "cbtmintimeout",
185 pub cbt_initial_timeout: IntegerMilliseconds<BoundedInt32<10, { i32::MAX }>> = (60_000)
188 from "cbtinitialtimeout",
189 pub cbt_testing_delay: IntegerSeconds<BoundedInt32<1, { i32::MAX }>> = (10)
193 from "cbttestfreq",
194 pub cbt_max_open_circuits_for_testing: BoundedInt32<0, 14> = (10)
198 from "cbtmaxopencircs",
199
200 pub cc_alg: BoundedInt32<0, 2> = (0)
207 from "cc_alg",
208
209 pub cc_cwnd_full_gap: BoundedInt32<0, { i16::MAX as i32 }> = (4444)
212 from "cc_cwnd_full_gap",
213 pub cc_cwnd_full_minpct: Percentage<BoundedInt32<0, 100>> = (25)
215 from "cc_cwnd_full_minpct",
216 pub cc_cwnd_full_per_cwnd: BoundedInt32<0, 1> = (1)
218 from "cc_cwnd_full_per_cwnd",
219
220 pub cc_cwnd_init: BoundedInt32<31, 10_000> = (4 * 31)
222 from "cc_cwnd_init",
223 pub cc_cwnd_inc_pct_ss: Percentage<BoundedInt32<1, 500>> = (50)
226 from "cc_cwnd_inc_pct_ss",
227 pub cc_cwnd_inc: BoundedInt32<1, 1000> = (31)
230 from "cc_cwnd_inc",
231 pub cc_cwnd_inc_rate: BoundedInt32<1, 250> = (1)
234 from "cc_cwnd_inc_rate",
235 pub cc_cwnd_min: BoundedInt32<31, 1000> = (31)
237 from "cc_cwnd_min",
238 pub cc_cwnd_max: BoundedInt32<500, { i32::MAX }> = (i32::MAX)
240 from "cc_cwnd_max",
241
242 pub cc_ewma_cwnd_pct: Percentage<BoundedInt32<1, 255>> = (50)
248 from "cc_ewma_cwnd_pct",
249 pub cc_ewma_max: BoundedInt32<2, { i32::MAX }> = (10)
251 from "cc_ewma_max",
252 pub cc_ewma_ss: BoundedInt32<2, { i32::MAX }> = (2)
254 from "cc_ewma_ss",
255 pub cc_rtt_reset_pct: Percentage<BoundedInt32<0, 100>> = (100)
258 from "cc_rtt_reset_pct",
259 pub cc_sendme_inc: BoundedInt32<1, 254> = (31)
261 from "cc_sendme_inc",
262 pub cc_ss_max: BoundedInt32<500, { i32::MAX }> = (5000)
264 from "cc_ss_max",
265
266 pub cc_vegas_alpha_exit: BoundedInt32<0, 1000> = (3 * 62)
268 from "cc_vegas_alpha_exit",
269 pub cc_vegas_beta_exit: BoundedInt32<0, 1000> = (4 * 62)
271 from "cc_vegas_beta_exit",
272 pub cc_vegas_delta_exit: BoundedInt32<0, 1000> = (5 * 62)
274 from "cc_vegas_delta_exit",
275 pub cc_vegas_gamma_exit: BoundedInt32<0, 1000> = (3 * 62)
277 from "cc_vegas_gamma_exit",
278
279 pub cc_vegas_alpha_onion: BoundedInt32<0, 1000> = (3 * 62)
281 from "cc_vegas_alpha_onion",
282 pub cc_vegas_beta_onion: BoundedInt32<0, 1000> = (6 * 62)
284 from "cc_vegas_beta_onion",
285 pub cc_vegas_delta_onion: BoundedInt32<0, 1000> = (7 * 62)
287 from "cc_vegas_delta_onion",
288 pub cc_vegas_gamma_onion: BoundedInt32<0, 1000> = (4 * 62)
290 from "cc_vegas_gamma_onion",
291
292 pub cc_vegas_sscap_exit: BoundedInt32<100, { i32::MAX }> = (600)
295 from "cc_sscap_exit",
296 pub cc_vegas_sscap_onion: BoundedInt32<100, { i32::MAX }> = (475)
299 from "cc_sscap_onion",
300
301 pub circuit_window: BoundedInt32<100, 1000> = (1_000)
303 from "circwindow",
304 pub circuit_priority_half_life: IntegerMilliseconds<BoundedInt32<1, { i32::MAX }>> = (30_000)
306 from "CircuitPriorityHalflifeMsec",
307 pub extend_by_ed25519_id: BoundedInt32<0, 1> = (0)
309 from "ExtendByEd25519ID",
310
311 pub guard_meaningful_restriction: Percentage<BoundedInt32<1,100>> = (20)
315 from "guard-meaningful-restriction-percent",
316
317 pub guard_extreme_restriction: Percentage<BoundedInt32<1,100>> = (1)
320 from "guard-extreme-restriction-percent",
321
322 pub guard_lifetime_unconfirmed: IntegerDays<BoundedInt32<1, 3650>> = (120)
325 from "guard-lifetime-days",
326
327 pub guard_lifetime_confirmed: IntegerDays<BoundedInt32<1, 3650>> = (60)
330 from "guard-confirmed-min-lifetime-days",
331
332 pub guard_internet_likely_down: IntegerSeconds<BoundedInt32<1, {i32::MAX}>> = (600)
336 from "guard-internet-likely-down-interval",
337 pub guard_max_sample_size: BoundedInt32<1, {i32::MAX}> = (60)
340 from "guard-max-sample-size",
341 pub guard_max_sample_threshold: Percentage<BoundedInt32<1,100>> = (20)
344 from "guard-max-sample-threshold",
345
346 pub guard_filtered_min_sample_size: BoundedInt32<1,{i32::MAX}> = (20)
350 from "guard-min-filtered-sample-size",
351
352 pub guard_n_primary: BoundedInt32<1,{i32::MAX}> = (3)
355 from "guard-n-primary-guards",
356 pub guard_use_parallelism: BoundedInt32<1, {i32::MAX}> = (1)
359 from "guard-n-primary-guards-to-use",
360 pub guard_dir_use_parallelism: BoundedInt32<1, {i32::MAX}> = (3)
364 from "guard-n-primary-dir-guards-to-use",
365
366 pub guard_nonprimary_connect_timeout: IntegerSeconds<BoundedInt32<1,{i32::MAX}>> = (15)
370 from "guard-nonprimary-guard-connect-timeout",
371 pub guard_nonprimary_idle_timeout: IntegerSeconds<BoundedInt32<1,{i32::MAX}>> = (600)
374 from "guard-nonprimary-guard-idle-timeout",
375 pub guard_remove_unlisted_after: IntegerDays<BoundedInt32<1,3650>> = (20)
378 from "guard-remove-unlisted-guards-after-days",
379
380
381 pub min_circuit_path_threshold: Percentage<BoundedInt32<25, 95>> = (60)
383 from "min_paths_for_circs_pct",
384
385 pub nf_ito_low: IntegerMilliseconds<BoundedInt32<0, CHANNEL_PADDING_TIMEOUT_UPPER_BOUND>> = (1500)
389 from "nf_ito_low",
390 pub nf_ito_high: IntegerMilliseconds<BoundedInt32<0, CHANNEL_PADDING_TIMEOUT_UPPER_BOUND>> = (9500)
392 from "nf_ito_high",
393 pub nf_ito_low_reduced: IntegerMilliseconds<BoundedInt32<0, CHANNEL_PADDING_TIMEOUT_UPPER_BOUND>> = (9000)
395 from "nf_ito_low_reduced",
396 pub nf_ito_high_reduced: IntegerMilliseconds<BoundedInt32<0, CHANNEL_PADDING_TIMEOUT_UPPER_BOUND>> = (14000)
398 from "nf_ito_high_reduced",
399
400 pub sendme_accept_min_version: SendMeVersion = (0)
402 from "sendme_accept_min_version",
403 pub sendme_emit_min_version: SendMeVersion = (0)
405 from "sendme_emit_min_version",
406
407 pub unused_client_circ_timeout: IntegerSeconds<BoundedInt32<60, 86_400>> = (30*60)
410 from "nf_conntimeout_clients",
411 pub unused_client_circ_timeout_while_learning_cbt: IntegerSeconds<BoundedInt32<10, 60_000>> = (3*60)
414 from "cbtlearntimeout",
415
416 pub hs_introcirc_requests_min: BoundedInt32<0, {i32::MAX}> = (16384)
420 from "hs_intro_min_introduce2",
421
422 pub hs_introcirc_requests_max: BoundedInt32<0, {i32::MAX}> = (32768)
426 from "hs_intro_max_introduce2",
427
428 pub hs_intro_min_lifetime: IntegerSeconds<BoundedInt32<0, {i32::MAX}>> = (18 * 60 * 60)
430 from "hs_intro_min_lifetime",
431
432 pub hs_intro_max_lifetime: IntegerSeconds<BoundedInt32<0, {i32::MAX}>> = (24 * 60 * 60)
434 from "hs_intro_max_lifetime",
435
436 pub hs_intro_num_extra_intropoints: BoundedInt32<0, 128> = (2)
439 from "hs_intro_num_extra",
440
441 pub hsdir_timeperiod_length: IntegerMinutes<BoundedInt32<30, 14400>> = (1440)
447 from "hsdir_interval",
448
449 pub hsdir_n_replicas: BoundedInt32<1, 16> = (2)
452 from "hsdir_n_replicas",
453
454 pub hsdir_spread_fetch: BoundedInt32<1, 128> = (3)
457 from "hsdir_spread_fetch",
458
459 pub hsdir_spread_store: BoundedInt32<1,128> = (4)
462 from "hsdir_spread_store",
463
464 pub hsdir_max_desc_size: BoundedInt32<1, {i32::MAX}> = (50_000)
466 from "HSV3MaxDescriptorSize",
467
468 pub hs_service_rendezvous_failures_max: BoundedInt32<1, 10> = (2)
471 from "hs_service_max_rdv_failures",
472
473 pub hs_intro_dos_enabled: BoundedInt32<0, 1> = (0)
478 from "HiddenServiceEnableIntroDoSDefense",
479
480 pub hs_intro_dos_max_burst: BoundedInt32<0, {i32::MAX}> = (200)
486 from "HiddenServiceEnableIntroDoSBurstPerSec",
487
488 pub hs_intro_dos_rate: BoundedInt32<0, {i32::MAX}> = (25)
494 from "HiddenServiceEnableIntroDoSRatePerSec",
495
496 pub vanguards_enabled: BoundedInt32<0, 2> = (1)
507 from "vanguards-enabled",
508
509 pub vanguards_hs_service: BoundedInt32<0, 2> = (2)
522 from "vanguards-hs-service",
523
524 pub guard_hs_l2_number: BoundedInt32<1, {i32::MAX}> = (4)
529 from "guard-hs-l2-number",
530
531 pub guard_hs_l2_lifetime_min: IntegerSeconds<BoundedInt32<1, {i32::MAX}>> = (86400)
536 from "guard-hs-l2-lifetime-min",
537
538 pub guard_hs_l2_lifetime_max: IntegerSeconds<BoundedInt32<1, {i32::MAX}>> = (1036800)
543 from "guard-hs-l2-lifetime-max",
544
545 pub guard_hs_l3_number: BoundedInt32<1, {i32::MAX}> = (8)
550 from "guard-hs-l3-number",
551
552 pub guard_hs_l3_lifetime_min: IntegerSeconds<BoundedInt32<1, {i32::MAX}>> = (3600)
557 from "guard-hs-l3-lifetime-min",
558
559 pub guard_hs_l3_lifetime_max: IntegerSeconds<BoundedInt32<1, {i32::MAX}>> = (172800)
564 from "guard-hs-l3-lifetime-max",
565
566 pub kist_enabled: BoundedInt32<0, 1> = (0)
577 from "kist-enabled",
578
579 pub kist_tcp_notsent_lowat: BoundedInt32<1, {i32::MAX}> = (1)
590 from "kist-tcp-notsent-lowat",
591
592 pub use_family_lists: BoundedInt32<0,1> = (1)
595 from "use-family-lists",
596
597 pub use_family_ids: BoundedInt32<0,1> = (1)
600 from "use-family-ids",
601}
602
603}
604
605impl Default for NetParameters {
606 fn default() -> Self {
607 NetParameters::default_values().expect("Default parameters were out-of-bounds")
608 }
609}
610
611impl AsRef<NetParameters> for NetParameters {
614 fn as_ref(&self) -> &NetParameters {
615 self
616 }
617}
618
619impl NetParameters {
620 pub fn from_map(p: &tor_netdoc::doc::netstatus::NetParams<i32>) -> Self {
624 let mut params = NetParameters::default();
625 let _ = params.saturating_update(p.iter());
626 params
627 }
628
629 pub(crate) fn saturating_update<'a, S>(
634 &mut self,
635 iter: impl Iterator<Item = (S, &'a i32)>,
636 ) -> Vec<S>
637 where
638 S: AsRef<str>,
639 {
640 let mut unrecognized = Vec::new();
641 for (k, v) in iter {
642 if !self.set_saturating(k.as_ref(), *v) {
643 unrecognized.push(k);
644 }
645 }
646 unrecognized
647 }
648}
649
650#[cfg(test)]
651#[allow(clippy::many_single_char_names)]
652#[allow(clippy::unwrap_used)]
653#[allow(clippy::cognitive_complexity)]
654mod test {
655 #![allow(clippy::bool_assert_comparison)]
657 #![allow(clippy::clone_on_copy)]
658 #![allow(clippy::dbg_macro)]
659 #![allow(clippy::mixed_attributes_style)]
660 #![allow(clippy::print_stderr)]
661 #![allow(clippy::print_stdout)]
662 #![allow(clippy::single_char_pattern)]
663 #![allow(clippy::unwrap_used)]
664 #![allow(clippy::unchecked_duration_subtraction)]
665 #![allow(clippy::useless_vec)]
666 #![allow(clippy::needless_pass_by_value)]
667 use super::*;
669 use std::string::String;
670
671 #[test]
672 fn empty_list() {
673 let mut x = NetParameters::default();
674 let y = Vec::<(&String, &i32)>::new();
675 let u = x.saturating_update(y.into_iter());
676 assert!(u.is_empty());
677 }
678
679 #[test]
680 fn unknown_parameter() {
681 let mut x = NetParameters::default();
682 let mut y = Vec::<(&String, &i32)>::new();
683 let k = &String::from("This_is_not_a_real_key");
684 let v = &456;
685 y.push((k, v));
686 let u = x.saturating_update(y.into_iter());
687 assert_eq!(u, vec![&String::from("This_is_not_a_real_key")]);
688 }
689
690 #[test]
694 fn single_good_parameter() {
695 let mut x = NetParameters::default();
696 let mut y = Vec::<(&String, &i32)>::new();
697 let k = &String::from("min_paths_for_circs_pct");
698 let v = &54;
699 y.push((k, v));
700 let z = x.saturating_update(y.into_iter());
701 assert!(z.is_empty());
702 assert_eq!(x.min_circuit_path_threshold.as_percent().get(), 54);
703 }
704
705 #[test]
706 fn multiple_good_parameters() {
707 let mut x = NetParameters::default();
708 let mut y = Vec::<(&String, &i32)>::new();
709 let k = &String::from("min_paths_for_circs_pct");
710 let v = &54;
711 y.push((k, v));
712 let k = &String::from("circwindow");
713 let v = &900;
714 y.push((k, v));
715 let z = x.saturating_update(y.into_iter());
716 assert!(z.is_empty());
717 assert_eq!(x.min_circuit_path_threshold.as_percent().get(), 54);
718 assert_eq!(x.circuit_window.get(), 900);
719 }
720
721 #[test]
722 fn good_out_of_range() {
723 let mut x = NetParameters::default();
724 let mut y = Vec::<(&String, &i32)>::new();
725 let k = &String::from("sendme_accept_min_version");
726 let v = &30;
727 y.push((k, v));
728 let k = &String::from("min_paths_for_circs_pct");
729 let v = &255;
730 y.push((k, v));
731 let z = x.saturating_update(y.into_iter());
732 assert!(z.is_empty());
733 assert_eq!(x.sendme_accept_min_version.get(), 30);
734 assert_eq!(x.min_circuit_path_threshold.as_percent().get(), 95);
735 }
736
737 #[test]
738 fn good_invalid_rep() {
739 let mut x = NetParameters::default();
740 let mut y = Vec::<(&String, &i32)>::new();
741 let k = &String::from("sendme_accept_min_version");
742 let v = &30;
743 y.push((k, v));
744 let k = &String::from("min_paths_for_circs_pct");
745 let v = &9000;
746 y.push((k, v));
747 let z = x.saturating_update(y.into_iter());
748 assert!(z.is_empty());
749 assert_eq!(x.sendme_accept_min_version.get(), 30);
750 assert_eq!(x.min_circuit_path_threshold.as_percent().get(), 95);
751 }
752
753 #[test]
756 fn good_unknown() {
757 let mut x = NetParameters::default();
758 let mut y = Vec::<(&String, &i32)>::new();
759 let k = &String::from("sendme_accept_min_version");
760 let v = &30;
761 y.push((k, v));
762 let k = &String::from("not_a_real_parameter");
763 let v = &9000;
764 y.push((k, v));
765 let z = x.saturating_update(y.into_iter());
766 assert_eq!(z, vec![&String::from("not_a_real_parameter")]);
767 assert_eq!(x.sendme_accept_min_version.get(), 30);
768 }
769
770 #[test]
771 fn from_consensus() {
772 let mut p = NetParameters::default();
773 let mut mp: std::collections::HashMap<String, i32> = std::collections::HashMap::new();
774 mp.insert("bwweightscale".to_string(), 70);
775 mp.insert("min_paths_for_circs_pct".to_string(), 45);
776 mp.insert("im_a_little_teapot".to_string(), 1);
777 mp.insert("circwindow".to_string(), 99999);
778 mp.insert("ExtendByEd25519ID".to_string(), 1);
779
780 let z = p.saturating_update(mp.iter());
781 assert_eq!(z, vec![&String::from("im_a_little_teapot")]);
782
783 assert_eq!(p.bw_weight_scale.get(), 70);
784 assert_eq!(p.min_circuit_path_threshold.as_percent().get(), 45);
785 let b_val: bool = p.extend_by_ed25519_id.into();
786 assert!(b_val);
787 }
788
789 #[test]
790 fn all_parameters() {
791 use std::time::Duration;
792 let mut p = NetParameters::default();
793 let mp = [
794 ("bwweightscale", 10),
795 ("cbtdisabled", 1),
796 ("cbtnummodes", 11),
797 ("cbtrecentcount", 12),
798 ("cbtmaxtimeouts", 13),
799 ("cbtmincircs", 5),
800 ("cbtquantile", 61),
801 ("cbtclosequantile", 15),
802 ("cbtlearntimeout", 1900),
803 ("cbtmintimeout", 2020),
804 ("cbtinitialtimeout", 2050),
805 ("cbttestfreq", 110),
806 ("cbtmaxopencircs", 14),
807 ("circwindow", 999),
808 ("CircuitPriorityHalflifeMsec", 222),
809 ("guard-lifetime-days", 36),
810 ("guard-confirmed-min-lifetime-days", 37),
811 ("guard-internet-likely-down-interval", 38),
812 ("guard-max-sample-size", 39),
813 ("guard-max-sample-threshold", 40),
814 ("guard-min-filtered-sample-size", 41),
815 ("guard-n-primary-guards", 42),
816 ("guard-n-primary-guards-to-use", 43),
817 ("guard-n-primary-dir-guards-to-use", 44),
818 ("guard-nonprimary-guard-connect-timeout", 45),
819 ("guard-nonprimary-guard-idle-timeout", 46),
820 ("guard-remove-unlisted-guards-after-days", 47),
821 ("guard-meaningful-restriction-percent", 12),
822 ("guard-extreme-restriction-percent", 3),
823 ("ExtendByEd25519ID", 0),
824 ("min_paths_for_circs_pct", 51),
825 ("nf_conntimeout_clients", 606),
826 ("nf_ito_low", 1_000),
827 ("nf_ito_high", 20_000),
828 ("nf_ito_low_reduced", 3_000),
829 ("nf_ito_high_reduced", 40_000),
830 ("sendme_accept_min_version", 31),
831 ("sendme_emit_min_version", 32),
832 ];
833 let ignored = p.saturating_update(mp.iter().map(|(a, b)| (a, b)));
834 assert!(ignored.is_empty());
835
836 assert_eq!(p.bw_weight_scale.get(), 10);
837 assert!(bool::from(p.cbt_learning_disabled));
838 assert_eq!(p.cbt_num_xm_modes.get(), 11);
839 assert_eq!(p.cbt_success_count.get(), 12);
840 assert_eq!(p.cbt_max_timeouts.get(), 13);
841 assert_eq!(p.cbt_min_circs_for_estimate.get(), 5);
842 assert_eq!(p.cbt_timeout_quantile.as_percent().get(), 61);
843 assert_eq!(p.cbt_abandon_quantile.as_percent().get(), 15);
844 assert_eq!(p.nf_ito_low.as_millis().get(), 1_000);
845 assert_eq!(p.nf_ito_high.as_millis().get(), 20_000);
846 assert_eq!(p.nf_ito_low_reduced.as_millis().get(), 3_000);
847 assert_eq!(p.nf_ito_high_reduced.as_millis().get(), 40_000);
848 assert_eq!(
849 Duration::try_from(p.unused_client_circ_timeout_while_learning_cbt).unwrap(),
850 Duration::from_secs(1900)
851 );
852 assert_eq!(
853 Duration::try_from(p.cbt_min_timeout).unwrap(),
854 Duration::from_millis(2020)
855 );
856 assert_eq!(
857 Duration::try_from(p.cbt_initial_timeout).unwrap(),
858 Duration::from_millis(2050)
859 );
860 assert_eq!(
861 Duration::try_from(p.cbt_testing_delay).unwrap(),
862 Duration::from_secs(110)
863 );
864 assert_eq!(p.cbt_max_open_circuits_for_testing.get(), 14);
865 assert_eq!(p.circuit_window.get(), 999);
866 assert_eq!(
867 Duration::try_from(p.circuit_priority_half_life).unwrap(),
868 Duration::from_millis(222)
869 );
870 assert!(!bool::from(p.extend_by_ed25519_id));
871 assert_eq!(p.min_circuit_path_threshold.as_percent().get(), 51);
872 assert_eq!(
873 Duration::try_from(p.unused_client_circ_timeout).unwrap(),
874 Duration::from_secs(606)
875 );
876 assert_eq!(p.sendme_accept_min_version.get(), 31);
877 assert_eq!(p.sendme_emit_min_version.get(), 32);
878
879 assert_eq!(
880 Duration::try_from(p.guard_lifetime_unconfirmed).unwrap(),
881 Duration::from_secs(86400 * 36)
882 );
883 assert_eq!(
884 Duration::try_from(p.guard_lifetime_confirmed).unwrap(),
885 Duration::from_secs(86400 * 37)
886 );
887 assert_eq!(
888 Duration::try_from(p.guard_internet_likely_down).unwrap(),
889 Duration::from_secs(38)
890 );
891 assert_eq!(p.guard_max_sample_size.get(), 39);
892 assert_eq!(p.guard_max_sample_threshold.as_percent().get(), 40);
893 assert_eq!(p.guard_filtered_min_sample_size.get(), 41);
894 assert_eq!(p.guard_n_primary.get(), 42);
895 assert_eq!(p.guard_use_parallelism.get(), 43);
896 assert_eq!(p.guard_dir_use_parallelism.get(), 44);
897 assert_eq!(
898 Duration::try_from(p.guard_nonprimary_connect_timeout).unwrap(),
899 Duration::from_secs(45)
900 );
901 assert_eq!(
902 Duration::try_from(p.guard_nonprimary_idle_timeout).unwrap(),
903 Duration::from_secs(46)
904 );
905 assert_eq!(
906 Duration::try_from(p.guard_remove_unlisted_after).unwrap(),
907 Duration::from_secs(86400 * 47)
908 );
909 assert_eq!(p.guard_meaningful_restriction.as_percent().get(), 12);
910 assert_eq!(p.guard_extreme_restriction.as_percent().get(), 3);
911 }
912}