referrerpolicy=no-referrer-when-downgrade

frame_election_provider_support/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Primitive traits for providing election functionality.
19//!
20//! This crate provides two traits that could interact to enable extensible election functionality
21//! within FRAME pallets.
22//!
23//! Something that will provide the functionality of election will implement
24//! [`ElectionProvider`], whilst needing an associated [`ElectionProvider::DataProvider`], which
25//! needs to be fulfilled by an entity implementing [`ElectionDataProvider`]. Most often, *the data
26//! provider is* the receiver of the election, resulting in a diagram as below:
27//!
28//! ```ignore
29//!                                         ElectionDataProvider
30//!                          <------------------------------------------+
31//!                          |                                          |
32//!                          v                                          |
33//!                    +-----+----+                              +------+---+
34//!                    |          |                              |          |
35//! pallet-do-election |          |                              |          | pallet-needs-election
36//!                    |          |                              |          |
37//!                    |          |                              |          |
38//!                    +-----+----+                              +------+---+
39//!                          |                                          ^
40//!                          |                                          |
41//!                          +------------------------------------------+
42//!                                         ElectionProvider
43//! ```
44//!
45//! > It could also be possible that a third party pallet (C), provides the data of election to an
46//! > election provider (B), which then passes the election result to another pallet (A).
47//!
48//! ## Election Types
49//!
50//! Typically, two types of elections exist:
51//!
52//! 1. **Stateless**: Election data is provided, and the election result is immediately ready.
53//! 2. **Stateful**: Election data is is queried ahead of time, and the election result might be
54//!    ready some number of blocks in the future.
55//!
56//! To accommodate both type of elections in one trait, the traits lean toward **stateful
57//! election**, as it is more general than the stateless. This is why [`ElectionProvider::elect`]
58//! does not receive election data as an input. All value and type parameter must be provided by the
59//! [`ElectionDataProvider`] trait, even if the election happens immediately.
60//!
61//! ## Multi-page election support
62//!
63//! Both [`ElectionDataProvider`] and [`ElectionProvider`] traits are parameterized by page,
64//! supporting an election to be performed over multiple pages. This enables the
65//! [`ElectionDataProvider`] implementor to provide all the election data over multiple pages.
66//! Similarly [`ElectionProvider::elect`] is parameterized by page index.
67//!
68//! ## Election Data
69//!
70//! The data associated with an election, essentially what the [`ElectionDataProvider`] must convey
71//! is as follows:
72//!
73//! 1. A list of voters, with their stake.
74//! 2. A list of targets (i.e. _candidates_).
75//! 3. A number of desired targets to be elected (i.e. _winners_)
76//!
77//! In addition to that, the [`ElectionDataProvider`] must also hint [`ElectionProvider`] at when
78//! the next election might happen ([`ElectionDataProvider::next_election_prediction`]). A stateless
79//! election provider would probably ignore this. A stateful election provider can use this to
80//! prepare the election result in advance.
81//!
82//! Nonetheless, an [`ElectionProvider`] shan't rely on this and should preferably provide some
83//! means of fallback election as well, in case the `elect` was called immaturely early.
84//!
85//! ## Example
86//!
87//! ```rust
88//! # use frame_election_provider_support::{*, data_provider};
89//! # use sp_npos_elections::{Support, Assignment};
90//! # use frame_support::traits::ConstU32;
91//! # use sp_runtime::bounded_vec;
92//!
93//! type AccountId = u64;
94//! type Balance = u64;
95//! type BlockNumber = u32;
96//!
97//! mod data_provider_mod {
98//!     use super::*;
99//!
100//!     pub trait Config: Sized {
101//!         type ElectionProvider: ElectionProvider<
102//!             AccountId = AccountId,
103//!             BlockNumber = BlockNumber,
104//!             DataProvider = Pallet<Self>,
105//!         >;
106//!     }
107//!
108//!     pub struct Pallet<T: Config>(std::marker::PhantomData<T>);
109//!
110//!     impl<T: Config> ElectionDataProvider for Pallet<T> {
111//!         type AccountId = AccountId;
112//!         type BlockNumber = BlockNumber;
113//!         type MaxVotesPerVoter = ConstU32<100>;
114//!
115//!         fn desired_targets() -> data_provider::Result<u32> {
116//!             Ok(1)
117//!         }
118//!         fn electing_voters(bounds: DataProviderBounds, _page: PageIndex)
119//!           -> data_provider::Result<Vec<VoterOf<Self>>>
120//!         {
121//!             Ok(Default::default())
122//!         }
123//!         fn electable_targets(bounds: DataProviderBounds, _page: PageIndex) -> data_provider::Result<Vec<AccountId>> {
124//!             Ok(vec![10, 20, 30])
125//!         }
126//!         fn next_election_prediction(now: BlockNumber) -> BlockNumber {
127//!             0
128//!         }
129//!     }
130//! }
131//!
132//!
133//! mod generic_election_provider {
134//!     use super::*;
135//!     use sp_runtime::traits::Zero;
136//!
137//!     pub struct GenericElectionProvider<T: Config>(std::marker::PhantomData<T>);
138//!
139//!     pub trait Config {
140//!         type DataProvider: ElectionDataProvider<AccountId=AccountId, BlockNumber = BlockNumber>;
141//!         type MaxWinnersPerPage: Get<u32>;
142//!         type MaxBackersPerWinner: Get<u32>;
143//!         type Pages: Get<u32>;
144//!     }
145//!
146//!     impl<T: Config> ElectionProvider for GenericElectionProvider<T> {
147//!         type AccountId = AccountId;
148//!         type BlockNumber = BlockNumber;
149//!         type Error = &'static str;
150//!         type MaxBackersPerWinner = T::MaxBackersPerWinner;
151//! 		type MaxBackersPerWinnerFinal = T::MaxBackersPerWinner;
152//!         type MaxWinnersPerPage = T::MaxWinnersPerPage;
153//!         type Pages = T::Pages;
154//!         type DataProvider = T::DataProvider;
155//!
156//! 		fn duration() -> <Self as frame_election_provider_support::ElectionProvider>::BlockNumber { todo!() }
157//!
158//! 		fn start() -> Result<(), <Self as frame_election_provider_support::ElectionProvider>::Error> { todo!() }
159//!
160//!         fn elect(page: PageIndex) -> Result<BoundedSupportsOf<Self>, Self::Error> {
161//!             unimplemented!()
162//!         }
163//!
164//!         fn status() -> Result<bool, ()> {
165//!             unimplemented!()
166//!         }
167//!     }
168//! }
169//!
170//! mod runtime {
171//!     use frame_support::parameter_types;
172//!     use super::generic_election_provider;
173//!     use super::data_provider_mod;
174//!     use super::AccountId;
175//!
176//!     parameter_types! {
177//!         pub static MaxWinnersPerPage: u32 = 10;
178//!         pub static MaxBackersPerWinner: u32 = 20;
179//!         pub static Pages: u32 = 2;
180//!     }
181//!
182//!     struct Runtime;
183//!     impl generic_election_provider::Config for Runtime {
184//!         type DataProvider = data_provider_mod::Pallet<Runtime>;
185//!         type MaxWinnersPerPage = MaxWinnersPerPage;
186//!         type MaxBackersPerWinner = MaxBackersPerWinner;
187//!         type Pages = Pages;
188//!     }
189//!
190//!     impl data_provider_mod::Config for Runtime {
191//!         type ElectionProvider = generic_election_provider::GenericElectionProvider<Runtime>;
192//!     }
193//!
194//! }
195//!
196//! # fn main() {}
197//! ```
198
199#![cfg_attr(not(feature = "std"), no_std)]
200
201pub mod bounds;
202pub mod onchain;
203pub mod traits;
204
205extern crate alloc;
206
207use alloc::{boxed::Box, vec::Vec};
208use core::fmt::Debug;
209use frame_support::traits::{Defensive, DefensiveResult};
210use sp_core::ConstU32;
211use sp_runtime::{
212	traits::{Bounded, Saturating, Zero},
213	RuntimeDebug,
214};
215
216pub use bounds::DataProviderBounds;
217pub use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
218/// Re-export the solution generation macro.
219pub use frame_election_provider_solution_type::generate_solution_type;
220pub use frame_support::{traits::Get, weights::Weight, BoundedVec, DefaultNoBound};
221use scale_info::TypeInfo;
222/// Re-export some type as they are used in the interface.
223pub use sp_arithmetic::PerThing;
224pub use sp_npos_elections::{
225	Assignment, BalancingConfig, ElectionResult, Error, ExtendedBalance, IdentifierT, PerThing128,
226	Support, Supports, VoteWeight,
227};
228pub use traits::NposSolution;
229
230#[cfg(feature = "try-runtime")]
231use sp_runtime::TryRuntimeError;
232
233// re-export for the solution macro, with the dependencies of the macro.
234#[doc(hidden)]
235pub mod private {
236	pub use alloc::{
237		collections::{btree_map::BTreeMap, btree_set::BTreeSet},
238		vec::Vec,
239	};
240	pub use codec;
241	pub use scale_info;
242	pub use sp_arithmetic;
243
244	// Simple Extension trait to easily convert `None` from index closures to `Err`.
245	//
246	// This is only generated and re-exported for the solution code to use.
247	pub trait __OrInvalidIndex<T> {
248		fn or_invalid_index(self) -> Result<T, crate::Error>;
249	}
250
251	impl<T> __OrInvalidIndex<T> for Option<T> {
252		fn or_invalid_index(self) -> Result<T, crate::Error> {
253			self.ok_or(crate::Error::SolutionInvalidIndex)
254		}
255	}
256}
257
258use private::__OrInvalidIndex;
259
260pub mod weights;
261pub use weights::WeightInfo;
262
263#[cfg(test)]
264mod mock;
265#[cfg(test)]
266mod tests;
267
268/// A page index for the multi-block elections pagination.
269pub type PageIndex = u32;
270
271/// The [`IndexAssignment`] type is an intermediate between the assignments list
272/// ([`&[Assignment<T>]`][Assignment]) and `SolutionOf<T>`.
273///
274/// The voter and target identifiers have already been replaced with appropriate indices,
275/// making it fast to repeatedly encode into a `SolutionOf<T>`. This property turns out
276/// to be important when trimming for solution length.
277#[derive(RuntimeDebug, Clone, Default)]
278#[cfg_attr(feature = "std", derive(PartialEq, Eq, Encode, Decode))]
279pub struct IndexAssignment<VoterIndex, TargetIndex, P: PerThing> {
280	/// Index of the voter among the voters list.
281	pub who: VoterIndex,
282	/// The distribution of the voter's stake among winning targets.
283	///
284	/// Targets are identified by their index in the canonical list.
285	pub distribution: Vec<(TargetIndex, P)>,
286}
287
288impl<VoterIndex: core::fmt::Debug, TargetIndex: core::fmt::Debug, P: PerThing>
289	IndexAssignment<VoterIndex, TargetIndex, P>
290{
291	pub fn new<AccountId: IdentifierT>(
292		assignment: &Assignment<AccountId, P>,
293		voter_index: impl Fn(&AccountId) -> Option<VoterIndex>,
294		target_index: impl Fn(&AccountId) -> Option<TargetIndex>,
295	) -> Result<Self, Error> {
296		Ok(Self {
297			who: voter_index(&assignment.who).or_invalid_index()?,
298			distribution: assignment
299				.distribution
300				.iter()
301				.map(|(target, proportion)| Some((target_index(target)?, *proportion)))
302				.collect::<Option<Vec<_>>>()
303				.or_invalid_index()?,
304		})
305	}
306}
307
308/// A type alias for [`IndexAssignment`] made from [`NposSolution`].
309pub type IndexAssignmentOf<C> = IndexAssignment<
310	<C as NposSolution>::VoterIndex,
311	<C as NposSolution>::TargetIndex,
312	<C as NposSolution>::Accuracy,
313>;
314
315/// Types that are used by the data provider trait.
316pub mod data_provider {
317	/// Alias for the result type of the election data provider.
318	pub type Result<T> = core::result::Result<T, &'static str>;
319}
320
321/// Something that can provide the data to an [`ElectionProvider`].
322pub trait ElectionDataProvider {
323	/// The account identifier type.
324	type AccountId: Encode;
325
326	/// The block number type.
327	type BlockNumber;
328
329	/// Maximum number of votes per voter that this data provider is providing.
330	type MaxVotesPerVoter: Get<u32>;
331
332	/// Returns the possible targets for the election associated with the provided `page`, i.e. the
333	/// targets that could become elected, thus "electable".
334	///
335	/// This should be implemented as a self-weighing function. The implementor should register its
336	/// appropriate weight at the end of execution with the system pallet directly.
337	fn electable_targets(
338		bounds: DataProviderBounds,
339		page: PageIndex,
340	) -> data_provider::Result<Vec<Self::AccountId>>;
341
342	/// A state-less version of [`Self::electable_targets`].
343	///
344	/// An election-provider that only uses 1 page should use this.
345	fn electable_targets_stateless(
346		bounds: DataProviderBounds,
347	) -> data_provider::Result<Vec<Self::AccountId>> {
348		Self::electable_targets(bounds, 0)
349	}
350
351	/// All the voters that participate in the election associated with page `page`, thus
352	/// "electing".
353	///
354	/// Note that if a notion of self-vote exists, it should be represented here.
355	///
356	/// This should be implemented as a self-weighing function. The implementor should register its
357	/// appropriate weight at the end of execution with the system pallet directly.
358	fn electing_voters(
359		bounds: DataProviderBounds,
360		page: PageIndex,
361	) -> data_provider::Result<Vec<VoterOf<Self>>>;
362
363	/// A state-less version of [`Self::electing_voters`].
364	///
365	/// An election-provider that only uses 1 page should use this.
366	fn electing_voters_stateless(
367		bounds: DataProviderBounds,
368	) -> data_provider::Result<Vec<VoterOf<Self>>> {
369		Self::electing_voters(bounds, 0)
370	}
371
372	/// The number of targets to elect.
373	///
374	/// This should be implemented as a self-weighing function. The implementor should register its
375	/// appropriate weight at the end of execution with the system pallet directly.
376	///
377	/// A sensible implementation should use the minimum between this value and
378	/// [`Self::targets().len()`], since desiring a winner set larger than candidates is not
379	/// feasible.
380	///
381	/// This is documented further in issue: <https://github.com/paritytech/substrate/issues/9478>
382	fn desired_targets() -> data_provider::Result<u32>;
383
384	/// Provide a best effort prediction about when the next election is about to happen.
385	///
386	/// In essence, the implementor should predict with this function when it will trigger the
387	/// [`ElectionProvider::elect`].
388	///
389	/// This is only useful for stateful election providers.
390	fn next_election_prediction(now: Self::BlockNumber) -> Self::BlockNumber;
391
392	/// Utility function only to be used in benchmarking scenarios, to be implemented optionally,
393	/// else a noop.
394	#[cfg(any(feature = "runtime-benchmarks", test))]
395	fn put_snapshot(
396		_voters: Vec<VoterOf<Self>>,
397		_targets: Vec<Self::AccountId>,
398		_target_stake: Option<VoteWeight>,
399	) {
400	}
401
402	/// Instruct the data provider to fetch a page of the solution.
403	///
404	/// This can be useful to measure the export process in benchmarking.
405	#[cfg(any(feature = "runtime-benchmarks", test))]
406	fn fetch_page(_page: PageIndex) {}
407
408	/// Utility function only to be used in benchmarking scenarios, to be implemented optionally,
409	/// else a noop.
410	///
411	/// Same as `put_snapshot`, but can add a single voter one by one.
412	#[cfg(any(feature = "runtime-benchmarks", test))]
413	fn add_voter(
414		_voter: Self::AccountId,
415		_weight: VoteWeight,
416		_targets: BoundedVec<Self::AccountId, Self::MaxVotesPerVoter>,
417	) {
418	}
419
420	/// Utility function only to be used in benchmarking scenarios, to be implemented optionally,
421	/// else a noop.
422	///
423	/// Same as `put_snapshot`, but can add a single voter one by one.
424	#[cfg(any(feature = "runtime-benchmarks", test))]
425	fn add_target(_target: Self::AccountId) {}
426
427	/// Clear all voters and targets.
428	#[cfg(any(feature = "runtime-benchmarks", test))]
429	fn clear() {}
430
431	/// Force set the desired targets in the snapshot.
432	#[cfg(any(feature = "runtime-benchmarks", test))]
433	fn set_desired_targets(_count: u32) {}
434}
435
436/// Something that can compute the result of an election and pass it back to the caller in a paged
437/// way.
438pub trait ElectionProvider {
439	/// The account ID identifier;
440	type AccountId;
441
442	/// The block number type.
443	type BlockNumber;
444
445	/// The error type returned by the provider;
446	type Error: Debug + PartialEq;
447
448	/// The maximum number of winners per page in results returned by this election provider.
449	///
450	/// A winner is an `AccountId` that is part of the final election result.
451	type MaxWinnersPerPage: Get<u32>;
452
453	/// The maximum number of backers that a single page may have in results returned by this
454	/// election provider.
455	///
456	/// A backer is an `AccountId` that "backs" one or more winners. For example, in the context of
457	/// nominated proof of stake, a backer is a voter that nominates a winner validator in the
458	/// election result.
459	type MaxBackersPerWinner: Get<u32>;
460
461	/// Same as [`Self::MaxBackersPerWinner`], but across all pages.
462	///
463	/// If [`Self::Pages`] is set to 0, a reasonable value is [`Self::MaxBackersPerWinner`]. For
464	/// multi-page elections, a reasonable value is the range of [`Self::MaxBackersPerWinner`] to
465	/// [`Self::Pages`] * [`Self::MaxBackersPerWinner`].
466	type MaxBackersPerWinnerFinal: Get<u32>;
467
468	/// The number of pages that this election provider supports.
469	type Pages: Get<PageIndex>;
470
471	/// The data provider of the election.
472	type DataProvider: ElectionDataProvider<
473		AccountId = Self::AccountId,
474		BlockNumber = Self::BlockNumber,
475	>;
476
477	/// Elect a new set of winners.
478	///
479	/// A complete election may require multiple calls to [`ElectionProvider::elect`] if
480	/// [`ElectionProvider::Pages`] is higher than one.
481	///
482	/// The result is returned in a target major format, namely as vector of supports.
483	fn elect(page: PageIndex) -> Result<BoundedSupportsOf<Self>, Self::Error>;
484
485	/// The index of the *most* significant page that this election provider supports.
486	fn msp() -> PageIndex {
487		Self::Pages::get().saturating_sub(1)
488	}
489
490	/// The index of the *least* significant page that this election provider supports.
491	fn lsp() -> PageIndex {
492		Zero::zero()
493	}
494
495	/// checked call to `Self::DataProvider::desired_targets()` ensuring the value never exceeds
496	/// [`Self::MaxWinnersPerPage`].
497	fn desired_targets_checked() -> data_provider::Result<u32> {
498		Self::DataProvider::desired_targets().and_then(|desired_targets| {
499			if desired_targets <= Self::MaxWinnersPerPage::get() {
500				Ok(desired_targets)
501			} else {
502				Err("desired_targets must not be greater than MaxWinners.")
503			}
504		})
505	}
506
507	/// Return the duration of your election.
508	///
509	/// This excludes the duration of the export. For that, use [`Self::duration_with_export`].
510	fn duration() -> Self::BlockNumber;
511
512	/// Return the duration of your election, including the export.
513	fn duration_with_export() -> Self::BlockNumber
514	where
515		Self::BlockNumber: From<PageIndex> + core::ops::Add<Output = Self::BlockNumber>,
516	{
517		let export: Self::BlockNumber = Self::Pages::get().into();
518		Self::duration() + export
519	}
520
521	/// Signal that the election should start
522	fn start() -> Result<(), Self::Error>;
523
524	/// Indicate whether this election provider is currently ongoing an asynchronous election.
525	///
526	/// `Err(())` should signal that we are not doing anything, and `elect` should def. not be
527	/// called. `Ok(false)` means we are doing something, but work is still ongoing. `elect` should
528	/// not be called. `Ok(true)` means we are done and ready for a call to `elect`.
529	fn status() -> Result<bool, ()>;
530
531	/// Signal the election provider that we are about to call `elect` asap, and it should prepare
532	/// itself.
533	#[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
534	fn asap() {}
535}
536
537/// A (almost) marker trait that signifies an election provider as working synchronously. i.e. being
538/// *instant*.
539///
540/// This must still use the same data provider as with [`ElectionProvider::DataProvider`].
541/// However, it can optionally overwrite the amount of voters and targets that are fetched from the
542/// data provider at runtime via `forced_input_voters_bound` and `forced_input_target_bound`.
543pub trait InstantElectionProvider: ElectionProvider {
544	fn instant_elect(
545		voters: Vec<VoterOf<Self::DataProvider>>,
546		targets: Vec<Self::AccountId>,
547		desired_targets: u32,
548	) -> Result<BoundedSupportsOf<Self>, Self::Error>;
549
550	// Sine many instant election provider, like [`NoElection`] are meant to do nothing, this is a
551	// hint for the caller to call before, and if `false` is returned, not bother with passing all
552	// the info to `instant_elect`.
553	fn bother() -> bool;
554}
555
556/// An election provider that does nothing whatsoever.
557pub struct NoElection<X>(core::marker::PhantomData<X>);
558
559impl<AccountId, BlockNumber, DataProvider, MaxWinnersPerPage, MaxBackersPerWinner> ElectionProvider
560	for NoElection<(AccountId, BlockNumber, DataProvider, MaxWinnersPerPage, MaxBackersPerWinner)>
561where
562	DataProvider: ElectionDataProvider<AccountId = AccountId, BlockNumber = BlockNumber>,
563	MaxWinnersPerPage: Get<u32>,
564	MaxBackersPerWinner: Get<u32>,
565	BlockNumber: Zero,
566{
567	type AccountId = AccountId;
568	type BlockNumber = BlockNumber;
569	type Error = &'static str;
570	type Pages = ConstU32<1>;
571	type DataProvider = DataProvider;
572	type MaxWinnersPerPage = MaxWinnersPerPage;
573	type MaxBackersPerWinner = MaxBackersPerWinner;
574	type MaxBackersPerWinnerFinal = MaxBackersPerWinner;
575
576	fn elect(_page: PageIndex) -> Result<BoundedSupportsOf<Self>, Self::Error> {
577		Err("`NoElection` cannot do anything.")
578	}
579
580	fn start() -> Result<(), Self::Error> {
581		Err("`NoElection` cannot do anything.")
582	}
583
584	fn duration() -> Self::BlockNumber {
585		Zero::zero()
586	}
587
588	fn status() -> Result<bool, ()> {
589		Err(())
590	}
591}
592
593impl<AccountId, BlockNumber, DataProvider, MaxWinnersPerPage, MaxBackersPerWinner>
594	InstantElectionProvider
595	for NoElection<(AccountId, BlockNumber, DataProvider, MaxWinnersPerPage, MaxBackersPerWinner)>
596where
597	DataProvider: ElectionDataProvider<AccountId = AccountId, BlockNumber = BlockNumber>,
598	MaxWinnersPerPage: Get<u32>,
599	MaxBackersPerWinner: Get<u32>,
600	BlockNumber: Zero,
601{
602	fn instant_elect(
603		_: Vec<VoterOf<Self::DataProvider>>,
604		_: Vec<Self::AccountId>,
605		_: u32,
606	) -> Result<BoundedSupportsOf<Self>, Self::Error> {
607		Err("`NoElection` cannot do anything.")
608	}
609
610	fn bother() -> bool {
611		false
612	}
613}
614
615/// A utility trait for something to implement `ElectionDataProvider` in a sensible way.
616///
617/// This is generic over `AccountId` and it can represent a validator, a nominator, or any other
618/// entity.
619///
620/// The scores (see [`Self::Score`]) are ascending, the higher, the better.
621///
622/// Something that implements this trait will do a best-effort sort over ids, and thus can be
623/// used on the implementing side of [`ElectionDataProvider`].
624pub trait SortedListProvider<AccountId> {
625	/// The list's error type.
626	type Error: core::fmt::Debug;
627
628	/// The type used by the list to compare nodes for ordering.
629	type Score: Bounded + Saturating + Zero + Default;
630
631	/// A typical range for this list.
632	///
633	/// By default, this would be implemented as `Bounded` impl of `Self::Score`.
634	///
635	/// If this is implemented by a bags-list instance, it will be the smallest and largest bags.
636	///
637	/// This is useful to help another pallet that consumes this trait generate an even distribution
638	/// of nodes for testing/genesis.
639	fn range() -> (Self::Score, Self::Score) {
640		(Self::Score::min_value(), Self::Score::max_value())
641	}
642
643	/// An iterator over the list, which can have `take` called on it.
644	fn iter() -> Box<dyn Iterator<Item = AccountId>>;
645
646	/// Lock the list.
647	///
648	/// This will prevent subsequent calls to
649	/// - [`Self::on_insert`]
650	/// - [`Self::on_update`]
651	/// - [`Self::on_decrease`]
652	/// - [`Self::on_increase`]
653	/// - [`Self::on_remove`]
654	fn lock();
655
656	/// Unlock the list. This will nullify the effects of [`Self::lock`].
657	fn unlock();
658
659	/// Returns an iterator over the list, starting right after from the given voter.
660	///
661	/// May return an error if `start` is invalid.
662	fn iter_from(start: &AccountId) -> Result<Box<dyn Iterator<Item = AccountId>>, Self::Error>;
663
664	/// The current count of ids in the list.
665	fn count() -> u32;
666
667	/// Return true if the list already contains `id`.
668	fn contains(id: &AccountId) -> bool;
669
670	/// Hook for inserting a new id.
671	///
672	/// Implementation should return an error if duplicate item is being inserted.
673	fn on_insert(id: AccountId, score: Self::Score) -> Result<(), Self::Error>;
674
675	/// Hook for updating a single id.
676	///
677	/// The `new` score is given.
678	///
679	/// Returns `Ok(())` iff it successfully updates an item, an `Err(_)` otherwise.
680	fn on_update(id: &AccountId, score: Self::Score) -> Result<(), Self::Error>;
681
682	/// Get the score of `id`.
683	fn get_score(id: &AccountId) -> Result<Self::Score, Self::Error>;
684
685	/// Same as `on_update`, but incorporate some increased score.
686	fn on_increase(id: &AccountId, additional: Self::Score) -> Result<(), Self::Error> {
687		let old_score = Self::get_score(id)?;
688		let new_score = old_score.saturating_add(additional);
689		Self::on_update(id, new_score)
690	}
691
692	/// Same as `on_update`, but incorporate some decreased score.
693	///
694	/// If the new score of the item is `Zero`, it is removed.
695	fn on_decrease(id: &AccountId, decreased: Self::Score) -> Result<(), Self::Error> {
696		let old_score = Self::get_score(id)?;
697		let new_score = old_score.saturating_sub(decreased);
698		if new_score.is_zero() {
699			Self::on_remove(id)
700		} else {
701			Self::on_update(id, new_score)
702		}
703	}
704
705	/// Hook for removing am id from the list.
706	///
707	/// Returns `Ok(())` iff it successfully removes an item, an `Err(_)` otherwise.
708	fn on_remove(id: &AccountId) -> Result<(), Self::Error>;
709
710	/// Regenerate this list from scratch. Returns the count of items inserted.
711	///
712	/// This should typically only be used at a runtime upgrade.
713	///
714	/// ## WARNING
715	///
716	/// This function should be called with care, regenerate will remove the current list write the
717	/// new list, which can lead to too many storage accesses, exhausting the block weight.
718	fn unsafe_regenerate(
719		all: impl IntoIterator<Item = AccountId>,
720		score_of: Box<dyn Fn(&AccountId) -> Option<Self::Score>>,
721	) -> u32;
722
723	/// Remove all items from the list.
724	///
725	/// ## WARNING
726	///
727	/// This function should never be called in production settings because it can lead to an
728	/// unbounded amount of storage accesses.
729	fn unsafe_clear();
730
731	/// Check internal state of the list. Only meant for debugging.
732	#[cfg(feature = "try-runtime")]
733	fn try_state() -> Result<(), TryRuntimeError>;
734
735	/// If `who` changes by the returned amount they are guaranteed to have a worst case change
736	/// in their list position.
737	#[cfg(feature = "runtime-benchmarks")]
738	fn score_update_worst_case(_who: &AccountId, _is_increase: bool) -> Self::Score;
739}
740
741/// Something that can provide the `Score` of an account. Similar to [`ElectionProvider`] and
742/// [`ElectionDataProvider`], this should typically be implementing by whoever is supposed to *use*
743/// `SortedListProvider`.
744pub trait ScoreProvider<AccountId> {
745	type Score;
746
747	/// Get the current `Score` of `who`, `None` if `who` is not present.
748	///
749	/// `None` can be interpreted as a signal that the voter should be removed from the list.
750	fn score(who: &AccountId) -> Option<Self::Score>;
751
752	/// For tests, benchmarks and fuzzing, set the `score`.
753	#[cfg(any(feature = "runtime-benchmarks", feature = "fuzz", feature = "std"))]
754	fn set_score_of(_: &AccountId, _: Self::Score) {}
755}
756
757/// Something that can compute the result to an NPoS solution.
758pub trait NposSolver {
759	/// The account identifier type of this solver.
760	type AccountId: sp_npos_elections::IdentifierT;
761	/// The accuracy of this solver. This will affect the accuracy of the output.
762	type Accuracy: PerThing128;
763	/// The error type of this implementation.
764	type Error: core::fmt::Debug + core::cmp::PartialEq;
765
766	/// Solve an NPoS solution with the given `voters`, `targets`, and select `to_elect` count
767	/// of `targets`.
768	fn solve(
769		to_elect: usize,
770		targets: Vec<Self::AccountId>,
771		voters: Vec<(
772			Self::AccountId,
773			VoteWeight,
774			impl Clone + IntoIterator<Item = Self::AccountId>,
775		)>,
776	) -> Result<ElectionResult<Self::AccountId, Self::Accuracy>, Self::Error>;
777
778	/// Measure the weight used in the calculation of the solver.
779	/// - `voters` is the number of voters.
780	/// - `targets` is the number of targets.
781	/// - `vote_degree` is the degree ie the maximum numbers of votes per voter.
782	fn weight<T: WeightInfo>(voters: u32, targets: u32, vote_degree: u32) -> Weight;
783}
784
785/// A quick and dirty solver, that produces a valid but probably worthless election result, but is
786/// fast.
787///
788/// It choses a random number of winners without any consideration.
789///
790/// Then it iterates over the voters and assigns them to the winners.
791///
792/// It is only meant to be used in benchmarking.
793pub struct QuickDirtySolver<AccountId, Accuracy>(core::marker::PhantomData<(AccountId, Accuracy)>);
794impl<AccountId: IdentifierT, Accuracy: PerThing128> NposSolver
795	for QuickDirtySolver<AccountId, Accuracy>
796{
797	type AccountId = AccountId;
798	type Accuracy = Accuracy;
799	type Error = &'static str;
800
801	fn solve(
802		to_elect: usize,
803		targets: Vec<Self::AccountId>,
804		voters: Vec<(
805			Self::AccountId,
806			VoteWeight,
807			impl Clone + IntoIterator<Item = Self::AccountId>,
808		)>,
809	) -> Result<ElectionResult<Self::AccountId, Self::Accuracy>, Self::Error> {
810		use sp_std::collections::btree_map::BTreeMap;
811
812		if to_elect > targets.len() {
813			return Err("to_elect is greater than the number of targets.");
814		}
815
816		let winners = targets.into_iter().take(to_elect).collect::<Vec<_>>();
817
818		let mut assignments = Vec::with_capacity(voters.len());
819		let mut final_winners = BTreeMap::<Self::AccountId, u128>::new();
820
821		for (voter, weight, votes) in voters {
822			let our_winners = winners
823				.iter()
824				.filter(|w| votes.clone().into_iter().any(|v| v == **w))
825				.collect::<Vec<_>>();
826			let our_winners_len = our_winners.len();
827			let distribution = our_winners
828				.into_iter()
829				.map(|w| {
830					*final_winners.entry(w.clone()).or_default() += weight as u128;
831					(w.clone(), Self::Accuracy::from_rational(1, our_winners_len as u128))
832				})
833				.collect::<Vec<_>>();
834
835			let mut assignment = Assignment { who: voter, distribution };
836			assignment.try_normalize().unwrap();
837			assignments.push(assignment);
838		}
839
840		let winners = final_winners.into_iter().collect::<Vec<_>>();
841		Ok(ElectionResult { winners, assignments })
842	}
843
844	fn weight<T: WeightInfo>(_: u32, _: u32, _: u32) -> Weight {
845		Default::default()
846	}
847}
848
849/// A wrapper for [`sp_npos_elections::seq_phragmen`] that implements [`NposSolver`]. See the
850/// documentation of [`sp_npos_elections::seq_phragmen`] for more info.
851pub struct SequentialPhragmen<AccountId, Accuracy, Balancing = ()>(
852	core::marker::PhantomData<(AccountId, Accuracy, Balancing)>,
853);
854
855impl<AccountId: IdentifierT, Accuracy: PerThing128, Balancing: Get<Option<BalancingConfig>>>
856	NposSolver for SequentialPhragmen<AccountId, Accuracy, Balancing>
857{
858	type AccountId = AccountId;
859	type Accuracy = Accuracy;
860	type Error = sp_npos_elections::Error;
861	fn solve(
862		winners: usize,
863		targets: Vec<Self::AccountId>,
864		voters: Vec<(
865			Self::AccountId,
866			VoteWeight,
867			impl Clone + IntoIterator<Item = Self::AccountId>,
868		)>,
869	) -> Result<ElectionResult<Self::AccountId, Self::Accuracy>, Self::Error> {
870		sp_npos_elections::seq_phragmen(winners, targets, voters, Balancing::get())
871	}
872
873	fn weight<T: WeightInfo>(voters: u32, targets: u32, vote_degree: u32) -> Weight {
874		T::phragmen(voters, targets, vote_degree)
875	}
876}
877
878/// A wrapper for [`sp_npos_elections::phragmms()`] that implements [`NposSolver`]. See the
879/// documentation of [`sp_npos_elections::phragmms()`] for more info.
880pub struct PhragMMS<AccountId, Accuracy, Balancing = ()>(
881	core::marker::PhantomData<(AccountId, Accuracy, Balancing)>,
882);
883
884impl<AccountId: IdentifierT, Accuracy: PerThing128, Balancing: Get<Option<BalancingConfig>>>
885	NposSolver for PhragMMS<AccountId, Accuracy, Balancing>
886{
887	type AccountId = AccountId;
888	type Accuracy = Accuracy;
889	type Error = sp_npos_elections::Error;
890	fn solve(
891		winners: usize,
892		targets: Vec<Self::AccountId>,
893		voters: Vec<(
894			Self::AccountId,
895			VoteWeight,
896			impl Clone + IntoIterator<Item = Self::AccountId>,
897		)>,
898	) -> Result<ElectionResult<Self::AccountId, Self::Accuracy>, Self::Error> {
899		sp_npos_elections::phragmms(winners, targets, voters, Balancing::get())
900	}
901
902	fn weight<T: WeightInfo>(voters: u32, targets: u32, vote_degree: u32) -> Weight {
903		T::phragmms(voters, targets, vote_degree)
904	}
905}
906
907/// A voter, at the level of abstraction of this crate.
908pub type Voter<AccountId, Bound> = (AccountId, VoteWeight, BoundedVec<AccountId, Bound>);
909
910/// Same as [`Voter`], but parameterized by an [`ElectionDataProvider`].
911pub type VoterOf<D> =
912	Voter<<D as ElectionDataProvider>::AccountId, <D as ElectionDataProvider>::MaxVotesPerVoter>;
913
914/// A bounded vector of supports. Bounded equivalent to [`sp_npos_elections::Supports`].
915#[derive(
916	Default, Debug, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, MaxEncodedLen,
917)]
918#[codec(mel_bound(AccountId: MaxEncodedLen, Bound: Get<u32>))]
919#[scale_info(skip_type_params(Bound))]
920pub struct BoundedSupport<AccountId, Bound: Get<u32>> {
921	/// Total support.
922	pub total: ExtendedBalance,
923	/// Support from voters.
924	pub voters: BoundedVec<(AccountId, ExtendedBalance), Bound>,
925}
926
927impl<AccountId, Bound: Get<u32>> sp_npos_elections::Backings for &BoundedSupport<AccountId, Bound> {
928	fn total(&self) -> ExtendedBalance {
929		self.total
930	}
931}
932
933impl<AccountId: PartialEq, Bound: Get<u32>> PartialEq for BoundedSupport<AccountId, Bound> {
934	fn eq(&self, other: &Self) -> bool {
935		self.total == other.total && self.voters == other.voters
936	}
937}
938
939impl<AccountId, Bound: Get<u32>> From<BoundedSupport<AccountId, Bound>> for Support<AccountId> {
940	fn from(b: BoundedSupport<AccountId, Bound>) -> Self {
941		Support { total: b.total, voters: b.voters.into_inner() }
942	}
943}
944
945impl<AccountId: Clone, Bound: Get<u32>> Clone for BoundedSupport<AccountId, Bound> {
946	fn clone(&self) -> Self {
947		Self { voters: self.voters.clone(), total: self.total }
948	}
949}
950
951impl<AccountId, Bound: Get<u32>> TryFrom<sp_npos_elections::Support<AccountId>>
952	for BoundedSupport<AccountId, Bound>
953{
954	type Error = &'static str;
955	fn try_from(s: sp_npos_elections::Support<AccountId>) -> Result<Self, Self::Error> {
956		let voters = s.voters.try_into().map_err(|_| "voters bound not respected")?;
957		Ok(Self { voters, total: s.total })
958	}
959}
960
961impl<AccountId: Clone, Bound: Get<u32>> BoundedSupport<AccountId, Bound> {
962	/// Try and construct a `BoundedSupport` from an unbounded version, and reside to sorting and
963	/// truncating if needed.
964	///
965	/// Returns the number of backers removed.
966	pub fn sorted_truncate_from(mut support: sp_npos_elections::Support<AccountId>) -> (Self, u32) {
967		// If bounds meet, then short circuit.
968		if let Ok(bounded) = support.clone().try_into() {
969			return (bounded, 0)
970		}
971
972		let pre_len = support.voters.len();
973		// sort support based on stake of each backer, low to high.
974		// Note: we don't sort high to low and truncate because we would have to track `total`
975		// updates, so we need one iteration anyhow.
976		support.voters.sort_by(|a, b| a.1.cmp(&b.1));
977		// then do the truncation.
978		let mut bounded = Self { voters: Default::default(), total: 0 };
979		while let Some((voter, weight)) = support.voters.pop() {
980			if let Err(_) = bounded.voters.try_push((voter, weight)) {
981				break
982			}
983			bounded.total += weight;
984		}
985		let post_len = bounded.voters.len();
986		(bounded, (pre_len - post_len) as u32)
987	}
988}
989
990/// A bounded vector of [`BoundedSupport`].
991///
992/// A [`BoundedSupports`] is a set of [`sp_npos_elections::Supports`] which are bounded in two
993/// dimensions. `BInner` corresponds to the bound of the maximum backers per voter and `BOuter`
994/// corresponds to the bound of the maximum winners that the bounded supports may contain.
995///
996/// With the bounds, we control the maximum size of a bounded supports instance.
997#[derive(Encode, Decode, DecodeWithMemTracking, TypeInfo, DefaultNoBound, MaxEncodedLen)]
998#[codec(mel_bound(AccountId: MaxEncodedLen, BOuter: Get<u32>, BInner: Get<u32>))]
999#[scale_info(skip_type_params(BOuter, BInner))]
1000pub struct BoundedSupports<AccountId, BOuter: Get<u32>, BInner: Get<u32>>(
1001	pub BoundedVec<(AccountId, BoundedSupport<AccountId, BInner>), BOuter>,
1002);
1003
1004/// Try and build yourself from another `BoundedSupports` with a different set of types.
1005pub trait TryFromOtherBounds<AccountId, BOtherOuter: Get<u32>, BOtherInner: Get<u32>> {
1006	fn try_from_other_bounds(
1007		other: BoundedSupports<AccountId, BOtherOuter, BOtherInner>,
1008	) -> Result<Self, crate::Error>
1009	where
1010		Self: Sized;
1011}
1012
1013impl<
1014		AccountId,
1015		BOuter: Get<u32>,
1016		BInner: Get<u32>,
1017		BOtherOuter: Get<u32>,
1018		BOuterInner: Get<u32>,
1019	> TryFromOtherBounds<AccountId, BOtherOuter, BOuterInner>
1020	for BoundedSupports<AccountId, BOuter, BInner>
1021{
1022	fn try_from_other_bounds(
1023		other: BoundedSupports<AccountId, BOtherOuter, BOuterInner>,
1024	) -> Result<Self, crate::Error> {
1025		// NOTE: we might as well do this with unsafe rust and do it faster.
1026		if BOtherOuter::get() <= BOuter::get() && BOuterInner::get() <= BInner::get() {
1027			// Both ouf our bounds are larger than the input's bound, can convert.
1028			let supports = other
1029				.into_iter()
1030				.map(|(acc, b_support)| {
1031					b_support
1032						.try_into()
1033						.defensive_map_err(|_| Error::BoundsExceeded)
1034						.map(|b_support| (acc, b_support))
1035				})
1036				.collect::<Result<Vec<_>, _>>()
1037				.defensive()?;
1038			supports.try_into()
1039		} else {
1040			Err(crate::Error::BoundsExceeded)
1041		}
1042	}
1043}
1044
1045impl<AccountId: Clone, BOuter: Get<u32>, BInner: Get<u32>>
1046	BoundedSupports<AccountId, BOuter, BInner>
1047{
1048	/// Try and construct a `BoundedSupports` from an unbounded version, and reside to sorting and
1049	/// truncating if need ne.
1050	///
1051	/// Two u32s returned are number of winners and backers removed respectively.
1052	pub fn sorted_truncate_from(supports: Supports<AccountId>) -> (Self, u32, u32) {
1053		// if bounds, meet, short circuit
1054		if let Ok(bounded) = supports.clone().try_into() {
1055			return (bounded, 0, 0)
1056		}
1057
1058		let pre_winners = supports.len();
1059		let mut backers_removed = 0;
1060		// first, convert all inner supports.
1061		let mut inner_supports = supports
1062			.into_iter()
1063			.map(|(account, support)| {
1064				let (bounded, removed) =
1065					BoundedSupport::<AccountId, BInner>::sorted_truncate_from(support);
1066				backers_removed += removed;
1067				(account, bounded)
1068			})
1069			.collect::<Vec<_>>();
1070
1071		// then sort outer supports based on total stake, high to low
1072		inner_supports.sort_by(|a, b| b.1.total.cmp(&a.1.total));
1073
1074		// then take the first slice that can fit.
1075		let bounded = BoundedSupports(BoundedVec::<
1076			(AccountId, BoundedSupport<AccountId, BInner>),
1077			BOuter,
1078		>::truncate_from(inner_supports));
1079		let post_winners = bounded.len();
1080		(bounded, (pre_winners - post_winners) as u32, backers_removed)
1081	}
1082}
1083
1084/// Helper trait for conversion of a vector of unbounded supports into a vector of bounded ones.
1085pub trait TryFromUnboundedPagedSupports<AccountId, BOuter: Get<u32>, BInner: Get<u32>> {
1086	fn try_from_unbounded_paged(
1087		self,
1088	) -> Result<Vec<BoundedSupports<AccountId, BOuter, BInner>>, crate::Error>
1089	where
1090		Self: Sized;
1091}
1092
1093impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>>
1094	TryFromUnboundedPagedSupports<AccountId, BOuter, BInner> for Vec<Supports<AccountId>>
1095{
1096	fn try_from_unbounded_paged(
1097		self,
1098	) -> Result<Vec<BoundedSupports<AccountId, BOuter, BInner>>, crate::Error> {
1099		self.into_iter()
1100			.map(|s| s.try_into().map_err(|_| crate::Error::BoundsExceeded))
1101			.collect::<Result<Vec<_>, _>>()
1102	}
1103}
1104
1105impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>> sp_npos_elections::EvaluateSupport
1106	for BoundedSupports<AccountId, BOuter, BInner>
1107{
1108	fn evaluate(&self) -> sp_npos_elections::ElectionScore {
1109		sp_npos_elections::evaluate_support(self.iter().map(|(_, s)| s))
1110	}
1111}
1112
1113impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>> sp_std::ops::DerefMut
1114	for BoundedSupports<AccountId, BOuter, BInner>
1115{
1116	fn deref_mut(&mut self) -> &mut Self::Target {
1117		&mut self.0
1118	}
1119}
1120
1121impl<AccountId: Debug, BOuter: Get<u32>, BInner: Get<u32>> Debug
1122	for BoundedSupports<AccountId, BOuter, BInner>
1123{
1124	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1125		for s in self.0.iter() {
1126			write!(f, "({:?}, {:?}, {:?}) ", s.0, s.1.total, s.1.voters)?;
1127		}
1128		Ok(())
1129	}
1130}
1131
1132impl<AccountId: PartialEq, BOuter: Get<u32>, BInner: Get<u32>> PartialEq
1133	for BoundedSupports<AccountId, BOuter, BInner>
1134{
1135	fn eq(&self, other: &Self) -> bool {
1136		self.0 == other.0
1137	}
1138}
1139
1140impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>> Into<Supports<AccountId>>
1141	for BoundedSupports<AccountId, BOuter, BInner>
1142{
1143	fn into(self) -> Supports<AccountId> {
1144		// NOTE: can be done faster with unsafe code.
1145		self.0.into_iter().map(|(acc, b_support)| (acc, b_support.into())).collect()
1146	}
1147}
1148
1149impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>>
1150	From<BoundedVec<(AccountId, BoundedSupport<AccountId, BInner>), BOuter>>
1151	for BoundedSupports<AccountId, BOuter, BInner>
1152{
1153	fn from(t: BoundedVec<(AccountId, BoundedSupport<AccountId, BInner>), BOuter>) -> Self {
1154		Self(t)
1155	}
1156}
1157
1158impl<AccountId: Clone, BOuter: Get<u32>, BInner: Get<u32>> Clone
1159	for BoundedSupports<AccountId, BOuter, BInner>
1160{
1161	fn clone(&self) -> Self {
1162		Self(self.0.clone())
1163	}
1164}
1165
1166impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>> sp_std::ops::Deref
1167	for BoundedSupports<AccountId, BOuter, BInner>
1168{
1169	type Target = BoundedVec<(AccountId, BoundedSupport<AccountId, BInner>), BOuter>;
1170
1171	fn deref(&self) -> &Self::Target {
1172		&self.0
1173	}
1174}
1175
1176impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>> IntoIterator
1177	for BoundedSupports<AccountId, BOuter, BInner>
1178{
1179	type Item = (AccountId, BoundedSupport<AccountId, BInner>);
1180	type IntoIter = sp_std::vec::IntoIter<Self::Item>;
1181
1182	fn into_iter(self) -> Self::IntoIter {
1183		self.0.into_iter()
1184	}
1185}
1186
1187impl<AccountId, BOuter: Get<u32>, BInner: Get<u32>> TryFrom<Supports<AccountId>>
1188	for BoundedSupports<AccountId, BOuter, BInner>
1189{
1190	type Error = crate::Error;
1191
1192	fn try_from(supports: Supports<AccountId>) -> Result<Self, Self::Error> {
1193		// optimization note: pre-allocate outer bounded vec.
1194		let mut outer_bounded_supports = BoundedVec::<
1195			(AccountId, BoundedSupport<AccountId, BInner>),
1196			BOuter,
1197		>::with_bounded_capacity(
1198			supports.len().min(BOuter::get() as usize)
1199		);
1200
1201		// optimization note: avoid intermediate allocations.
1202		supports
1203			.into_iter()
1204			.map(|(account, support)| (account, support.try_into().map_err(|_| ())))
1205			.try_for_each(|(account, maybe_bounded_supports)| {
1206				outer_bounded_supports
1207					.try_push((account, maybe_bounded_supports?))
1208					.map_err(|_| ())
1209			})
1210			.map_err(|_| crate::Error::BoundsExceeded)?;
1211
1212		Ok(outer_bounded_supports.into())
1213	}
1214}
1215
1216/// Same as `BoundedSupports` but parameterized by an `ElectionProvider`.
1217pub type BoundedSupportsOf<E> = BoundedSupports<
1218	<E as ElectionProvider>::AccountId,
1219	<E as ElectionProvider>::MaxWinnersPerPage,
1220	<E as ElectionProvider>::MaxBackersPerWinner,
1221>;
1222
1223sp_core::generate_feature_enabled_macro!(
1224	runtime_benchmarks_enabled,
1225	feature = "runtime-benchmarks",
1226	$
1227);
1228
1229sp_core::generate_feature_enabled_macro!(
1230	runtime_benchmarks_or_std_enabled,
1231	any(feature = "runtime-benchmarks", feature = "std"),
1232	$
1233);