#tetcoin #framework #blockchain #crypto

无 std tp-election-providers

基本选举提供者

显示包…

2 个稳定版本

2.0.2 2021年4月3日
2.0.0 2021年4月2日

#118 in #tetcoin

Apache-2.0

335KB
7.5K SLoC

election-providers


lib.rs:

提供选举功能的基本特性。

该包提供了两个特性,可以交互以在 FRAME 等包中启用可扩展的选举功能。

能够提供选举功能的某物将实现 ElectionProvider,同时需要一个相关的 ElectionProvider::DataProvider,这需要由实现 ElectionDataProvider 的实体来满足。通常,数据提供者是 选举的接收者,从而产生如下所示的图

                                        ElectionDataProvider
                         <------------------------------------------+
                         |                                          |
                         v                                          |
                   +-----+----+                              +------+---+
                   |          |                              |          |
pallet-do-election |          |                              |          | pallet-needs-election
                   |          |                              |          |
                   |          |                              |          |
                   +-----+----+                              +------+---+
                         |                                          ^
                         |                                          |
                         +------------------------------------------+
                                        ElectionProvider

也有可能是一个第三方包(C)向选举提供者(B)提供选举数据,然后选举提供者(B)将选举结果传递给另一个包(A)。

选举类型

通常,存在两种类型的选举

  1. 无状态:提供选举数据,选举结果立即准备好。
  2. 有状态:提前查询选举数据,选举结果可能在未来的几个块内准备好。

为了在同一个特性中容纳这两种类型的选举,特性倾向于 有状态选举,因为它比无状态选举更通用。这就是为什么 ElectionProvider::elect 没有参数。所有值和类型参数必须由 ElectionDataProvider 特性提供,即使选举立即发生。

选举数据

与选举相关的数据,本质上是指ElectionDataProvider必须传达的内容如下

  1. 选民列表,以及他们的利益。
  2. 目标列表(即候选人)。
  3. 希望当选的目标数量(即赢家

除此之外,ElectionDataProvider还应该暗示ElectionProvider下次选举可能发生的时间(ElectionDataProvider::next_election_prediction)。无状态的选举提供者可能会忽略这一点。有状态的选举提供者可以使用它来提前准备选举结果。

尽管如此,ElectionProvider不应该依赖于这一点,并最好也提供一些备用选举方式,以防在太早的时候调用elect

示例


type AccountId = u64;
type Balance = u64;
type BlockNumber = u32;

mod data_provider {
    use super::*;

    pub trait Config: Sized {
        type ElectionProvider: ElectionProvider<
            AccountId,
            BlockNumber,
            DataProvider = Module<Self>,
        >;
    }

    pub struct Module<T: Config>(std::marker::PhantomData<T>);

    impl<T: Config> ElectionDataProvider<AccountId, BlockNumber> for Module<T> {
        fn desired_targets() -> u32 {
            1
        }
        fn voters() -> Vec<(AccountId, VoteWeight, Vec<AccountId>)> {
            Default::default()
        }
        fn targets() -> Vec<AccountId> {
            vec![10, 20, 30]
        }
        fn next_election_prediction(now: BlockNumber) -> BlockNumber {
            0
        }
    }
}


mod generic_election_provider {
    use super::*;

    pub struct GenericElectionProvider<T: Config>(std::marker::PhantomData<T>);

    pub trait Config {
        type DataProvider: ElectionDataProvider<AccountId, BlockNumber>;
    }

    impl<T: Config> ElectionProvider<AccountId, BlockNumber> for GenericElectionProvider<T> {
        type Error = ();
        type DataProvider = T::DataProvider;

        fn elect() -> Result<Supports<AccountId>, Self::Error> {
            Self::DataProvider::targets()
                .first()
                .map(|winner| vec![(*winner, Support::default())])
                .ok_or(())
        }
    }
}

mod runtime {
    use super::generic_election_provider;
    use super::data_provider;
    use super::AccountId;

    struct Runtime;
    impl generic_election_provider::Config for Runtime {
        type DataProvider = data_provider::Module<Runtime>;
    }

    impl data_provider::Config for Runtime {
        type ElectionProvider = generic_election_provider::GenericElectionProvider<Runtime>;
    }

}

依赖项

~3–11MB
~126K SLoC