Rust核心成员库pallet-core-fellowship的使用,实现Substrate区块链治理与身份管理功能

Core Fellowship

Polkadot核心联盟的专用逻辑实现。

安装方式

在项目目录中执行以下Cargo命令:

cargo add pallet-core-fellowship

或者直接在Cargo.toml中添加依赖项:

pallet-core-fellowship = "25.0.0"

使用示例

以下是完整的演示代码,展示如何配置和使用pallet-core-fellowship实现区块链治理功能:

// 引入必要的库和模块
use frame_support::{parameter_types, traits::Everything};
use pallet_core_fellowship::{Config, Module};
use sp_core::H256;
use sp_runtime::{
    traits::{BlakeTwo256, IdentityLookup},
    BuildStorage,
};

// 定义测试区块链结构
type Block = frame_system::mocking::MockBlock<Test>;

// 构建测试运行时
frame_support::construct_runtime!(
    pub enum Test {
        System: frame_system,
        CoreFellowship: pallet_core_fellowship,
    }
);

// 系统参数配置
parameter_types! {
    pub const BlockHashCount: u64 = 250;
    pub const SS58Prefix: u8 = 42;
}

// 实现frame_system配置
impl frame_system::Config for Test {
    type BaseCallFilter = Everything;
    type BlockWeights = ();
    type BlockLength = ();
    type DbWeight = ();
    type RuntimeOrigin = RuntimeOrigin;
    type RuntimeCall = RuntimeCall;
    type Nonce = u64;
    type Hash = H256;
    type Hashing = BlakeTwo256;
    type AccountId = u64;
    type Lookup = IdentityLookup<Self::AccountId>;
    type Block = Block;
    type RuntimeEvent = RuntimeEvent;
    type BlockHashCount = BlockHashCount;
    type Version = ();
    type PalletInfo = PalletInfo;
    type AccountData = ();
    type OnNewAccount = ();
    type OnKilledAccount = ();
    type SystemWeightInfo = ();
    type SS58Prefix = SS58Prefix;
    type OnSetCode = ();
    type MaxConsumers = frame_support::traits::ConstU32<16>;
}

// 联盟专用参数
parameter_types! {
    pub const FellowshipMembershipPeriod: u64 = 5;
    pub const FellowshipVotingPeriod: u64 = 5;
    pub const FellowshipEnactmentPeriod: u64 = 5;
    pub const FellowshipCooloffPeriod: u64 = 5;
    pub const FellowshipMinimumDeposit: u64 = 1;
    pub const FellowshipMaxProposals: u32 = 100;
    pub const FellowshipMaxMembers: u32 = 100;
}

// 实现联盟模块配置
impl Config for Test {
    type RuntimeEvent = RuntimeEvent;
    type MembershipPeriod = FellowshipMembershipPeriod;
    type VotingPeriod = FellowshipVotingPeriod;
    type EnactmentPeriod = FellowshipEnactmentPeriod;
    type CooloffPeriod = FellowshipCooloffPeriod;
    type MinimumDeposit = FellowshipMinimumDeposit;
    type MaxProposals = FellowshipMaxProposals;
    type MaxMembers = FellowshipMaxMembers;
    type WeightInfo = ();
}

// 单元测试
#[test]
fn test_fellowship_operations() {
    let mut ext = sp_io::TestExternalities::new(
        frame_system::GenesisConfig::<Test>::default()
            .build_storage()
            .unwrap(),
    );
    
    ext.execute_with(|| {
        // 准备测试环境
        System::set_block_number(1);
        
        // 验证初始状态
        assert_eq!(CoreFellowship::member_count(), 0);
        
        // 测试添加成员功能
        CoreFellowship::add_member(RuntimeOrigin::root(), 1).unwrap();
        assert_eq!(CoreFellowship::member_count(), 1);
        assert!(CoreFellowship::is_member(&1));
        
        // 测试提案功能
        let proposal = RuntimeCall::System(frame_system::Call::remark { remark: vec![1, 2, 3] });
        let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32);
        let proposal_hash = BlakeTwo256::hash_of(&proposal);
        
        CoreFellowship::propose(
            RuntimeOrigin::signed(1),
            Box::new(proposal),
            proposal_len,
        ).unwrap();
        
        // 测试投票功能
        CoreFellowship::vote(
            RuntimeOrigin::signed(1),
            proposal_hash,
            0,
            true
        ).unwrap();
        
        // 测试成员移除功能
        CoreFellowship::remove_member(RuntimeOrigin::root(), 1).unwrap();
        assert_eq!(CoreFellowship::member_count(), 0);
        assert!(!CoreFellowship::is_member(&1));
    });
}

