NAC_Blockchain/nac-udm/src/l1_protocol/acc/acc_governance.rs

351 lines
13 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.

//! acc_governance - NAC 原生协议实现
use crate::primitives::{Address, Hash, Timestamp};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
/// ACCGovernanceError 错误类型
pub enum ACCGovernanceError {
/// ProposalNotFound 变体
ProposalNotFound(Hash),
/// ProposalAlreadyExecuted 变体
ProposalAlreadyExecuted(Hash),
/// VotingPeriodEnded 变体
VotingPeriodEnded(Hash),
/// AlreadyVoted 变体
AlreadyVoted(Address),
/// InsufficientVotingPower 变体
InsufficientVotingPower {
/// 所需数量
required: u128,
/// actual 字段
actual: u128,
},
/// QuorumNotReached 变体
QuorumNotReached {
/// 所需数量
required: u128,
/// actual 字段
actual: u128,
},
/// 宪法收据无效错误
InvalidConstitutionalReceipt,
/// 未授权操作错误
Unauthorized(Address),
}
impl std::fmt::Display for ACCGovernanceError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ProposalNotFound(h) => write!(f, "提案不存在: {}", h.to_hex()),
Self::ProposalAlreadyExecuted(h) => write!(f, "提案已执行: {}", h.to_hex()),
Self::VotingPeriodEnded(h) => write!(f, "投票期已结束: {}", h.to_hex()),
Self::AlreadyVoted(a) => write!(f, "已投票: {}", a.to_hex()),
Self::InsufficientVotingPower { required, actual } => write!(f, "投票权不足: 需要 {},实际 {}", required, actual),
Self::QuorumNotReached { required, actual } => write!(f, "未达法定人数: 需要 {},实际 {}", required, actual),
Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"),
Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
/// ProposalType 类型
pub enum ProposalType {
/// ParameterChange 变体
ParameterChange {
/// parameter 字段
parameter: String,
/// new_value 字段
new_value: Vec<u8>,
},
/// ProtocolUpgrade 变体
ProtocolUpgrade {
/// new_version 字段
new_version: String,
/// upgrade_hash 哈希值48字节 SHA3-384
upgrade_hash: Hash,
},
/// AssetPolicyChange 变体
AssetPolicyChange {
/// 资产标识符
asset_id: Hash,
/// policy_hash 哈希值48字节 SHA3-384
policy_hash: Hash,
},
/// EmergencyPause 变体
EmergencyPause {
/// 操作原因说明
reason: String,
},
/// GovernanceMemberChange 变体
GovernanceMemberChange {
/// member 字段
member: Address,
/// action 字段
action: MemberAction,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
/// MemberAction 枚举类型
pub enum MemberAction {
/// Add 变体
Add,
/// Remove 变体
Remove,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
/// ProposalStatus 状态枚举
pub enum ProposalStatus {
/// 活跃状态
Active,
/// 已通过状态
Passed,
/// 已拒绝状态
Rejected,
/// 已执行状态
Executed,
/// 已取消状态
Cancelled,
/// 已过期状态
Expired,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
/// VoteChoice 枚举类型
pub enum VoteChoice {
/// For 变体
For,
/// Against 变体
Against,
/// Abstain 变体
Abstain,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
/// GovernanceProposal 结构体
pub struct GovernanceProposal {
/// 治理提案标识符
pub proposal_id: Hash,
/// proposer 字段
pub proposer: Address,
/// proposal_type 字段
pub proposal_type: ProposalType,
/// 详细描述
pub description: String,
/// 状态
pub status: ProposalStatus,
/// votes_for 字段
pub votes_for: u128,
/// votes_against 字段
pub votes_against: u128,
/// votes_abstain 字段
pub votes_abstain: u128,
/// vote_records 字段
pub vote_records: HashMap<Address, VoteChoice>,
/// voting_start 字段
pub voting_start: Timestamp,
/// voting_end 字段
pub voting_end: Timestamp,
/// quorum_bps 字段
pub quorum_bps: u32,
/// pass_threshold_bps 字段
pub pass_threshold_bps: u32,
/// 宪法收据哈希CBPP 共识凭证)
pub constitutional_receipt: Hash,
/// 创建时间戳
pub created_at: Timestamp,
/// 执行时间戳
pub executed_at: Option<Timestamp>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
/// GovernanceProtocolEvent 协议事件
pub enum GovernanceProtocolEvent {
/// ProposalCreated 变体
ProposalCreated {
/// 治理提案标识符
proposal_id: Hash,
/// proposer 字段
proposer: Address,
/// 操作时间戳UTC Unix 毫秒)
timestamp: Timestamp,
},
/// VoteCast 变体
VoteCast {
/// 治理提案标识符
proposal_id: Hash,
/// 投票者账户地址
voter: Address,
/// choice 字段
choice: VoteChoice,
/// voting_power 字段
voting_power: u128,
/// 操作时间戳UTC Unix 毫秒)
timestamp: Timestamp,
},
/// ProposalPassed 变体
ProposalPassed {
/// 治理提案标识符
proposal_id: Hash,
/// votes_for 字段
votes_for: u128,
/// votes_against 字段
votes_against: u128,
/// 操作时间戳UTC Unix 毫秒)
timestamp: Timestamp,
},
/// ProposalRejected 变体
ProposalRejected {
/// 治理提案标识符
proposal_id: Hash,
/// 操作原因说明
reason: String,
/// 操作时间戳UTC Unix 毫秒)
timestamp: Timestamp,
},
/// ProposalExecuted 变体
ProposalExecuted {
/// 治理提案标识符
proposal_id: Hash,
/// 操作时间戳UTC Unix 毫秒)
timestamp: Timestamp,
/// 宪法收据哈希CBPP 共识凭证)
constitutional_receipt: Hash,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
/// ACCGovernanceProtocol 协议实现
pub struct ACCGovernanceProtocol {
/// 协议唯一标识符
pub protocol_uid: String,
/// NAC-Lens 协议向量
pub lens_protocol_vector: String,
/// proposals 字段
pub proposals: HashMap<Hash, GovernanceProposal>,
/// voting_power_registry 字段
pub voting_power_registry: HashMap<Address, u128>,
/// total_voting_power 字段
pub total_voting_power: u128,
/// default_quorum_bps 字段
pub default_quorum_bps: u32,
/// default_pass_threshold_bps 字段
pub default_pass_threshold_bps: u32,
/// 待广播的 CSNP 协议事件队列
pub pending_events: Vec<GovernanceProtocolEvent>,
/// 创建时间戳
pub created_at: Timestamp,
/// 最后更新时间戳
pub updated_at: Timestamp,
}
impl ACCGovernanceProtocol {
/// new 方法
pub fn new(default_quorum_bps: u32, default_pass_threshold_bps: u32) -> Self {
Self {
protocol_uid: "nac.acc.ACCGovernanceProtocol.v1".to_string(),
lens_protocol_vector: "ACC-Governance".to_string(),
proposals: HashMap::new(),
voting_power_registry: HashMap::new(),
total_voting_power: 0,
default_quorum_bps, default_pass_threshold_bps,
pending_events: Vec::new(),
created_at: Timestamp::now(), updated_at: Timestamp::now(),
}
}
/// register_voting_power 方法
pub fn register_voting_power(&mut self, address: Address, power: u128) {
let old = self.voting_power_registry.insert(address, power).unwrap_or(0);
self.total_voting_power = self.total_voting_power.saturating_sub(old).saturating_add(power);
}
/// 创建治理提案
pub fn create_proposal(
&mut self, proposer: Address, proposal_type: ProposalType, description: String,
voting_duration_secs: u64, constitutional_receipt: Hash, timestamp: Timestamp,
) -> Result<Hash, ACCGovernanceError> {
if constitutional_receipt.is_zero() { return Err(ACCGovernanceError::InvalidConstitutionalReceipt); }
let proposer_power = self.voting_power_registry.get(&proposer).copied().unwrap_or(0);
if proposer_power == 0 {
return Err(ACCGovernanceError::InsufficientVotingPower { required: 1, actual: 0 });
}
let mut data = Vec::new();
data.extend_from_slice(proposer.as_bytes());
data.extend_from_slice(&timestamp.as_secs().to_be_bytes());
let proposal_id = Hash::sha3_384(&data);
let proposal = GovernanceProposal {
proposal_id, proposer: proposer.clone(), proposal_type, description,
status: ProposalStatus::Active,
votes_for: 0, votes_against: 0, votes_abstain: 0,
vote_records: HashMap::new(),
voting_start: timestamp.clone(),
voting_end: timestamp.add_secs(voting_duration_secs),
quorum_bps: self.default_quorum_bps,
pass_threshold_bps: self.default_pass_threshold_bps,
constitutional_receipt, created_at: timestamp.clone(), executed_at: None,
};
self.proposals.insert(proposal_id, proposal);
self.pending_events.push(GovernanceProtocolEvent::ProposalCreated { proposal_id, proposer, timestamp });
self.updated_at = Timestamp::now();
Ok(proposal_id)
}
/// 投票
pub fn cast_vote(
&mut self, proposal_id: Hash, voter: Address, choice: VoteChoice, timestamp: Timestamp,
) -> Result<(), ACCGovernanceError> {
let voting_power = self.voting_power_registry.get(&voter).copied().unwrap_or(0);
if voting_power == 0 {
return Err(ACCGovernanceError::InsufficientVotingPower { required: 1, actual: 0 });
}
let proposal = self.proposals.get_mut(&proposal_id)
.ok_or(ACCGovernanceError::ProposalNotFound(proposal_id))?;
if proposal.status != ProposalStatus::Active {
return Err(ACCGovernanceError::VotingPeriodEnded(proposal_id));
}
if proposal.vote_records.contains_key(&voter) {
return Err(ACCGovernanceError::AlreadyVoted(voter));
}
match choice {
VoteChoice::For => proposal.votes_for = proposal.votes_for.saturating_add(voting_power),
VoteChoice::Against => proposal.votes_against = proposal.votes_against.saturating_add(voting_power),
VoteChoice::Abstain => proposal.votes_abstain = proposal.votes_abstain.saturating_add(voting_power),
}
proposal.vote_records.insert(voter.clone(), choice);
self.pending_events.push(GovernanceProtocolEvent::VoteCast { proposal_id, voter, choice, voting_power, timestamp });
Ok(())
}
/// finalize_proposal 方法
pub fn finalize_proposal(
&mut self, proposal_id: Hash, constitutional_receipt: Hash, timestamp: Timestamp,
) -> Result<bool, ACCGovernanceError> {
if constitutional_receipt.is_zero() { return Err(ACCGovernanceError::InvalidConstitutionalReceipt); }
let proposal = self.proposals.get_mut(&proposal_id)
.ok_or(ACCGovernanceError::ProposalNotFound(proposal_id))?;
let total_votes = proposal.votes_for + proposal.votes_against + proposal.votes_abstain;
let quorum_required = (self.total_voting_power as u64 * proposal.quorum_bps as u64 / 10000) as u128;
if total_votes < quorum_required {
proposal.status = ProposalStatus::Rejected;
self.pending_events.push(GovernanceProtocolEvent::ProposalRejected {
proposal_id, reason: format!("未达法定人数: {} < {}", total_votes, quorum_required), timestamp,
});
return Ok(false);
}
let effective_votes = proposal.votes_for + proposal.votes_against;
let pass_required = (effective_votes as u64 * proposal.pass_threshold_bps as u64 / 10000) as u128;
let passed = proposal.votes_for >= pass_required;
if passed {
proposal.status = ProposalStatus::Executed;
proposal.executed_at = Some(timestamp.clone());
self.pending_events.push(GovernanceProtocolEvent::ProposalExecuted { proposal_id, timestamp, constitutional_receipt });
} else {
proposal.status = ProposalStatus::Rejected;
self.pending_events.push(GovernanceProtocolEvent::ProposalRejected {
proposal_id, reason: "赞成票未达阈值".to_string(), timestamp,
});
}
Ok(passed)
}
/// 获取提案详情
pub fn get_proposal(&self, id: &Hash) -> Option<&GovernanceProposal> { self.proposals.get(id) }
/// 排空待广播事件队列
pub fn drain_pending_events(&mut self) -> Vec<GovernanceProtocolEvent> { std::mem::take(&mut self.pending_events) }
}