scirs2_metrics/optimization/distributed_advanced/consensus/
majority.rs1use crate::error::{MetricsError, Result};
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct MajorityConsensus {
12 node_id: String,
13 nodes: Vec<String>,
14 votes: HashMap<String, bool>,
15 proposal_id: u64,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Vote {
20 voter_id: String,
21 proposal_id: u64,
22 decision: bool,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct MajorityState {
28 pub current_proposal_id: u64,
29 pub active_votes: HashMap<String, Vote>,
30 pub completed_proposals: Vec<u64>,
31 pub consensus_threshold: f64,
32}
33
34impl Default for MajorityState {
35 fn default() -> Self {
36 Self {
37 current_proposal_id: 0,
38 active_votes: HashMap::new(),
39 completed_proposals: Vec::new(),
40 consensus_threshold: 0.5, }
42 }
43}
44
45impl MajorityConsensus {
46 pub fn new(node_id: String, nodes: Vec<String>) -> Self {
47 Self {
48 node_id,
49 nodes,
50 votes: HashMap::new(),
51 proposal_id: 0,
52 }
53 }
54
55 pub fn propose(&mut self, data: Vec<u8>) -> Result<u64> {
56 self.proposal_id += 1;
57 self.votes.clear();
58 self.votes.insert(self.node_id.clone(), true);
60 Ok(self.proposal_id)
61 }
62
63 pub fn vote(&mut self, vote: Vote) -> Result<()> {
64 if vote.proposal_id != self.proposal_id {
65 return Err(MetricsError::InvalidOperation("Invalid proposal ID".into()));
66 }
67
68 self.votes.insert(vote.voter_id, vote.decision);
69 Ok(())
70 }
71
72 pub fn has_majority(&self) -> bool {
73 let yes_votes = self.votes.values().filter(|&&v| v).count();
74 let total_nodes = self.nodes.len();
75 yes_votes > total_nodes / 2
76 }
77
78 pub fn is_decided(&self) -> bool {
79 let total_votes = self.votes.len();
80 let total_nodes = self.nodes.len();
81
82 let yes_votes = self.votes.values().filter(|&&v| v).count();
84 let no_votes = total_votes - yes_votes;
85
86 yes_votes > total_nodes / 2 || no_votes > total_nodes / 2
88 }
89
90 pub fn get_result(&self) -> Option<bool> {
91 if self.is_decided() {
92 Some(self.has_majority())
93 } else {
94 None
95 }
96 }
97}