NAC_Blockchain/nac-upgrade-framework/src/traits.rs

196 lines
5.4 KiB
Rust

//! 升级框架核心trait定义
use crate::{
error::Result, migration::UpgradeData, proposal::{ProposalId, UpgradeProposal},
snapshot::Snapshot, governance::{Vote, VoteResult}, version::Version, UpgradeRecord,
};
/// 可升级trait - 所有NAC模块必须实现此trait
pub trait Upgradeable {
/// 获取模块名称
fn module_name(&self) -> &str;
/// 获取当前版本
fn current_version(&self) -> Version;
/// 检查是否可以升级到目标版本
fn can_upgrade_to(&self, target: &Version) -> Result<bool>;
/// 执行升级
///
/// # 参数
/// - `target`: 目标版本
/// - `data`: 升级数据(包含迁移脚本、配置变更等)
///
/// # 返回
/// - `Ok(())`: 升级成功
/// - `Err(UpgradeError)`: 升级失败
fn upgrade(&mut self, target: Version, data: UpgradeData) -> Result<()>;
/// 创建状态快照
///
/// 在升级前创建快照,用于回滚
fn create_snapshot(&self) -> Result<Snapshot>;
/// 从快照回滚
///
/// # 参数
/// - `snapshot`: 要回滚到的快照
///
/// # 返回
/// - `Ok(())`: 回滚成功
/// - `Err(UpgradeError)`: 回滚失败
fn rollback(&mut self, snapshot: Snapshot) -> Result<()>;
/// 获取升级历史
fn upgrade_history(&self) -> Vec<UpgradeRecord>;
/// 验证升级后的状态
///
/// 升级后调用,验证状态是否正确
fn validate_state(&self) -> Result<bool>;
}
/// 升级治理trait - 管理升级提案和投票
pub trait UpgradeGovernance {
/// 提交升级提案
///
/// # 参数
/// - `proposal`: 升级提案
///
/// # 返回
/// - `Ok(ProposalId)`: 提案ID
/// - `Err(UpgradeError)`: 提交失败
fn propose_upgrade(&mut self, proposal: UpgradeProposal) -> Result<ProposalId>;
/// 对升级提案投票
///
/// # 参数
/// - `proposal_id`: 提案ID
/// - `vote`: 投票(赞成/反对/弃权)
///
/// # 返回
/// - `Ok(())`: 投票成功
/// - `Err(UpgradeError)`: 投票失败
fn vote(&mut self, proposal_id: ProposalId, vote: Vote) -> Result<()>;
/// 执行已批准的升级
///
/// # 参数
/// - `proposal_id`: 提案ID
///
/// # 返回
/// - `Ok(())`: 执行成功
/// - `Err(UpgradeError)`: 执行失败
fn execute_upgrade(&mut self, proposal_id: ProposalId) -> Result<()>;
/// 获取提案
fn get_proposal(&self, proposal_id: ProposalId) -> Result<UpgradeProposal>;
/// 获取投票结果
fn get_vote_result(&self, proposal_id: ProposalId) -> Result<VoteResult>;
/// 取消提案
///
/// 只有提案者可以在投票期前取消
fn cancel_proposal(&mut self, proposal_id: ProposalId) -> Result<()>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::proposal::ProposalStatus;
use std::collections::HashMap;
// 测试用的简单实现
struct TestModule {
name: String,
version: Version,
history: Vec<UpgradeRecord>,
}
impl Upgradeable for TestModule {
fn module_name(&self) -> &str {
&self.name
}
fn current_version(&self) -> Version {
self.version.clone()
}
fn can_upgrade_to(&self, target: &Version) -> Result<bool> {
Ok(self.version.can_upgrade_to(target))
}
fn upgrade(&mut self, target: Version, _data: UpgradeData) -> Result<()> {
self.version = target;
Ok(())
}
fn create_snapshot(&self) -> Result<Snapshot> {
Ok(Snapshot::new(
self.name.clone(),
self.version.clone(),
vec![],
))
}
fn rollback(&mut self, snapshot: Snapshot) -> Result<()> {
self.version = snapshot.version;
Ok(())
}
fn upgrade_history(&self) -> Vec<UpgradeRecord> {
self.history.clone()
}
fn validate_state(&self) -> Result<bool> {
Ok(true)
}
}
#[test]
fn test_upgradeable_trait() {
let mut module = TestModule {
name: "test-module".to_string(),
version: Version::new(1, 0, 0),
history: vec![],
};
assert_eq!(module.module_name(), "test-module");
assert_eq!(module.current_version(), Version::new(1, 0, 0));
let target = Version::new(1, 1, 0);
assert!(module.can_upgrade_to(&target).expect("mainnet: handle error"));
let data = UpgradeData {
migration_script: None,
config_changes: HashMap::new(),
state_migrations: vec![],
breaking_changes: vec![],
};
assert!(module.upgrade(target.clone(), data).is_ok());
assert_eq!(module.current_version(), target);
}
#[test]
fn test_snapshot_and_rollback() {
let mut module = TestModule {
name: "test-module".to_string(),
version: Version::new(1, 0, 0),
history: vec![],
};
let snapshot = module.create_snapshot().expect("mainnet: handle error");
assert_eq!(snapshot.version, Version::new(1, 0, 0));
// 升级
module.version = Version::new(1, 1, 0);
// 回滚
assert!(module.rollback(snapshot).is_ok());
assert_eq!(module.current_version(), Version::new(1, 0, 0));
}
}