Substrate中democracy模块分析

2019-11-29  本文已影响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

下一个公投是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.") },
        }
    }
上一篇下一篇

猜你喜欢

热点阅读