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));
});
}
核心功能
-
成员管理:
- 支持添加和删除核心成员
- 提供成员资格查询接口
- 管理成员生命周期
-
治理机制:
- 完整的提案提交和投票流程
- 决策执行管理
- 包含冷却期控制逻辑
-
安全控制:
- 成员身份验证系统
- 细粒度权限管理
- 访问控制机制
完整功能示例
// 扩展测试用例展示完整功能
#[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);
});
}
}
总结
这个完整示例展示了如何:
- 在runtime中集成
pallet-core-fellowship
- 配置成员管理参数
- 实现自定义特权分配
- 构建基于成员等级的治理系统
- 编写测试用例验证功能
通过这种方式,你可以构建一个灵活且安全的区块链治理系统,其中成员权限和投票权重由他们的等级决定。