NAC_Blockchain/charter-std/governance/voting.ch

801 lines
21 KiB
Plaintext
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.

///! # 投票系统
///!
///! Voting System
///! 提供提案投票、权重计算和委托投票功能
///!
///! **版本**: v1.0
///! **模块**: charter-std/governance/voting.ch
use utils::math::{safe_add, safe_sub, safe_mul, safe_div};
use utils::crypto::sha3_384_hash;
// ============================================================================
// 投票枚举
// ============================================================================
/// 投票选项
pub enum VoteOption {
/// 赞成
For,
/// 反对
Against,
/// 弃权
Abstain
}
/// 投票状态
pub enum VoteStatus {
/// 待开始
Pending,
/// 进行中
Active,
/// 已结束
Ended,
/// 已取消
Cancelled
}
/// 投票结果
pub enum VoteResult {
/// 未决定
Undecided,
/// 通过
Passed,
/// 未通过
Failed,
/// 法定人数不足
QuorumNotReached
}
// ============================================================================
// 投票结构
// ============================================================================
/// 投票信息
struct Vote {
/// 投票ID
vote_id: Hash,
/// 提案ID
proposal_id: Hash,
/// 标题
title: String,
/// 描述
description: String,
/// 创建者
creator: Address,
/// 开始时间
start_time: Timestamp,
/// 结束时间
end_time: Timestamp,
/// 赞成票数
votes_for: u256,
/// 反对票数
votes_against: u256,
/// 弃权票数
votes_abstain: u256,
/// 总投票权重
total_weight: u256,
/// 法定人数(基点)
quorum: u16,
/// 通过阈值(基点)
threshold: u16,
/// 投票状态
status: VoteStatus,
/// 投票结果
result: VoteResult,
/// 是否允许委托
allow_delegation: bool
}
/// 投票记录
struct VoteRecord {
/// 投票者
voter: Address,
/// 投票ID
vote_id: Hash,
/// 投票选项
option: VoteOption,
/// 投票权重
weight: u256,
/// 投票时间
timestamp: Timestamp,
/// 是否通过委托
is_delegated: bool,
/// 委托人(如果是委托投票)
delegator: Option<Address>
}
/// 委托记录
struct Delegation {
/// 委托人
delegator: Address,
/// 被委托人
delegate: Address,
/// 委托权重
weight: u256,
/// 委托时间
delegated_at: Timestamp,
/// 过期时间(可选)
expires_at: Option<Timestamp>
}
/// 投票权重快照
struct WeightSnapshot {
/// 地址
address: Address,
/// 权重
weight: u256,
/// 快照时间
snapshot_at: Timestamp
}
// ============================================================================
// 投票事件
// ============================================================================
/// 投票创建事件
event VoteCreated {
vote_id: Hash,
proposal_id: Hash,
title: String,
creator: Address,
start_time: Timestamp,
end_time: Timestamp,
quorum: u16,
threshold: u16
}
/// 投票提交事件
event VoteCast {
vote_id: Hash,
voter: Address,
option: VoteOption,
weight: u256,
timestamp: Timestamp
}
/// 投票结束事件
event VoteEnded {
vote_id: Hash,
result: VoteResult,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
timestamp: Timestamp
}
/// 委托事件
event DelegationCreated {
delegator: Address,
delegate: Address,
weight: u256,
timestamp: Timestamp
}
/// 取消委托事件
event DelegationRevoked {
delegator: Address,
delegate: Address,
timestamp: Timestamp
}
// ============================================================================
// 投票系统
// ============================================================================
/// 投票系统
certificate VotingSystem {
/// 投票 (vote_id => vote)
let _votes: Map<Hash, Vote>;
/// 投票记录 (vote_id => voter => record)
let _vote_records: Map<Hash, Map<Address, VoteRecord>>;
/// 委托 (delegator => delegate => delegation)
let _delegations: Map<Address, Map<Address, Delegation>>;
/// 权重快照 (vote_id => address => snapshot)
let _weight_snapshots: Map<Hash, Map<Address, WeightSnapshot>>;
/// 治理代币地址
let _governance_token: Address;
/// 管理员地址
let _admin: Address;
/// 默认法定人数(基点)
let _default_quorum: u16;
/// 默认通过阈值(基点)
let _default_threshold: u16;
/// 最小投票期限(秒)
let _min_voting_period: Duration;
/// 最大投票期限(秒)
let _max_voting_period: Duration;
// ========== 构造函数 ==========
constructor(
governance_token: Address,
default_quorum: u16,
default_threshold: u16,
min_period: Duration,
max_period: Duration
) {
require(!governance_token.is_zero(), "Invalid governance token");
require(default_quorum <= 10000, "Invalid quorum");
require(default_threshold <= 10000, "Invalid threshold");
require(min_period > 0, "Min period must be positive");
require(max_period > min_period, "Max period must be > min period");
self._governance_token = governance_token;
self._admin = msg.sender;
self._default_quorum = default_quorum;
self._default_threshold = default_threshold;
self._min_voting_period = min_period;
self._max_voting_period = max_period;
}
// ========== 投票管理 ==========
/// 创建投票
///
/// # 参数
/// - `proposal_id`: 提案ID
/// - `title`: 标题
/// - `description`: 描述
/// - `duration`: 投票期限(秒)
/// - `quorum`: 法定人数基点0表示使用默认值
/// - `threshold`: 通过阈值基点0表示使用默认值
/// - `allow_delegation`: 是否允许委托
///
/// # 返回
/// - `Hash`: 投票ID
pub fn create_vote(
proposal_id: Hash,
title: String,
description: String,
duration: Duration,
quorum: u16,
threshold: u16,
allow_delegation: bool
) -> Hash {
require(!title.is_empty(), "Title required");
require(duration >= self._min_voting_period, "Duration too short");
require(duration <= self._max_voting_period, "Duration too long");
let final_quorum = if quorum == 0 {
self._default_quorum
} else {
require(quorum <= 10000, "Invalid quorum");
quorum
};
let final_threshold = if threshold == 0 {
self._default_threshold
} else {
require(threshold <= 10000, "Invalid threshold");
threshold
};
// 生成投票ID
let vote_id = self._generate_vote_id(proposal_id, msg.sender);
let start_time = block.timestamp;
let end_time = block.timestamp + duration;
let vote = Vote {
vote_id: vote_id,
proposal_id: proposal_id,
title: title.clone(),
description: description,
creator: msg.sender,
start_time: start_time,
end_time: end_time,
votes_for: 0,
votes_against: 0,
votes_abstain: 0,
total_weight: 0,
quorum: final_quorum,
threshold: final_threshold,
status: VoteStatus::Active,
result: VoteResult::Undecided,
allow_delegation: allow_delegation
};
self._votes[vote_id] = vote;
emit VoteCreated {
vote_id: vote_id,
proposal_id: proposal_id,
title: title,
creator: msg.sender,
start_time: start_time,
end_time: end_time,
quorum: final_quorum,
threshold: final_threshold
};
return vote_id;
}
/// 投票
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `option`: 投票选项
///
/// # 返回
/// - `bool`: 是否成功
pub fn cast_vote(vote_id: Hash, option: VoteOption) -> bool {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(vote.status == VoteStatus::Active, "Vote not active");
require(block.timestamp >= vote.start_time, "Vote not started");
require(block.timestamp < vote.end_time, "Vote ended");
// 检查是否已投票
if let Some(records) = self._vote_records.get(vote_id) {
require(!records.contains_key(msg.sender), "Already voted");
}
// 获取投票权重(实际需要查询治理代币余额)
let weight = self._get_voting_weight(msg.sender, vote_id);
require(weight > 0, "No voting power");
// 记录投票
let record = VoteRecord {
voter: msg.sender,
vote_id: vote_id,
option: option,
weight: weight,
timestamp: block.timestamp,
is_delegated: false,
delegator: None
};
if !self._vote_records.contains_key(vote_id) {
self._vote_records[vote_id] = Map::new();
}
self._vote_records[vote_id][msg.sender] = record;
// 更新投票统计
match option {
VoteOption::For => {
vote.votes_for = safe_add(vote.votes_for, weight);
},
VoteOption::Against => {
vote.votes_against = safe_add(vote.votes_against, weight);
},
VoteOption::Abstain => {
vote.votes_abstain = safe_add(vote.votes_abstain, weight);
}
}
vote.total_weight = safe_add(vote.total_weight, weight);
self._votes[vote_id] = vote;
emit VoteCast {
vote_id: vote_id,
voter: msg.sender,
option: option,
weight: weight,
timestamp: block.timestamp
};
return true;
}
/// 结束投票
///
/// # 参数
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `VoteResult`: 投票结果
pub fn end_vote(vote_id: Hash) -> VoteResult {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(vote.status == VoteStatus::Active, "Vote not active");
require(block.timestamp >= vote.end_time, "Vote not ended yet");
// 计算结果
let result = self._calculate_result(vote_id);
vote.status = VoteStatus::Ended;
vote.result = result;
self._votes[vote_id] = vote;
emit VoteEnded {
vote_id: vote_id,
result: result,
votes_for: vote.votes_for,
votes_against: vote.votes_against,
votes_abstain: vote.votes_abstain,
timestamp: block.timestamp
};
return result;
}
/// 取消投票
///
/// # 参数
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `bool`: 是否成功
pub fn cancel_vote(vote_id: Hash) -> bool {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(
msg.sender == vote.creator || msg.sender == self._admin,
"Not authorized"
);
require(vote.status == VoteStatus::Active, "Vote not active");
vote.status = VoteStatus::Cancelled;
self._votes[vote_id] = vote;
return true;
}
// ========== 委托投票 ==========
/// 委托投票权
///
/// # 参数
/// - `delegate`: 被委托人
/// - `expires_at`: 过期时间(可选)
///
/// # 返回
/// - `bool`: 是否成功
pub fn delegate_vote(
delegate: Address,
expires_at: Option<Timestamp>
) -> bool {
require(!delegate.is_zero(), "Invalid delegate");
require(delegate != msg.sender, "Cannot delegate to self");
if let Some(expiry) = expires_at {
require(expiry > block.timestamp, "Invalid expiry time");
}
// 获取委托权重(实际需要查询治理代币余额)
let weight = self._get_base_voting_weight(msg.sender);
require(weight > 0, "No voting power");
let delegation = Delegation {
delegator: msg.sender,
delegate: delegate,
weight: weight,
delegated_at: block.timestamp,
expires_at: expires_at
};
if !self._delegations.contains_key(msg.sender) {
self._delegations[msg.sender] = Map::new();
}
self._delegations[msg.sender][delegate] = delegation;
emit DelegationCreated {
delegator: msg.sender,
delegate: delegate,
weight: weight,
timestamp: block.timestamp
};
return true;
}
/// 撤销委托
///
/// # 参数
/// - `delegate`: 被委托人
///
/// # 返回
/// - `bool`: 是否成功
pub fn revoke_delegation(delegate: Address) -> bool {
require(self._delegations.contains_key(msg.sender), "No delegation");
require(
self._delegations[msg.sender].contains_key(delegate),
"Delegation not found"
);
self._delegations[msg.sender].remove(delegate);
emit DelegationRevoked {
delegator: msg.sender,
delegate: delegate,
timestamp: block.timestamp
};
return true;
}
/// 使用委托权投票
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `option`: 投票选项
/// - `delegator`: 委托人
///
/// # 返回
/// - `bool`: 是否成功
pub fn cast_delegated_vote(
vote_id: Hash,
option: VoteOption,
delegator: Address
) -> bool {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(vote.allow_delegation, "Delegation not allowed");
require(vote.status == VoteStatus::Active, "Vote not active");
require(block.timestamp >= vote.start_time, "Vote not started");
require(block.timestamp < vote.end_time, "Vote ended");
// 检查委托
require(self._delegations.contains_key(delegator), "No delegation");
require(
self._delegations[delegator].contains_key(msg.sender),
"Not delegated to you"
);
let delegation = self._delegations[delegator][msg.sender];
// 检查是否过期
if let Some(expiry) = delegation.expires_at {
require(block.timestamp < expiry, "Delegation expired");
}
// 检查委托人是否已投票
if let Some(records) = self._vote_records.get(vote_id) {
require(!records.contains_key(delegator), "Delegator already voted");
}
let weight = delegation.weight;
// 记录投票
let record = VoteRecord {
voter: msg.sender,
vote_id: vote_id,
option: option,
weight: weight,
timestamp: block.timestamp,
is_delegated: true,
delegator: Some(delegator)
};
if !self._vote_records.contains_key(vote_id) {
self._vote_records[vote_id] = Map::new();
}
self._vote_records[vote_id][delegator] = record;
// 更新投票统计
match option {
VoteOption::For => {
vote.votes_for = safe_add(vote.votes_for, weight);
},
VoteOption::Against => {
vote.votes_against = safe_add(vote.votes_against, weight);
},
VoteOption::Abstain => {
vote.votes_abstain = safe_add(vote.votes_abstain, weight);
}
}
vote.total_weight = safe_add(vote.total_weight, weight);
self._votes[vote_id] = vote;
emit VoteCast {
vote_id: vote_id,
voter: delegator,
option: option,
weight: weight,
timestamp: block.timestamp
};
return true;
}
// ========== 查询函数 ==========
/// 获取投票信息
///
/// # 参数
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `Vote`: 投票信息
pub fn get_vote(vote_id: Hash) -> Vote {
require(self._votes.contains_key(vote_id), "Vote not found");
return self._votes[vote_id];
}
/// 获取投票记录
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `voter`: 投票者地址
///
/// # 返回
/// - `Option<VoteRecord>`: 投票记录
pub fn get_vote_record(vote_id: Hash, voter: Address) -> Option<VoteRecord> {
return self._vote_records.get(vote_id)
.and_then(|m| m.get(voter));
}
/// 获取委托信息
///
/// # 参数
/// - `delegator`: 委托人
/// - `delegate`: 被委托人
///
/// # 返回
/// - `Option<Delegation>`: 委托信息
pub fn get_delegation(
delegator: Address,
delegate: Address
) -> Option<Delegation> {
return self._delegations.get(delegator)
.and_then(|m| m.get(delegate));
}
/// 获取投票权重
///
/// # 参数
/// - `voter`: 投票者地址
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `u256`: 投票权重
pub fn get_voting_weight(voter: Address, vote_id: Hash) -> u256 {
return self._get_voting_weight(voter, vote_id);
}
/// 检查是否已投票
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `voter`: 投票者地址
///
/// # 返回
/// - `bool`: 是否已投票
pub fn has_voted(vote_id: Hash, voter: Address) -> bool {
return self._vote_records.get(vote_id)
.map(|m| m.contains_key(voter))
.unwrap_or(false);
}
// ========== 内部函数 ==========
/// 生成投票ID
fn _generate_vote_id(proposal_id: Hash, creator: Address) -> Hash {
let mut data = Bytes::new();
data.extend(proposal_id.as_bytes());
data.extend(creator.as_bytes());
data.extend(block.timestamp.to_bytes());
data.extend(tx.hash.as_bytes());
return sha3_384_hash(data);
}
/// 获取基础投票权重(不包括委托)
fn _get_base_voting_weight(voter: Address) -> u256 {
// 实际需要查询治理代币余额
// 这里简化处理
return 100;
}
/// 获取投票权重(包括委托)
fn _get_voting_weight(voter: Address, vote_id: Hash) -> u256 {
// 检查是否有快照
if let Some(snapshots) = self._weight_snapshots.get(vote_id) {
if let Some(snapshot) = snapshots.get(voter) {
return snapshot.weight;
}
}
// 获取基础权重
let base_weight = self._get_base_voting_weight(voter);
// 计算委托给该投票者的权重
let mut delegated_weight = 0u256;
// 实际需要遍历所有委托记录
// 这里简化处理
return safe_add(base_weight, delegated_weight);
}
/// 计算投票结果
fn _calculate_result(vote_id: Hash) -> VoteResult {
let vote = self._votes[vote_id];
// 检查法定人数
// 实际需要查询治理代币总供应量
let total_supply = 10000u256; // 简化
let participation = safe_mul(vote.total_weight, 10000) / total_supply;
if participation < vote.quorum as u256 {
return VoteResult::QuorumNotReached;
}
// 计算赞成票比例
let valid_votes = safe_add(vote.votes_for, vote.votes_against);
if valid_votes == 0 {
return VoteResult::Failed;
}
let approval_rate = safe_mul(vote.votes_for, 10000) / valid_votes;
if approval_rate >= vote.threshold as u256 {
return VoteResult::Passed;
} else {
return VoteResult::Failed;
}
}
// ========== 管理函数 ==========
/// 设置默认法定人数
pub fn set_default_quorum(quorum: u16) -> bool {
require(msg.sender == self._admin, "Only admin");
require(quorum <= 10000, "Invalid quorum");
self._default_quorum = quorum;
return true;
}
/// 设置默认通过阈值
pub fn set_default_threshold(threshold: u16) -> bool {
require(msg.sender == self._admin, "Only admin");
require(threshold <= 10000, "Invalid threshold");
self._default_threshold = threshold;
return true;
}
}