34 次重大版本更新

37.0.0 2024年7月18日
36.0.0 2024年7月12日
35.0.0 2024年6月21日
34.0.0 2024年5月23日
0.0.0 2022年11月21日

15 in #assignment

Download history 1981/week @ 2024-05-02 1492/week @ 2024-05-09 1636/week @ 2024-05-16 2048/week @ 2024-05-23 1944/week @ 2024-05-30 1741/week @ 2024-06-06 1444/week @ 2024-06-13 2400/week @ 2024-06-20 1583/week @ 2024-06-27 894/week @ 2024-07-04 2576/week @ 2024-07-11 1753/week @ 2024-07-18 1567/week @ 2024-07-25 1662/week @ 2024-08-01 1903/week @ 2024-08-08 1902/week @ 2024-08-15

7,349 下载/月
90 crate 中使用(直接使用16个)

Apache-2.0

2.5MB
51K SLoC

提供选举功能的原始特性。

此crate提供两个特性,可以交互使用,以在FRAME提袋内启用可扩展的选举功能。

将提供选举功能的某物将实现ElectionProvider及其父特性ElectionProviderBase,同时需要一个关联的ElectionProviderBase::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_mod {
    use super::*;

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

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

    impl<T: Config> ElectionDataProvider for Pallet<T> {
        type AccountId = AccountId;
        type BlockNumber = BlockNumber;
        type MaxVotesPerVoter = ConstU32<1>;

        fn desired_targets() -> data_provider::Result<u32> {
            Ok(1)
        }
        fn electing_voters(bounds: DataProviderBounds)
          -> data_provider::Result<Vec<VoterOf<Self>>>
        {
            Ok(Default::default())
        }
        fn electable_targets(bounds: DataProviderBounds) -> data_provider::Result<Vec<AccountId>> {
            Ok(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=AccountId, BlockNumber = BlockNumber>;
    }

    impl<T: Config> ElectionProviderBase for GenericElectionProvider<T> {
        type AccountId = AccountId;
        type BlockNumber = BlockNumber;
        type Error = &'static str;
        type DataProvider = T::DataProvider;
        type MaxWinners = ConstU32<{ u32::MAX }>;

    }

    impl<T: Config> ElectionProvider for GenericElectionProvider<T> {
        fn ongoing() -> bool { false }
        fn elect() -> Result<BoundedSupportsOf<Self>, Self::Error> {
            Self::DataProvider::electable_targets(DataProviderBounds::default())
                .map_err(|_| "failed to elect")
                .map(|t| bounded_vec![(t[0], Support::default())])
        }
    }
}

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

    struct Runtime;
    impl generic_election_provider::Config for Runtime {
        type DataProvider = data_provider_mod::Pallet<Runtime>;
    }

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

}

依赖项

~18–33MB
~541K SLoC