Rust联盟插件库pallet-alliance的使用:构建去中心化治理与协作的Substrate区块链模块

Rust联盟插件库pallet-alliance的使用:构建去中心化治理与协作的Substrate区块链模块

Alliance Pallet概述

Alliance Pallet提供了一个集体治理机制,维护由投票成员认定的不道德行为者的账户和URL列表,主要功能包括:

  • 提供针对不良行为的道德准则
  • 为生态系统贡献者提供认可和影响力

核心功能

联盟通过Root调用初始化后,具备以下特性:

  1. 任何拥有已批准身份和网站的账户可作为Ally加入
  2. MembershipManager origin可将Ally提升为Fellow(拥有投票权)
  3. 投票成员维护账户和网站列表
  4. 成员可投票更新规则并发布公告

完整示例代码

以下是基于Substrate的pallet-alliance完整实现示例,包含详细注释:

//! 联盟模块实现
use frame_support::{
    decl_module, decl_storage, decl_event, decl_error, 
    dispatch, traits::Get, ensure
};
use frame_system::{ensure_root, ensure_signed};
use sp_std::prelude::*;
use frame_support::traits::EnsureOrigin;

/// 联盟模块配置Trait
pub trait Trait: frame_system::Trait {
    /// 事件类型
    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
    
    /// 成员管理权限
    type MembershipManager: EnsureOrigin<Self::Origin>;
    
    /// 退休通知期(区块数)
    type RetirementPeriod: Get<Self::BlockNumber>;
    
    /// Ally加入押金
    type AllyDeposit: Get<Self::Balance>;
}

// 存储项定义
decl_storage! {
    trait Store for Module<T: Trait> as Alliance {
        /// 成员状态存储
        pub Members get(fn members):
            map hasher(blake2_128_concat) T::AccountId => MemberStatus;
            
        /// 联盟规则(IPFS CID)
        pub Rule get(fn rule): Option<Vec<u8>>;
        
        /// 公告列表(IPFS CID)
        pub Announcements get(fn announcements): Vec<Vec<u8>>;
        
        /// 不道德项目列表
        pub UnscrupulousList get(fn unscrupulous_list): Vec<UnscrupulousItem>;
        
        /// 退休通知
        pub RetirementNotice get(fn retirement_notice):
            map hasher(blake2_128_concat) T::AccountId => T::BlockNumber;
            
        /// 动议列表
        pub Motions get(fn motions): Vec<Motion<T::AccountId, T::BlockNumber>>;
    }
}

// 事件定义
decl_event!(
    pub enum Event<T> where AccountId = <T as frame_system::Trait>::AccountId {
        /// 新成员加入(Ally)
        NewAlly(AccountId),
        /// Ally晋升为Fellow
        AllyElevated(AccountId),
        /// 成员退休
        MemberRetired(AccountId),
        /// 规则更新
        RuleUpdated(Vec<u8>),
        /// 新公告
        AnnouncementAdded(Vec<u8>),
        /// 不道德项目添加
        UnscrupulousItemAdded(UnscrupulousItem),
        /// 不道德项目移除
        UnscrupulousItemRemoved(UnscrupulousItem),
    }
);

// 错误类型
decl_error! {
    pub enum Error for Module<T: Trait> {
        /// 账户已是成员
        AlreadyMember,
        /// 账户不是成员
        NotMember,
        /// 账户不是Fellow
        NotFellow,
        /// 退休通知期未到
        RetirementNoticeNotGiven,
        /// 退休期未结束
        RetirementPeriodNotPassed,
    }
}

