pub mod coordinator;
pub mod majority;
pub mod pbft;
pub mod proof_of_stake;
pub mod raft;
use crate::error::{MetricsError, Result};
use scirs2_core::numeric::Float;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::time::{Duration, Instant, SystemTime};
pub use coordinator::*;
pub use majority::*;
pub use pbft::*;
pub use proof_of_stake::*;
pub use raft::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusConfig {
pub algorithm: ConsensusAlgorithm,
pub quorum_size: usize,
pub election_timeout_ms: u64,
pub heartbeat_interval_ms: u64,
pub max_entries_per_append: usize,
pub log_compaction_threshold: usize,
pub snapshot_interval: Duration,
pub byzantine_threshold: usize,
pub enable_optimization: bool,
pub consensus_timeout_ms: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ConsensusAlgorithm {
Raft,
PBFT,
ProofOfStake,
SimpleMajority,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusSystemState {
pub current_leader: Option<String>,
pub active_participants: HashSet<String>,
pub current_term: u64,
pub last_consensus: SystemTime,
pub consensus_stats: ConsensusStats,
pub algorithm_state: AlgorithmSpecificState,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AlgorithmSpecificState {
Raft(raft::RaftState),
PBFT(pbft::PbftState),
ProofOfStake(proof_of_stake::PoSState),
SimpleMajority(majority::MajorityState),
Custom(HashMap<String, String>),
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ConsensusStats {
pub total_decisions: u64,
pub avg_consensus_time_ms: f64,
pub failed_attempts: u64,
pub leader_changes: u64,
pub byzantine_failures: u64,
pub network_partitions: u64,
pub health_score: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusProposal<T> {
pub proposal_id: String,
pub proposer: String,
pub timestamp: SystemTime,
pub data: T,
pub priority: u32,
pub required_quorum: usize,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusDecision<T> {
pub decision_id: String,
pub proposal: ConsensusProposal<T>,
pub outcome: DecisionOutcome,
pub participants: HashSet<String>,
pub timestamp: SystemTime,
pub algorithm: ConsensusAlgorithm,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum DecisionOutcome {
Accepted,
Rejected,
Timeout,
InsufficientQuorum,
ByzantineFault,
NetworkPartition,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusVote {
pub voter: String,
pub vote: VoteDecision,
pub timestamp: SystemTime,
pub signature: Option<String>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum VoteDecision {
Accept,
Reject,
Abstain,
}
#[allow(async_fn_in_trait)]
pub trait ConsensusManager<T>: Send + Sync {
async fn initialize(&mut self) -> Result<()>;
async fn propose(&mut self, proposal: ConsensusProposal<T>) -> Result<String>;
async fn vote(&mut self, proposal_id: &str, vote: ConsensusVote) -> Result<()>;
async fn get_decision(&self, proposal_id: &str) -> Result<Option<ConsensusDecision<T>>>;
async fn handle_node_failure(&mut self, node_id: &str) -> Result<()>;
async fn handle_node_recovery(&mut self, node_id: &str) -> Result<()>;
async fn get_state(&self) -> Result<ConsensusSystemState>;
async fn get_health_score(&self) -> Result<f64>;
async fn shutdown(&mut self) -> Result<()>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusEvent {
pub event_id: String,
pub event_type: ConsensusEventType,
pub timestamp: SystemTime,
pub nodes: Vec<String>,
pub data: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ConsensusEventType {
ProposalSubmitted,
VoteCast,
DecisionReached,
LeaderElection,
LeaderChange,
NodeFailure,
NodeRecovery,
ByzantineBehavior,
NetworkPartition,
PartitionHealed,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ConsensusPerformanceMetrics {
pub avg_proposal_time_ms: f64,
pub avg_voting_time_ms: f64,
pub success_rate: f64,
pub message_overhead: f64,
pub memory_usage_bytes: usize,
pub cpu_utilization: f64,
}
impl Default for ConsensusConfig {
fn default() -> Self {
Self {
algorithm: ConsensusAlgorithm::Raft,
quorum_size: 3,
election_timeout_ms: 5000,
heartbeat_interval_ms: 1000,
max_entries_per_append: 100,
log_compaction_threshold: 10000,
snapshot_interval: Duration::from_secs(300), byzantine_threshold: 1,
enable_optimization: true,
consensus_timeout_ms: 30000, }
}
}
impl<T> ConsensusProposal<T> {
pub fn new(proposal_id: String, proposer: String, data: T) -> Self {
Self {
proposal_id,
proposer,
timestamp: SystemTime::now(),
data,
priority: 0,
required_quorum: 3,
metadata: HashMap::new(),
}
}
pub fn with_priority(mut self, priority: u32) -> Self {
self.priority = priority;
self
}
pub fn with_quorum(mut self, quorum: usize) -> Self {
self.required_quorum = quorum;
self
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.insert(key, value);
self
}
}
impl ConsensusVote {
pub fn new(voter: String, vote: VoteDecision) -> Self {
Self {
voter,
vote,
timestamp: SystemTime::now(),
signature: None,
metadata: HashMap::new(),
}
}
pub fn with_signature(mut self, signature: String) -> Self {
self.signature = Some(signature);
self
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.insert(key, value);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_consensus_config_default() {
let config = ConsensusConfig::default();
assert_eq!(config.algorithm, ConsensusAlgorithm::Raft);
assert_eq!(config.quorum_size, 3);
assert!(config.enable_optimization);
}
#[test]
fn test_consensus_proposal() {
let proposal = ConsensusProposal::new(
"test_proposal".to_string(),
"node1".to_string(),
"test_data".to_string(),
);
assert_eq!(proposal.proposal_id, "test_proposal");
assert_eq!(proposal.proposer, "node1");
assert_eq!(proposal.priority, 0);
}
#[test]
fn test_consensus_vote() {
let vote = ConsensusVote::new("node1".to_string(), VoteDecision::Accept);
assert_eq!(vote.voter, "node1");
assert_eq!(vote.vote, VoteDecision::Accept);
assert!(vote.signature.is_none());
}
#[test]
fn test_consensus_stats() {
let stats = ConsensusStats::default();
assert_eq!(stats.total_decisions, 0);
assert_eq!(stats.health_score, 0.0);
}
}