NAC_Blockchain/_archive/nac-cbpp-bft-backup-20260307/validator.rs

162 lines
4.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 验证者管理
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// 验证者信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Validator {
pub address: String,
pub voting_power: u64,
pub stake: u64,
pub is_active: bool,
}
impl Validator {
pub fn new(address: String, stake: u64) -> Self {
Validator {
address,
voting_power: stake,
stake,
is_active: true,
}
}
}
/// 验证者集合
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorSet {
validators: HashMap<String, Validator>,
total_voting_power: u64,
}
impl ValidatorSet {
pub fn new() -> Self {
ValidatorSet {
validators: HashMap::new(),
total_voting_power: 0,
}
}
/// 添加验证者
pub fn add_validator(&mut self, validator: Validator) {
self.total_voting_power += validator.voting_power;
self.validators.insert(validator.address.clone(), validator);
}
/// 移除验证者
pub fn remove_validator(&mut self, address: &str) -> Option<Validator> {
if let Some(validator) = self.validators.remove(address) {
self.total_voting_power -= validator.voting_power;
Some(validator)
} else {
None
}
}
/// 获取验证者
pub fn get_validator(&self, address: &str) -> Option<&Validator> {
self.validators.get(address)
}
/// 更新验证者权益
pub fn update_stake(&mut self, address: &str, new_stake: u64) -> bool {
if let Some(validator) = self.validators.get_mut(address) {
self.total_voting_power = self.total_voting_power
.saturating_sub(validator.voting_power)
.saturating_add(new_stake);
validator.stake = new_stake;
validator.voting_power = new_stake;
true
} else {
false
}
}
/// 获取活跃验证者列表
pub fn get_active_validators(&self) -> Vec<&Validator> {
self.validators
.values()
.filter(|v| v.is_active)
.collect()
}
/// 获取验证者数量
pub fn len(&self) -> usize {
self.validators.len()
}
/// 检查是否为空
pub fn is_empty(&self) -> bool {
self.validators.is_empty()
}
/// 获取总投票权
pub fn total_voting_power(&self) -> u64 {
self.total_voting_power
}
/// 检查是否有足够的投票权2/3+
pub fn has_quorum(&self, voting_power: u64) -> bool {
voting_power * 3 > self.total_voting_power * 2
}
}
impl Default for ValidatorSet {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validator_creation() {
let validator = Validator::new("validator1".to_string(), 1000);
assert_eq!(validator.stake, 1000);
assert_eq!(validator.voting_power, 1000);
assert!(validator.is_active);
}
#[test]
fn test_validator_set() {
let mut set = ValidatorSet::new();
set.add_validator(Validator::new("v1".to_string(), 1000));
set.add_validator(Validator::new("v2".to_string(), 2000));
set.add_validator(Validator::new("v3".to_string(), 3000));
assert_eq!(set.len(), 3);
assert_eq!(set.total_voting_power(), 6000);
}
#[test]
fn test_quorum() {
let mut set = ValidatorSet::new();
set.add_validator(Validator::new("v1".to_string(), 1000));
set.add_validator(Validator::new("v2".to_string(), 1000));
set.add_validator(Validator::new("v3".to_string(), 1000));
// 总投票权3000需要>2000才能达到2/3+
assert!(set.has_quorum(2001));
assert!(!set.has_quorum(2000));
assert!(!set.has_quorum(1500));
}
#[test]
fn test_update_stake() {
let mut set = ValidatorSet::new();
set.add_validator(Validator::new("v1".to_string(), 1000));
assert!(set.update_stake("v1", 2000));
assert_eq!(set.total_voting_power(), 2000);
let validator = set.get_validator("v1").expect("FIX-006: unexpected None/Err");
assert_eq!(validator.stake, 2000);
}
}