1pub mod coordinator;
7pub mod majority;
8pub mod pbft;
9pub mod proof_of_stake;
10pub mod raft;
11
12use crate::error::{MetricsError, Result};
13use scirs2_core::numeric::Float;
14use serde::{Deserialize, Serialize};
15use std::collections::{HashMap, HashSet};
16use std::time::{Duration, Instant, SystemTime};
17
18pub use coordinator::*;
20pub use majority::*;
21pub use pbft::*;
22pub use proof_of_stake::*;
23pub use raft::*;
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct ConsensusConfig {
28 pub algorithm: ConsensusAlgorithm,
30
31 pub quorum_size: usize,
33
34 pub election_timeout_ms: u64,
36
37 pub heartbeat_interval_ms: u64,
39
40 pub max_entries_per_append: usize,
42
43 pub log_compaction_threshold: usize,
45
46 pub snapshot_interval: Duration,
48
49 pub byzantine_threshold: usize,
51
52 pub enable_optimization: bool,
54
55 pub consensus_timeout_ms: u64,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
61pub enum ConsensusAlgorithm {
62 Raft,
64
65 PBFT,
67
68 ProofOfStake,
70
71 SimpleMajority,
73
74 Custom(String),
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct ConsensusSystemState {
81 pub current_leader: Option<String>,
83
84 pub active_participants: HashSet<String>,
86
87 pub current_term: u64,
89
90 pub last_consensus: SystemTime,
92
93 pub consensus_stats: ConsensusStats,
95
96 pub algorithm_state: AlgorithmSpecificState,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub enum AlgorithmSpecificState {
103 Raft(raft::RaftState),
105
106 PBFT(pbft::PbftState),
108
109 ProofOfStake(proof_of_stake::PoSState),
111
112 SimpleMajority(majority::MajorityState),
114
115 Custom(HashMap<String, String>),
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize, Default)]
121pub struct ConsensusStats {
122 pub total_decisions: u64,
124
125 pub avg_consensus_time_ms: f64,
127
128 pub failed_attempts: u64,
130
131 pub leader_changes: u64,
133
134 pub byzantine_failures: u64,
136
137 pub network_partitions: u64,
139
140 pub health_score: f64,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct ConsensusProposal<T> {
147 pub proposal_id: String,
149
150 pub proposer: String,
152
153 pub timestamp: SystemTime,
155
156 pub data: T,
158
159 pub priority: u32,
161
162 pub required_quorum: usize,
164
165 pub metadata: HashMap<String, String>,
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct ConsensusDecision<T> {
172 pub decision_id: String,
174
175 pub proposal: ConsensusProposal<T>,
177
178 pub outcome: DecisionOutcome,
180
181 pub participants: HashSet<String>,
183
184 pub timestamp: SystemTime,
186
187 pub algorithm: ConsensusAlgorithm,
189
190 pub metadata: HashMap<String, String>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
196pub enum DecisionOutcome {
197 Accepted,
199
200 Rejected,
202
203 Timeout,
205
206 InsufficientQuorum,
208
209 ByzantineFault,
211
212 NetworkPartition,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct ConsensusVote {
219 pub voter: String,
221
222 pub vote: VoteDecision,
224
225 pub timestamp: SystemTime,
227
228 pub signature: Option<String>,
230
231 pub metadata: HashMap<String, String>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
237pub enum VoteDecision {
238 Accept,
240
241 Reject,
243
244 Abstain,
246}
247
248#[allow(async_fn_in_trait)]
250pub trait ConsensusManager<T>: Send + Sync {
251 async fn initialize(&mut self) -> Result<()>;
253
254 async fn propose(&mut self, proposal: ConsensusProposal<T>) -> Result<String>;
256
257 async fn vote(&mut self, proposal_id: &str, vote: ConsensusVote) -> Result<()>;
259
260 async fn get_decision(&self, proposal_id: &str) -> Result<Option<ConsensusDecision<T>>>;
262
263 async fn handle_node_failure(&mut self, node_id: &str) -> Result<()>;
265
266 async fn handle_node_recovery(&mut self, node_id: &str) -> Result<()>;
268
269 async fn get_state(&self) -> Result<ConsensusSystemState>;
271
272 async fn get_health_score(&self) -> Result<f64>;
274
275 async fn shutdown(&mut self) -> Result<()>;
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct ConsensusEvent {
282 pub event_id: String,
284
285 pub event_type: ConsensusEventType,
287
288 pub timestamp: SystemTime,
290
291 pub nodes: Vec<String>,
293
294 pub data: HashMap<String, String>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub enum ConsensusEventType {
301 ProposalSubmitted,
303
304 VoteCast,
306
307 DecisionReached,
309
310 LeaderElection,
312
313 LeaderChange,
315
316 NodeFailure,
318
319 NodeRecovery,
321
322 ByzantineBehavior,
324
325 NetworkPartition,
327
328 PartitionHealed,
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize, Default)]
334pub struct ConsensusPerformanceMetrics {
335 pub avg_proposal_time_ms: f64,
337
338 pub avg_voting_time_ms: f64,
340
341 pub success_rate: f64,
343
344 pub message_overhead: f64,
346
347 pub memory_usage_bytes: usize,
349
350 pub cpu_utilization: f64,
352}
353
354impl Default for ConsensusConfig {
355 fn default() -> Self {
356 Self {
357 algorithm: ConsensusAlgorithm::Raft,
358 quorum_size: 3,
359 election_timeout_ms: 5000,
360 heartbeat_interval_ms: 1000,
361 max_entries_per_append: 100,
362 log_compaction_threshold: 10000,
363 snapshot_interval: Duration::from_secs(300), byzantine_threshold: 1,
365 enable_optimization: true,
366 consensus_timeout_ms: 30000, }
368 }
369}
370
371impl<T> ConsensusProposal<T> {
372 pub fn new(proposal_id: String, proposer: String, data: T) -> Self {
374 Self {
375 proposal_id,
376 proposer,
377 timestamp: SystemTime::now(),
378 data,
379 priority: 0,
380 required_quorum: 3,
381 metadata: HashMap::new(),
382 }
383 }
384
385 pub fn with_priority(mut self, priority: u32) -> Self {
387 self.priority = priority;
388 self
389 }
390
391 pub fn with_quorum(mut self, quorum: usize) -> Self {
393 self.required_quorum = quorum;
394 self
395 }
396
397 pub fn with_metadata(mut self, key: String, value: String) -> Self {
399 self.metadata.insert(key, value);
400 self
401 }
402}
403
404impl ConsensusVote {
405 pub fn new(voter: String, vote: VoteDecision) -> Self {
407 Self {
408 voter,
409 vote,
410 timestamp: SystemTime::now(),
411 signature: None,
412 metadata: HashMap::new(),
413 }
414 }
415
416 pub fn with_signature(mut self, signature: String) -> Self {
418 self.signature = Some(signature);
419 self
420 }
421
422 pub fn with_metadata(mut self, key: String, value: String) -> Self {
424 self.metadata.insert(key, value);
425 self
426 }
427}
428
429#[cfg(test)]
430mod tests {
431 use super::*;
432
433 #[test]
434 fn test_consensus_config_default() {
435 let config = ConsensusConfig::default();
436 assert_eq!(config.algorithm, ConsensusAlgorithm::Raft);
437 assert_eq!(config.quorum_size, 3);
438 assert!(config.enable_optimization);
439 }
440
441 #[test]
442 fn test_consensus_proposal() {
443 let proposal = ConsensusProposal::new(
444 "test_proposal".to_string(),
445 "node1".to_string(),
446 "test_data".to_string(),
447 );
448
449 assert_eq!(proposal.proposal_id, "test_proposal");
450 assert_eq!(proposal.proposer, "node1");
451 assert_eq!(proposal.priority, 0);
452 }
453
454 #[test]
455 fn test_consensus_vote() {
456 let vote = ConsensusVote::new("node1".to_string(), VoteDecision::Accept);
457 assert_eq!(vote.voter, "node1");
458 assert_eq!(vote.vote, VoteDecision::Accept);
459 assert!(vote.signature.is_none());
460 }
461
462 #[test]
463 fn test_consensus_stats() {
464 let stats = ConsensusStats::default();
465 assert_eq!(stats.total_decisions, 0);
466 assert_eq!(stats.health_score, 0.0);
467 }
468}