核心功能

  1. 成员管理

    • 支持添加和删除核心成员
    • 提供成员资格查询接口
    • 管理成员生命周期
  2. 治理机制

    • 完整的提案提交和投票流程
    • 决策执行管理
    • 包含冷却期控制逻辑
  3. 安全控制

    • 成员身份验证系统
    • 细粒度权限管理
    • 访问控制机制

完整功能示例

// 扩展测试用例展示完整功能
#[test]
fn test_full_fellowship_workflow() {
    let mut ext = sp_io::TestExternalities::new(
        frame_system::GenesisConfig::<Test>::default()
            .build_storage()
            .unwrap(),
    );
    
    ext.execute_with(|| {
        // 初始化区块链环境
        System::set_block_number(1);
        
        // 1. 成员管理测试
        // 添加三个成员
        CoreFellowship::add_member(RuntimeOrigin::root(), 1).unwrap();
        CoreFellowship::add_member(RuntimeOrigin::root(), 2).unwrap();
        CoreFellowship::add_member(RuntimeOrigin::root(), 3).unwrap();
        
        // 验证成员数量
        assert_eq!(CoreFellowship::member_count(), 3);
        
        // 2. 提案治理测试
        // 创建两个提案
        let proposal1 = RuntimeCall::System(frame_system::Call::remark { remark: b"Proposal1".to_vec() });
        let proposal1_len = proposal1.using_encoded(|p| p.len() as u32);
        let proposal1_hash = BlakeTwo256::hash_of(&proposal1);
        
        let proposal2 = RuntimeCall::System(frame_system::Call::remark { remark: b"Proposal2".to_vec() });
        let proposal2_len = proposal2.using_encoded(|p| p.len() as u32);
        let proposal2_hash = BlakeTwo256::hash_of(&proposal2);
        
        // 成员1提交提案1
        CoreFellowship::propose(
            RuntimeOrigin::signed(1),
            Box::new(proposal1),
            proposal1_len,
        ).unwrap();
        
        // 成员2提交提案2
        CoreFellowship::propose(
            RuntimeOrigin::signed(2),
            Box::new(proposal2),
            proposal2_len,
        ).unwrap();
        
        // 3. 投票测试
        // 成员1和2对提案1投票
        CoreFellowship::vote(RuntimeOrigin::signed(1), proposal1_hash, 0, true).unwrap();
        CoreFellowship::vote(RuntimeOrigin::signed(2), proposal1_hash, 0, true).unwrap();
        
        // 成员3对提案2投票
        CoreFellowship::vote(RuntimeOrigin::signed(3), proposal2_hash, 1, true).unwrap();
        
        // 4. 执行阶段测试
        // 推进区块到执行期
        System::set_block_number(FellowshipVotingPeriod::get() + FellowshipEnactmentPeriod::get());
        
        // 执行通过的提案
        CoreFellowship::enact_proposals(
            RuntimeOrigin::root(),
            vec![proposal1_hash, proposal2_hash]
        ).unwrap();
        
        // 5. 冷却期测试
        // 尝试在冷却期内重复提交相同提案
        assert!(CoreFellowship::propose(
            RuntimeOrigin::signed(1),
            Box::new(proposal1),
            proposal1_len,
        ).is_err());
        
        // 6. 成员移除测试
        CoreFellowship::remove_member(RuntimeOrigin::root(), 1).unwrap();
        assert_eq!(CoreFellowship::member_count(), 2);
    });
}

1 回复

Rust核心成员库pallet-core-fellowship的使用:实现Substrate区块链治理与身份管理功能

完整示例demo

下面是一个完整的runtime集成示例,展示了如何使用pallet-core-fellowship实现完整的治理系统:

// runtime/src/lib.rs

// 1. 引入必要的依赖和模块
pub use pallet_core_fellowship as fellowship;
pub use pallet_ranked_collective as collective;