// 模块实现
decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        type Error = Error<T>;

        fn deposit_event() = default;

        /// 初始化联盟成员(Root权限)
        #[weight = 10_000]
        pub fn init_members(
            origin,
            fellows: Vec<T::AccountId>,
            allies: Vec<T::AccountId>
        ) -> dispatch::DispatchResult {
            ensure_root(origin)?;
            
            // 初始化Fellow成员
            for fellow in fellows {
                ensure!(!<Members<T>>::contains_key(&fellow), Error::<T>::AlreadyMember);
                <Members<T>>::insert(&fellow, MemberStatus::Fellow);
                Self::deposit_event(RawEvent::NewAlly(fellow));
            }
            
            // 初始化Ally成员
            for ally in allies {
                ensure!(!<Members<T>>::contains_key(&ally), Error::<T>::AlreadyMember);
                <Members<T>>::insert(&ally, MemberStatus::Ally);
                Self::deposit_event(RawEvent::NewAlly(ally));
            }
            
            Ok(())
        }
        
        /// 加入联盟(成为Ally)
        #[weight = 10_000]
        pub fn join_alliance(origin) -> dispatch::DispatchResult {
            let who = ensure_signed(origin)?;
            ensure!(!<Members<T>>::contains_key(&who), Error::<T>::AlreadyMember);
            
            // 设置初始状态为Ally
            <Members<T>>::insert(&who, MemberStatus::Ally);
            Self::deposit_event(RawEvent::NewAlly(who));
            
            Ok(())
        }
        
        /// 提升Ally为Fellow(需MembershipManager权限)
        #[weight = 10_000]
        pub fn elevate_ally(
            origin,
            ally: T::AccountId
        ) -> dispatch::DispatchResult {
            T::MembershipManager::ensure_origin(origin)?;
            
            ensure!(
                <Members<T>>::get(&ally) == Some(MemberStatus::Ally),
                Error::<T>::NotMember
            );
            
            <Members<T>>::insert(&ally, MemberStatus::Fellow);
            Self::deposit_event(RawEvent::AllyElevated(ally));
            
            Ok(())
        }
        
        /// 设置联盟规则(仅Fellow可调用)
        #[weight = 10_000]
        pub fn set_rule(
            origin,
            rule: Vec<u8>
        ) -> dispatch::DispatchResult {
            let who = ensure_signed(origin)?;
            ensure!(
                <Members<T>>::get(&who) == Some(MemberStatus::Fellow),
                Error::<T>::NotFellow
            );
            
            <Rule>::put(rule.clone());
            Self::deposit_event(RawEvent::RuleUpdated(rule));
            
            Ok(())
        }
        
        /// 添加不道德项目(仅Fellow可调用)
        #[weight = 10_000]
        pub fn add_unscrupulous_items(
            origin,
            items: Vec<UnscrupulousItem>
        ) -> dispatch::DispatchResult {
            let who = ensure_signed(origin)?;
            ensure!(
                <Members<T>>::get(&who) == Some(MemberStatus::Fellow),
                Error::<T>::NotFellow
            );
            
            for item in items {
                <UnscrupulousList>::mutate(|list| {
                    if !list.contains(&item) {
                        list.push(item.clone());
                        Self::deposit_event(RawEvent::UnscrupulousItemAdded(item));
                    }
                });
            }
            
            Ok(())
        }
    }
}

/// 成员状态枚举
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
pub enum MemberStatus {
    /// 投票成员
    Fellow,
    /// 普通成员
    Ally,
}

/// 不道德项目类型
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
pub enum UnscrupulousItem {
    /// 不良账户
    AccountId(Vec<u8>),
    /// 不良网站
    Website(Vec<u8>),
}

/// 动议结构
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
pub struct Motion<AccountId, BlockNumber> {
    /// 提案人
    proposer: AccountId,
    /// 提案区块
    created: BlockNumber,
    /// 赞成票
    ayes: Vec<AccountId>,
    /// 反对票
    nays: Vec<AccountId>,
}

功能说明

  1. 成员管理

    • 通过init_members初始化创始成员
    • join_alliance允许新成员加入
    • elevate_ally提升成员权限等级
  2. 治理功能

    • set_rule更新联盟规则
    • add_unscrupulous_items管理不良行为列表
  3. 权限控制

    • Root权限执行初始化
    • Fellow成员拥有治理权限
    • MembershipManager控制成员晋升

集成说明

要使用此pallet,需要在runtime中配置:

impl alliance::Trait for Runtime {
    type Event = Event;
    type MembershipManager = EnsureRootOrHalfCouncil;
    type RetirementPeriod = RetirementPeriod;
    type AllyDeposit = AllyDeposit;
}

该实现提供了完整的联盟治理功能,包括成员管理、规则制定和不良行为监管,可作为Substrate区块链去中心化治理的基础模块。


1 回复

以下是基于您提供的内容整理的关于pallet-alliance的完整示例demo:

内容中提供的核心示例

  1. 提交提案示例
// 创建一个调用示例
let proposal = Box::new(Call::System(frame_system::Call::remark { remark: b"Hello Alliance".to_vec() }));

