hashgraph_like_consensus/
scope_config.rs1use std::time::Duration;
9
10use crate::error::ConsensusError;
11use crate::utils::{validate_threshold, validate_timeout};
12
13pub(crate) const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum NetworkType {
18 Gossipsub,
20 P2P,
23}
24
25#[derive(Debug, Clone)]
30pub struct ScopeConfig {
31 pub network_type: NetworkType,
33 pub default_consensus_threshold: f64,
35 pub default_timeout: Duration,
37 pub default_liveness_criteria_yes: bool,
39 pub max_rounds_override: Option<u32>,
41}
42
43impl Default for ScopeConfig {
44 fn default() -> Self {
45 Self {
46 network_type: NetworkType::Gossipsub,
47 default_consensus_threshold: 2.0 / 3.0,
48 default_timeout: DEFAULT_TIMEOUT,
49 default_liveness_criteria_yes: true,
50 max_rounds_override: None,
51 }
52 }
53}
54
55impl ScopeConfig {
56 pub fn validate(&self) -> Result<(), ConsensusError> {
58 validate_threshold(self.default_consensus_threshold)?;
59 validate_timeout(self.default_timeout)?;
60 if let Some(max_rounds) = self.max_rounds_override
63 && max_rounds == 0
64 && self.network_type == NetworkType::Gossipsub
65 {
66 return Err(ConsensusError::InvalidMaxRounds);
67 }
68 Ok(())
69 }
70}
71
72impl From<NetworkType> for ScopeConfig {
73 fn from(network_type: NetworkType) -> Self {
74 match network_type {
75 NetworkType::Gossipsub => Self {
76 network_type: NetworkType::Gossipsub,
77 default_consensus_threshold: 2.0 / 3.0,
78 default_timeout: DEFAULT_TIMEOUT,
79 default_liveness_criteria_yes: true,
80 max_rounds_override: None,
81 },
82 NetworkType::P2P => Self {
83 network_type: NetworkType::P2P,
84 default_consensus_threshold: 2.0 / 3.0,
85 default_timeout: DEFAULT_TIMEOUT,
86 default_liveness_criteria_yes: true,
87 max_rounds_override: None,
88 },
89 }
90 }
91}
92
93pub(crate) struct ScopeConfigBuilder {
94 config: ScopeConfig,
95}
96
97impl ScopeConfigBuilder {
98 pub(crate) fn new() -> Self {
99 Self {
100 config: ScopeConfig::default(),
101 }
102 }
103
104 pub fn with_network_type(mut self, network_type: NetworkType) -> Self {
106 self.config.network_type = network_type;
107 self
108 }
109
110 pub fn with_threshold(mut self, threshold: f64) -> Self {
112 self.config.default_consensus_threshold = threshold;
113 self
114 }
115
116 pub fn with_timeout(mut self, timeout: Duration) -> Self {
118 self.config.default_timeout = timeout;
119 self
120 }
121
122 pub fn with_liveness_criteria(mut self, liveness_criteria_yes: bool) -> Self {
124 self.config.default_liveness_criteria_yes = liveness_criteria_yes;
125 self
126 }
127
128 pub fn with_max_rounds(mut self, max_rounds: Option<u32>) -> Self {
130 self.config.max_rounds_override = max_rounds;
131 self
132 }
133
134 pub fn from_existing(config: ScopeConfig) -> Self {
136 Self { config }
137 }
138
139 pub fn p2p_preset(mut self) -> Self {
141 self.config.network_type = NetworkType::P2P;
142 self.config.default_consensus_threshold = 2.0 / 3.0;
143 self.config.default_timeout = DEFAULT_TIMEOUT;
144 self.config.default_liveness_criteria_yes = true;
145 self.config.max_rounds_override = None;
146 self
147 }
148
149 pub fn gossipsub_preset(mut self) -> Self {
151 self.config.network_type = NetworkType::Gossipsub;
152 self.config.default_consensus_threshold = 2.0 / 3.0;
153 self.config.default_timeout = DEFAULT_TIMEOUT;
154 self.config.default_liveness_criteria_yes = true;
155 self.config.max_rounds_override = None;
156 self
157 }
158
159 pub fn strict_consensus(mut self) -> Self {
161 self.config.default_consensus_threshold = 0.9;
162 self
163 }
164
165 pub fn fast_consensus(mut self) -> Self {
167 self.config.default_consensus_threshold = 0.6;
168 self.config.default_timeout = Duration::from_secs(30);
169 self
170 }
171
172 pub fn with_network_defaults(mut self, network_type: NetworkType) -> Self {
174 match network_type {
175 NetworkType::P2P => {
176 self.config.network_type = NetworkType::P2P;
177 self.config.default_consensus_threshold = 2.0 / 3.0;
178 self.config.default_timeout = DEFAULT_TIMEOUT;
179 }
180 NetworkType::Gossipsub => {
181 self.config.network_type = NetworkType::Gossipsub;
182 self.config.default_consensus_threshold = 2.0 / 3.0;
183 self.config.default_timeout = DEFAULT_TIMEOUT;
184 }
185 }
186 self
187 }
188
189 pub fn validate(&self) -> Result<(), ConsensusError> {
191 self.config.validate()
192 }
193
194 pub fn build(self) -> Result<ScopeConfig, ConsensusError> {
196 self.validate()?;
197 Ok(self.config)
198 }
199
200 pub fn get_config(&self) -> ScopeConfig {
202 self.config.clone()
203 }
204}
205
206impl Default for ScopeConfigBuilder {
207 fn default() -> Self {
208 Self::new()
209 }
210}