美文网首页
Substrate中democracy模块分析

Substrate中democracy模块分析

作者: 建怀 | 来源:发表于2019-11-29 14:59 被阅读0次

    Substrate中democracy模块分析

    民主模块,用来处理常规抵押投票的决议实施。

    Conviction

    pub enum Conviction {
        /// 不对币上锁,只等额0.1倍
        None,
        /// 对币锁一个实施周期(默认30天),等额1倍
        Locked1x,
        /// 对币锁两个实施周期(默认60天),等额2倍
        Locked2x,
        /// 对币锁四个实施周期(默认120天),等额3倍
        Locked3x,
        /// 对币锁八个实施周期(默认240天),等额4倍
        Locked4x,
        /// 对币锁十六个实施周期(默认480天),等额5倍
        Locked5x,
        /// 对币锁三十二个实施周期(默认960天),等额6倍
        Locked6x,
    }
    

    Trait

    type Proposal: Parameter + Dispatchable<Origin=Self::Origin>;
    type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
    
    /// Currency type for this module.
    type Currency: ReservableCurrency<Self::AccountId>
        + LockableCurrency<Self::AccountId, Moment=Self::BlockNumber>;
    
    /// 投票如果要锁定,最少的锁定周期,是一个提案被通过后到被执行中间的周期,默认30天
    type EnactmentPeriod: Get<Self::BlockNumber>;
    
    /// 一个公共投票发起的周期,默认28天
    type LaunchPeriod: Get<Self::BlockNumber>;
    
    /// 对一个提案投票统计的周期,默认28天
    type VotingPeriod: Get<Self::BlockNumber>;
    
    /// 发起一个公共投票的最低存款,需要100个Token
    type MinimumDeposit: Get<BalanceOf<Self>>;
    
    /// 直接大多数议会成员(大于1/2)同意能决定其下一个动议,下一个将摆上桌面的全民公投
    type ExternalOrigin: EnsureOrigin<Self::Origin>;
    
    /// 一个绝大多数议会成员(大于3/4)同意能直接调度一个全民公投
    type ExternalMajorityOrigin: EnsureOrigin<Self::Origin>;
    
    /// 一致通过的议会能调度一个全民公投,赞成>反对 即可通过
    type ExternalDefaultOrigin: EnsureOrigin<Self::Origin>;
    
    /// 2/3的技术委员会成员同意能发起一个 ExternalMajority/ExternalDefault投票,且能够立即摆上桌面进行公投,而且有一个更短的投票/实施周期
    type FastTrackOrigin: EnsureOrigin<Self::Origin>;
    
    /// 在快速通道和紧急全民公投情况下,最小投票周期
    type EmergencyVotingPeriod: Get<Self::BlockNumber>;
    
    /// 在紧急情况下,任何全民公投都能够被取消,条件是2/3的议会成员同意
    type CancellationOrigin: EnsureOrigin<Self::Origin>;
    
    /// 任何技术委员会成员能够否决一个将要来临的议会提案,但是他们只能使用一次,在每个冷却周期过后
    type VetoOrigin: EnsureOrigin<Self::Origin, Success=Self::AccountId>;
    
    /// 技术委员会成员的否决权使用一次后,需要的冷却时间
    type CooloffPeriod: Get<Self::BlockNumber>;
    

    ReferedumInfo

    /// 正在进行的全民公投相关信息
    #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
    pub struct ReferendumInfo<BlockNumber: Parameter, Proposal: Parameter> {
        /// 结束时间
        end: BlockNumber,
        /// 投票的提案
        proposal: Proposal,
        /// 全民公投通过的投票比例 
        threshold: VoteThreshold,
        /// 一个通过的全民公投执行需要等待的时间
        delay: BlockNumber,
    }
    

    Store

    /// 公共提案数量
    pub PublicPropCount get(fn public_prop_count) build(|_| 0 as PropIndex) : PropIndex;
    /// 公共提案,未排序
    pub PublicProps get(fn public_props): Vec<(PropIndex, T::Proposal, T::AccountId)>;
    /// 公共提案锁仓的余额和所有账号
    pub DepositOf get(fn deposit_of): map PropIndex => Option<(BalanceOf<T>, Vec<T::AccountId>)>;
    
    /// 全民公投的总数
    pub ReferendumCount get(fn referendum_count) build(|_| 0 as ReferendumIndex): ReferendumIndex;
    /// 下一个将被统计到的全民公投索引
    pub NextTally get(fn next_tally) build(|_| 0 as ReferendumIndex): ReferendumIndex;
    /// 全民公投的信息
    pub ReferendumInfoOf get(fn referendum_info):
        map ReferendumIndex => Option<(ReferendumInfo<T::BlockNumber, T::Proposal>)>;
    /// 将被调遣的全民公投的队列
    pub DispatchQueue get(fn dispatch_queue):
        map T::BlockNumber => Vec<Option<(T::Proposal, ReferendumIndex)>>;
    
    /// 现在提案的所有投票账号
    pub VotersFor get(fn voters_for): map ReferendumIndex => Vec<T::AccountId>;
    
    /// 指定全民公投索引和账号,mapping的value是vote
    pub VoteOf get(fn vote_of): map (ReferendumIndex, T::AccountId) => Vote;
    
    /// 代理投票,value是资金持有账号,key是投票账号
    pub Proxy get(fn proxy): map T::AccountId => Option<T::AccountId>;
    
    /// 获取另一个正在委托投票的帐户(和锁定期)
    pub Delegations get(fn delegations): linked_map T::AccountId => (T::AccountId, Conviction);
    
    /// 如果上次提交的公投是外部提交的,那返回True。如果是公开提案,就返回False
    pub LastTabledWasExternal: bool;
    
    /// 公民投票将在任何可能提出外部建议的情况下进行。这种情况发生在需要举行公投,并且满足以下两个条件之一时:
    /// - `LastTabledWasExternal` is `false`; or
    /// - `PublicProps` is empty.
    pub NextExternal: Option<(T::Proposal, VoteThreshold)>;
    
    /// 投票的记录,Maps,value是Proposal的Hash,value是区块高度和该提案所有的投票
    pub Blacklist get(fn blacklist): map T::Hash => Option<(T::BlockNumber, Vec<T::AccountId>)>;
    
    /// 所有被紧急取消的提案
    pub Cancellations: map T::Hash => bool;
    

    Event

    Proposed(PropIndex, Balance),       // 提案发起 
    Tabled(PropIndex, Balance, Vec<AccountId>), // 提案被摆上桌面
    ExternalTabled,                         // 外部提交提案上桌面
    Started(ReferendumIndex, VoteThreshold), // 全民公投开始
    Passed(ReferendumIndex),                // 全民公投通过
    NotPassed(ReferendumIndex),         // 全民公投没通过
    Cancelled(ReferendumIndex),         // 全民公投取消
    Executed(ReferendumIndex, bool),        // 全民公投被执行
    Delegated(AccountId, AccountId),        // 某账号被代理了
    Undelegated(AccountId),                 // 某账号取消代理
    Vetoed(AccountId, Hash, BlockNumber), // 某个账号某个公投被投票
    

    Module

    • fn propose(origin,proposal: Box<T::Proposal>,#[compact] value: BalanceOf<T>)
      • 发起一个提案,提案人需要保留一定资金,这部分资金涉及惩罚?如何不再保留?
        • <PublicProps<T>>::append_or_put(&[Ref::from(&new_prop)][..]);
          • append_or_put()方法,插入数据到Vec
    • fn second(origin, #[compact] proposal: PropIndex)
      • 对某个提案复议,同样增加自己的保留
    • fn vote(origin,#[compact] ref_index: ReferendumIndex,vote: Vote)
      • 对全民公投进行投票
    • fn proxy_vote(origin,#[compact] ref_index: ReferendumIndex,vote: Vote)
      • 代理人投票
    • fn emergency_cancel(origin, ref_index: ReferendumIndex)
      • 紧急取消全民公投
    • fn external_propose(origin, proposal: Box<T::Proposal>)
      • 将一个提案摆上桌面进入全民公投阶段,提案需要过了blacklisting的时间
    • fn external_propose_majority(origin, proposal: Box<T::Proposal>)
      • 将一个提案摆上桌面,进入全民公投阶段,需要大多数同意才能通过,不受blacklisting影响
    • fn external_propose_default(origin, proposal: Box<T::Proposal>)
      • 将一个提案摆上桌面,进入全民公投阶段,反对通过需要绝大多数,不受blacklisting影响
    • fn fast_track(origin,proposal_hash: T::Hash,voting_period: T::BlockNumber,delay: T::BlockNumber)
      • 快速通道将一个提案直接全民公投
    • fn veto_external(origin, proposal_hash: T::Hash)
      • 反对和黑名单某个外部提案
    • fn cancel_referendum(origin, #[compact] ref_index: ReferendumIndex)
      • Root取消某个公投
    • fn cancel_queued(origin,#[compact] when: T::BlockNumber,#[compact] which: u32,#[compact] what: ReferendumIndex)
      • Root取消某个在队列中的将要执行到提案
    • fn on_initialize(n: T::BlockNumber)
      • Self::end_block(n)
    • fn set_proxy(origin, proxy: T::AccountId)
      • 指定某个代理,stash账号调用
    • fn resign_proxy(origin)
      • 清除代理,代理账号调用
    • fn remove_proxy(origin, proxy: T::AccountId)
      • 移除代理,stash账号调用
    • pub fn delegate(origin, to: T::AccountId, conviction: Conviction)
      • 指定代理,并且最大幅度锁定资产
    • fn undelegate(origin)
      • 取消代理,资产锁定时间确定为EnactmentPeriod + conviction.lock_periods()
    • pub fn locked_for(proposal: PropIndex) -> Option<BalanceOf<T>>
      • 锁定资产投票给某个提案
    • pub fn is_active_referendum(ref_index: ReferendumIndex) -> bool
      • 判断某个公投是否正在进行中
    • pub fn active_referenda() -> Vec<(ReferendumIndex, ReferendumInfo<T::BlockNumber, T::Proposal>)>
      • 现在活跃的所有普通投票
    • pub fn maturing_referenda_at(n: T::BlockNumber) -> Vec<(ReferendumIndex, ReferendumInfo<T::BlockNumber, T::Proposal>)>
      • 在某个区块高度,准备进行计票统计的公投
    • pub fn tally(ref_index: ReferendumIndex) -> (BalanceOf<T>, BalanceOf<T>, BalanceOf<T>)
      • 公投计票统计
    • fn tally_delegation(ref_index: ReferendumIndex) -> (BalanceOf<T>, BalanceOf<T>, BalanceOf<T>)
      • 代理投票计票统计
    • fn delegated_votes(ref_index: ReferendumIndex,to: T::AccountId,parent_conviction: Conviction,recursion_limit: u32,) -> (BalanceOf<T>, BalanceOf<T>)
      • 代理投票计票统计
    • pub fn force_proxy(stash: T::AccountId, proxy: T::AccountId)
      • 代理人设置
    • pub fn internal_start_referendum(proposal: T::Proposal,threshold: VoteThreshold,delay: T::BlockNumber) -> result::Result<ReferendumIndex, &'static str>
      • 开启一个公投
    • pub fn internal_cancel_referendum(ref_index: ReferendumIndex)
      • 取消一个公投
    • fn do_vote(who: T::AccountId, ref_index: ReferendumIndex, vote: Vote) -> Result
      • 给一个公投投票
    • fn inject_referendum(end: T::BlockNumber,proposal: T::Proposal,threshold: VoteThreshold,delay: T::BlockNumber,) -> result::Result<ReferendumIndex, &'static str>
      • 开启一个公投
    • fn clear_referendum(ref_index: ReferendumIndex)
      • 移除一个公投的所有信息
    • fn enact_proposal(proposal: T::Proposal, index: ReferendumIndex)
      • 执行一个公投的提案,在end_block()方法中,如果到执行,就执行提案
    • fn launch_next(now: T::BlockNumber) -> Result
      • 将正在等待的下一个提案摆上桌面进行公投
    • fn launch_external(now: T::BlockNumber) -> Result
      • 将正在等待的下一个外部提案摆上桌面进行公投
    • fn launch_public(now: T::BlockNumber) -> Result
      • 将正在等待的下一个公共提案,下一个就是最高支持率的公共提案,将其摆上桌面进行公投
    • fn bake_referendum(now: T::BlockNumber,index: ReferendumIndex,info: ReferendumInfo<T::BlockNumber, T::Proposal>) -> Result
      • 点票统计,通过公投的进入执行队列,该锁定的执行周期进行锁定
    • fn end_block(now: T::BlockNumber) -> Result
      • 现在的era结束了,应该完成任何提案

    下一个公投是external需要满足下面两个中任何一个:

    1. LastTabledWasExternal 是 false;
    2. PublicProps 是空。

    也就是说下一个公投要是external proposal,要么是上一个公投不是external proposal,要么没有public proposal。

    群众发起的提案是public proposal,技术委员会成员快速通道发起的是external proposal,但是快速通道不能连续,除非没有公共提案。

    提案执行逻辑

    collective模块中,执行调用的必须是议会成员:

    #[weight = SimpleDispatchInfo::FixedOperational(100_000)]
    fn execute(origin, proposal: Box<<T as Trait<I>>::Proposal>) {
        let who = ensure_signed(origin)?;
        ensure!(Self::is_member(&who), "proposer not a member");
    
        let proposal_hash = T::Hashing::hash_of(&proposal);
        let ok = proposal.dispatch(RawOrigin::Member(who).into()).is_ok();
        Self::deposit_event(RawEvent::MemberExecuted(proposal_hash, ok));
    }
    

    在support模块的dispatch.rs中,定义了dispatch这个方法:

    fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResult<Self::Error> {
            match self {
                $(
                    $call_type::$fn_name( $( $param_name ),* ) => {
                        $crate::decl_module!(
                            @call
                            $from
                            $mod_type<$trait_instance $(, $fn_instance)?> $fn_name _origin $system [ $( $param_name ),* ]
                        )
                    },
                )*
                $call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") },
            }
        }

    相关文章

      网友评论

          本文标题:Substrate中democracy模块分析

          本文链接:https://www.haomeiwen.com/subject/rrkgwctx.html