// 提交提案
Alliance::propose(
    RuntimeOrigin::signed(member_account),
    threshold,  // 通过所需的票数
    proposal,
    proposal_len,
);
  1. 投票表决示例
// 成员对提案进行投票
Alliance::vote(
    RuntimeOrigin::signed(member_account),
    proposal_hash,
    proposal_index,
    true,  // 赞成或反对
);
  1. 添加新成员示例
// 现有成员提议添加新成员
Alliance::add_member(
    RuntimeOrigin::signed(existing_member_account),
    new_member_account,
);

完整示例demo

// 1. 引入必要依赖和模块
use frame_support::{decl_module, decl_event, dispatch::DispatchResult};
use frame_system::{self as system, ensure_signed};
use sp_runtime::traits::{AccountIdConversion, Hash};
use sp_std::prelude::*;

// 2. 定义联盟模块
pub trait Config: system::Config {
    type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;
}

decl_event!(
    pub enum Event<T> where AccountId = <T as system::Config>::AccountId {
        /// 新成员加入事件
        MemberAdded(AccountId),
        /// 提案提交事件
        ProposalSubmitted(Hash, AccountId),
    }
);

decl_module! {
    pub struct Module<T: Config> for enum Call where origin: T::Origin {
        fn deposit_event() = default;

        /// 添加新成员
        #[weight = 10_000]
        pub fn add_member(origin, new_member: T::AccountId) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            
            // 验证发送者权限
            Self::ensure_member(&sender)?;
            
            // 添加新成员逻辑
            Members::<T>::insert(&new_member, ());
            
            // 触发事件
            Self::deposit_event(RawEvent::MemberAdded(new_member));
            Ok(())
        }

        /// 提交提案
        #[weight = 10_000]
        pub fn propose(
            origin,
            proposal: Box<<T as Config>::Proposal>,
            proposal_len: u32,
        ) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            
            // 验证发送者权限
            Self::ensure_member(&sender)?;
            
            // 生成提案哈希
            let proposal_hash = T::Hashing::hash_of(&proposal);
            
            // 存储提案
            Proposals::<T>::insert(&proposal_hash, (sender.clone(), proposal));
            
            // 触发事件
            Self::deposit_event(RawEvent::ProposalSubmitted(proposal_hash, sender));
            Ok(())
        }

        /// 对提案投票
        #[weight = 10_000]
        pub fn vote(
            origin,
            proposal_hash: T::Hash,
            index: ProposalIndex,
            approve: bool,
        ) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            
            // 验证发送者权限
            Self::ensure_member(&sender)?;
            
            // 投票逻辑
            Votes::<T>::insert((proposal_hash, sender), (index, approve));
            Ok(())
        }
    }
}

// 3. 自定义投票权重实现
struct CustomVoteWeight;
impl VoteWeighting for CustomVoteWeight {
    fn vote_weight(who: &AccountId) -> VoteWeight {
        // 基于账户余额计算投票权重
        Balances::free_balance(who)
    }
}

// 4. 在runtime中配置
impl pallet_alliance::Config for Runtime {
    type Event = Event;
    type Proposal = Call;
    type Currency = Balances;
    type MembershipChanged = AllianceMembershipChanged;
    type ProposalLifetime = ProposalLifetime;
    type VoteWeighting = CustomVoteWeight;
}

// 5. 链初始配置示例
pub fn testnet_genesis() -> GenesisConfig {
    GenesisConfig {
        alliance: AllianceConfig {
            members: vec![
                // 初始成员列表
                get_account_id_from_seed::<sr25519::Public>("Alice"),
                get_account_id_from_seed::<sr25519::Public>("Bob"),
            ],
            phantom: Default::default(),
        },
        // 其他pallet配置...
    }
}

示例说明

  1. 成员管理:通过add_member函数实现成员添加,触发MemberAdded事件
  2. 提案系统propose函数处理提案提交,存储提案并触发ProposalSubmitted事件
  3. 投票机制vote函数实现投票功能,使用自定义的CustomVoteWeight计算投票权重
  4. runtime配置:展示了如何在runtime中配置pallet-alliance
  5. 链初始化:提供了测试网初始成员配置示例

使用建议

  1. 在实际部署前,应充分测试所有治理流程
  2. 根据业务需求调整投票权重算法
  3. 合理设置提案生命周期参数
  4. 建议实现成员退出和惩罚机制作为补充
回到顶部