123 lines
2.9 KiB
Rust
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));
|
|
}
|
|
}
|