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
7,349 下载/月
在 90 个 crate 中使用(直接使用16个)
2.5MB
51K SLoC
提供选举功能的原始特性。
此crate提供两个特性,可以交互使用,以在FRAME提袋内启用可扩展的选举功能。
将提供选举功能的某物将实现ElectionProvider
及其父特性ElectionProviderBase
,同时需要一个关联的ElectionProviderBase::DataProvider
,该关联需要由实现ElectionDataProvider
的实体来满足。通常,数据提供者是选举的接收者,结果如下面的图所示
ElectionDataProvider
<------------------------------------------+
| |
v |
+-----+----+ +------+---+
| | | |
pallet-do-election | | | | pallet-needs-election
| | | |
| | | |
+-----+----+ +------+---+
| ^
| |
+------------------------------------------+
ElectionProvider
也可能存在第三方托盘(C)向选举提供者(B)提供选举数据的情况,然后选举提供者(B)将选举结果传递给另一个托盘(A)。
选举类型
通常存在两种类型的选举:
- 无状态:提供选举数据后,选举结果立即可用。
- 有状态:提前查询选举数据,选举结果可能在未来的若干块之后才可用。
为了在一个特性中容纳这两种类型的选举,特性倾向于采用有状态选举,因为它比无状态选举更通用。这就是为什么ElectionProvider::elect
没有参数。所有值和类型参数必须由ElectionDataProvider
特性提供,即使选举是立即发生的。
选举数据
与选举相关的数据,即ElectionDataProvider
必须传达的数据如下:
- 选民列表,包括他们的股份。
- 目标列表(即候选人)。
- 希望当选的目标数量(即获胜者)。
此外,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