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

123 lines
2.9 KiB
Rust

//! 投票机制
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
/// 投票类型
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum VoteType {
Prevote, // 预投票
Precommit, // 预提交
}
/// 投票
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Vote {
pub vote_type: VoteType,
pub height: u64,
pub round: u32,
pub block_hash: String,
pub validator: String,
pub timestamp: DateTime<Utc>,
pub signature: String,
}
impl Vote {
pub fn new(
vote_type: VoteType,
height: u64,
round: u32,
block_hash: String,
validator: String,
) -> Self {
Vote {
vote_type,
height,
round,
block_hash,
validator,
timestamp: Utc::now(),
signature: String::new(),
}
}
/// 创建预投票
pub fn prevote(height: u64, round: u32, block_hash: String, validator: String) -> Self {
Self::new(VoteType::Prevote, height, round, block_hash, validator)
}
/// 创建预提交
pub fn precommit(height: u64, round: u32, block_hash: String, validator: String) -> Self {
Self::new(VoteType::Precommit, height, round, block_hash, validator)
}
}
/// 投票集合
#[derive(Debug, Clone)]
pub struct VoteSet {
votes: Vec<Vote>,
total_voting_power: u64,
}
impl VoteSet {
pub fn new(total_voting_power: u64) -> Self {
VoteSet {
votes: Vec::new(),
total_voting_power,
}
}
/// 添加投票
pub fn add_vote(&mut self, vote: Vote) {
self.votes.push(vote);
}
/// 获取投票数量
pub fn len(&self) -> usize {
self.votes.len()
}
/// 检查是否为空
pub fn is_empty(&self) -> bool {
self.votes.is_empty()
}
/// 检查是否达到2/3+多数
pub fn has_two_thirds_majority(&self, voting_power: u64) -> bool {
voting_power * 3 > self.total_voting_power * 2
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vote_creation() {
let vote = Vote::prevote(1, 0, "block_hash".to_string(), "validator1".to_string());
assert_eq!(vote.vote_type, VoteType::Prevote);
assert_eq!(vote.height, 1);
assert_eq!(vote.round, 0);
}
#[test]
fn test_vote_set() {
let mut vote_set = VoteSet::new(3000);
vote_set.add_vote(Vote::prevote(1, 0, "hash".to_string(), "v1".to_string()));
vote_set.add_vote(Vote::prevote(1, 0, "hash".to_string(), "v2".to_string()));
assert_eq!(vote_set.len(), 2);
assert!(!vote_set.is_empty());
}
#[test]
fn test_two_thirds_majority() {
let vote_set = VoteSet::new(3000);
// 需要>2000才能达到2/3+
assert!(vote_set.has_two_thirds_majority(2001));
assert!(!vote_set.has_two_thirds_majority(2000));
}
}