// 2. 配置runtime实现
impl fellowship::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type Members = collective::Instance1;  // 使用ranked collective实例
    type Balance = Balance;  // 使用runtime定义的Balance类型
    type ParamsOrigin = EnsureRoot<AccountId>;  // 只有root可以修改参数
    type InductOrigin = EnsureRoot<AccountId>;  // 只有root可以初始化成员
    type ApproveOrigin = EnsureRoot<AccountId>;  // 只有root可以批准成员
    type PromoteOrigin = EnsureRoot<AccountId>;  // 只有root可以提升成员等级
    type EvidenceSize = ConstU32<65536>;  // 证据大小限制
    type MaxRank = ConstU32<9>;  // 最大等级设为9级
    
    // 自定义特权分配
    fn get_privileges(rank: u16) -> Vec<Privilege> {
        match rank {
            1 => vec![Privilege::Vote],  // 1级成员只有投票权
            3 => vec![Privilege::Vote, Privilege::Propose],  // 3级成员可以提案
            5 => vec![Privilege::Vote, Privilege::Propose, Privilege::Veto],  // 5级成员有否决权
            _ => vec![],  // 其他等级无特权
        }
    }
}

// 3. 在construct_runtime!宏中添加pallet
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic,
    {
        // 系统基础pallet
        System: frame_system,
        Timestamp: pallet_timestamp,
        
        // 治理相关pallet
        Collective: pallet_ranked_collective::<Instance1>,
        CoreFellowship: pallet_core_fellowship,
        
        // 其他pallet...
    }
);

// 4. 实现自定义成员管理逻辑
pub mod fellowship_extension {
    use super::*;
    use frame_support::{dispatch::DispatchResult, traits::Get};
    
    // 检查成员是否有特定特权
    pub fn has_privilege(who: &AccountId, privilege: Privilege) -> bool {
        if let Some(info) = CoreFellowship::member(who) {
            fellowship::Pallet::<Runtime>::get_privileges(info.rank)
                .contains(&privilege)
        } else {
            false
        }
    }
    
    // 带证据的成员申请
    pub fn apply_with_evidence(
        origin: OriginFor<Runtime>,
        evidence: Vec<u8>,
    ) -> DispatchResult {
        let who = ensure_signed(origin)?;
        
        // 验证证据大小
        ensure!(
            evidence.len() <= T::EvidenceSize::get() as usize,
            Error::<Runtime>::EvidenceTooLarge
        );
        
        // 存储申请证据
        PendingApplications::<Runtime>::insert(&who, evidence);
        
        // 触发申请事件
        Self::deposit_event(Event::Applied { who });
        
        Ok(())
    }
    
    // 自动晋升符合条件的成员
    pub fn auto_promote(origin: OriginFor<Runtime>) -> DispatchResult {
        // 只有root可以调用
        ensure_root(origin)?;
        
        // 遍历所有成员
        for (who, info) in Members::<Runtime>::iter() {
            // 检查是否符合晋升条件
            if meets_promotion_criteria(&who, &info) {
                CoreFellowship::promote(RawOrigin::Root.into(), who)?;
            }
        }
        
        Ok(())
    }
    
    // 晋升条件检查
    fn meets_promotion_criteria(who: &AccountId, info: &MemberInfo<Balance, BlockNumber>) -> bool {
        // 实现自定义晋升逻辑
        // 例如:检查活跃度、贡献度等
        true
    }
}

完整治理系统实现

下面是一个完整的治理投票系统实现示例:

// governance/src/lib.rs

use frame_support::{
    dispatch::DispatchResult,
    ensure,
    traits::{Currency, Get},
};
use frame_system::pallet_prelude::*;
use sp_std::prelude::*;

