196 lines
5.4 KiB
Rust
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));
|
|
}
|
|
}
|