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