162 lines
4.3 KiB
Rust
162 lines
4.3 KiB
Rust
//! 验证者管理
|
||
|
||
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);
|
||
}
|
||
}
|