// 治理提案结构
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct Proposal<AccountId, Hash, BlockNumber> {
    proposer: AccountId,
    hash: Hash,
    created: BlockNumber,
    votes: Vec<(AccountId, u64)>,  // (投票者, 投票权重)
    status: ProposalStatus,
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub enum ProposalStatus {
    Active,
    Approved,
    Rejected,
}

// 治理模块实现
impl<T: Config> Pallet<T> {
    // 创建新提案
    pub fn propose(
        origin: OriginFor<T>,
        proposal_hash: T::Hash,
    ) -> DispatchResult {
        let who = ensure_signed(origin)?;
        
        // 检查提案者是否是核心成员且有提案权
        ensure!(
            fellowship_extension::has_privilege(&who, Privilege::Propose),
            Error::<T>::NoProposalRight
        );
        
        // 创建新提案
        let proposal = Proposal {
            proposer: who.clone(),
            hash: proposal_hash,
            created: frame_system::Pallet::<T>::block_number(),
            votes: vec![],
            status: ProposalStatus::Active,
        };
        
        // 存储提案
        Proposals::<T>::insert(&proposal_hash, proposal);
        
        Ok(())
    }
    
    // 提交投票
    pub fn vote(
        origin: OriginFor<T>,
        proposal_hash: T::Hash,
        approve: bool,
    ) -> DispatchResult {
        let who = ensure_signed(origin)?;
        
        // 检查投票者是否是核心成员
        ensure!(
            CoreFellowship::is_member(&who),
            Error::<T>::NotMember
        );
        
        // 获取成员信息和投票权重
        let member_info = CoreFellowship::member(&who)
            .ok_or(Error::<T>::NotMember)?;
        let vote_weight = member_info.rank as u64;
        
        // 更新提案投票状态
        Proposals::<T>::mutate(proposal_hash, |maybe_proposal| {
            if let Some(proposal) = maybe_proposal {
                // 记录投票
                proposal.votes.push((who.clone(), vote_weight));
                
                // 检查投票结果
                let total_weight: u64 = proposal.votes.iter()
                    .map(|(_, weight)| weight)
                    .sum();
                
                let approval_weight: u64 = proposal.votes.iter()
                    .filter(|(_, approve)| *approve)
                    .map(|(_, weight)| weight)
                    .sum();
                
                // 更新提案状态
                if approval_weight * 2 > total_weight {
                    proposal.status = ProposalStatus::Approved;
                } else if (total_weight - approval_weight) * 2 > total_weight {
                    proposal.status = ProposalStatus::Rejected;
                }
            }
        });
        
        Ok(())
    }
    
    // 执行已批准的提案
    pub fn execute_proposal(
        origin: OriginFor<T>,
        proposal_hash: T::Hash,
    ) -> DispatchResult {
        // 检查提案状态
        if let Some(proposal) = Proposals::<T>::get(proposal_hash) {
            ensure!(
                proposal.status == ProposalStatus::Approved,
                Error::<T>::ProposalNotApproved
            );
            
            // 执行提案逻辑
            // ...
            
            // 移除已执行的提案
            Proposals::<T>::remove(proposal_hash);
        }
        
        Ok(())
    }
}

测试用例

#[cfg(test)]
mod tests {
    use super::*;
    use frame_support::{
        assert_ok, assert_err,
        traits::{OnInitialize, Currency}
    };
    use sp_core::H256;
    use crate::mock::{new_test_ext, Test, Origin};
    
    #[test]
    fn test_member_management() {
        new_test_ext().execute_with(|| {
            // 初始化测试账户
            let root = Origin::root();
            let alice = 1u64;
            let bob = 2u64;
            
            // 初始化成员
            assert_ok!(CoreFellowship::induct(root.clone(), alice, 1));
            assert_ok!(CoreFellowship::induct(root.clone(), bob, 1));
            
            // 检查成员状态
            assert!(CoreFellowship::is_member(&alice));
            assert_eq!(CoreFellowship::member(&alice).unwrap().rank, 1);
            
            // 提升成员等级
            assert_ok!(CoreFellowship::promote(root.clone(), alice));
            assert_eq!(CoreFellowship::member(&alice).unwrap().rank, 2);
            
            // 测试特权
            assert!(fellowship_extension::has_privilege(&alice, Privilege::Vote));
            assert!(!fellowship_extension::has_privilege(&alice, Privilege::Propose));
        });
    }
    
    #[test]
    fn test_governance() {
        new_test_ext().execute_with(|| {
            // 初始化测试账户
            let root = Origin::root();
            let alice = 1u64;
            let bob = 2u64;
            let proposal_hash = H256::random();
            
            // 初始化高级成员
            assert_ok!(CoreFellowship::induct(root.clone(), alice, 3));
            assert_ok!(CoreFellowship::induct(root.clone(), bob, 1));
            
            // 创建提案
            assert_ok!(Governance::propose(Origin::signed(alice), proposal_hash));
            
            // 投票
            assert_ok!(Governance::vote(Origin::signed(alice), proposal_hash, true));
            assert_ok!(Governance::vote(Origin::signed(bob), proposal_hash, false));
            
            // 检查提案状态
            let proposal = Governance::proposals(proposal_hash).unwrap();
            assert_eq!(proposal.votes.len(), 2);
            assert_eq!(proposal.status, ProposalStatus::Active);
        });
    }
}

总结

这个完整示例展示了如何:

  1. 在runtime中集成pallet-core-fellowship
  2. 配置成员管理参数
  3. 实现自定义特权分配
  4. 构建基于成员等级的治理系统
  5. 编写测试用例验证功能

通过这种方式,你可以构建一个灵活且安全的区块链治理系统,其中成员权限和投票权重由他们的等级决定。

回到顶部