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 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 with_config(mut self, config: ScopeConfig) -> Self {
136 self.config = config;
137 self
138 }
139
140 pub fn from_existing(config: ScopeConfig) -> Self {
142 Self { config }
143 }
144
145 pub fn p2p_preset(mut self) -> Self {
147 self.config.network_type = NetworkType::P2P;
148 self.config.default_consensus_threshold = 2.0 / 3.0;
149 self.config.default_timeout = DEFAULT_TIMEOUT;
150 self.config.default_liveness_criteria_yes = true;
151 self.config.max_rounds_override = None;
152 self
153 }
154
155 pub fn gossipsub_preset(mut self) -> Self {
157 self.config.network_type = NetworkType::Gossipsub;
158 self.config.default_consensus_threshold = 2.0 / 3.0;
159 self.config.default_timeout = DEFAULT_TIMEOUT;
160 self.config.default_liveness_criteria_yes = true;
161 self.config.max_rounds_override = None;
162 self
163 }
164
165 pub fn strict_consensus(mut self) -> Self {
167 self.config.default_consensus_threshold = 0.9;
168 self
169 }
170
171 pub fn fast_consensus(mut self) -> Self {
173 self.config.default_consensus_threshold = 0.6;
174 self.config.default_timeout = Duration::from_secs(30);
175 self
176 }
177
178 pub fn with_network_defaults(mut self, network_type: NetworkType) -> Self {
180 match network_type {
181 NetworkType::P2P => {
182 self.config.network_type = NetworkType::P2P;
183 self.config.default_consensus_threshold = 2.0 / 3.0;
184 self.config.default_timeout = DEFAULT_TIMEOUT;
185 }
186 NetworkType::Gossipsub => {
187 self.config.network_type = NetworkType::Gossipsub;
188 self.config.default_consensus_threshold = 2.0 / 3.0;
189 self.config.default_timeout = DEFAULT_TIMEOUT;
190 }
191 }
192 self
193 }
194
195 pub fn validate(&self) -> Result<(), ConsensusError> {
197 self.config.validate()
198 }
199
200 pub fn build(self) -> Result<ScopeConfig, ConsensusError> {
202 self.validate()?;
203 Ok(self.config)
204 }
205
206 pub fn get_config(&self) -> ScopeConfig {
208 self.config.clone()
209 }
210}
211
212impl Default for ScopeConfigBuilder {
213 fn default() -> Self {
214 Self::new()
215 }
216}