This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Multi-block election part 0: Paginated election data provider #11105
Closed
kianenigma
wants to merge
28
commits into
master
from
kiz-multi-election-pt0-paginated-data-provider
Closed
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
500bc9d
Implement the new validator-in-bags-list scenario + migration
kianenigma ddcc81b
Apply suggestions from code review
kianenigma 41540f2
some review comments
kianenigma 8ba2563
Merge branch 'kiz-validators-in-bags' of github.com:paritytech/substr…
kianenigma c293a0c
Merge branch 'master' of github.com:paritytech/substrate into kiz-val…
kianenigma 398cf70
guard the migration
kianenigma 66fc7d2
some review comments
kianenigma 75989de
Fix tests 🤦♂️
kianenigma db2a7b8
Fix build
kianenigma 8f74872
Merge branch 'master' of github.com:paritytech/substrate into kiz-val…
kianenigma 7a55fad
Master.into()
kianenigma 1ac8c34
Master.into()
kianenigma 0ce73d5
Merge branch 'master' of github.com:paritytech/substrate into kiz-val…
kianenigma f892d04
fix weight_of_fn
kianenigma 5640da7
reformat line width
kianenigma 3aefa00
make const
kianenigma 0923d5b
use weight of fn cached
kianenigma 2ea0769
SortedListProvider -> VoterList
kianenigma 4c9ef4b
Fix all build and docs
kianenigma b311d03
check post migration
kianenigma 2b2ff9b
Master.into()
kianenigma 8dcc94c
get everything going
kianenigma 288848c
Master.into()
kianenigma fb556a0
Master.into()
kianenigma 0d8b1b3
a good round of self-review
kianenigma 56b02c6
remote tests
kianenigma bc5ca19
fix
kianenigma 5ad46cc
remove todos
kianenigma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -103,16 +103,17 @@ | |||||||||
//! type AccountId = AccountId; | ||||||||||
//! type BlockNumber = BlockNumber; | ||||||||||
//! type MaxVotesPerVoter = ConstU32<1>; | ||||||||||
//! type Pages = ConstU32<1>; | ||||||||||
//! | ||||||||||
//! fn desired_targets() -> data_provider::Result<u32> { | ||||||||||
//! Ok(1) | ||||||||||
//! } | ||||||||||
//! fn electing_voters(maybe_max_len: Option<usize>) | ||||||||||
//! fn electing_voters_paged(maybe_max_len: Option<usize>, _: PageIndex) | ||||||||||
//! -> data_provider::Result<Vec<VoterOf<Self>>> | ||||||||||
//! { | ||||||||||
//! Ok(Default::default()) | ||||||||||
//! } | ||||||||||
//! fn electable_targets(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<AccountId>> { | ||||||||||
//! fn electable_targets_paged(maybe_max_len: Option<usize>, _: PageIndex) -> data_provider::Result<Vec<AccountId>> { | ||||||||||
//! Ok(vec![10, 20, 30]) | ||||||||||
//! } | ||||||||||
//! fn next_election_prediction(now: BlockNumber) -> BlockNumber { | ||||||||||
|
@@ -170,13 +171,14 @@ pub mod onchain; | |||||||||
pub mod traits; | ||||||||||
#[cfg(feature = "std")] | ||||||||||
use codec::{Decode, Encode}; | ||||||||||
use frame_support::{weights::Weight, BoundedVec, RuntimeDebug}; | ||||||||||
use frame_support::{traits::DefensiveSaturating, weights::Weight, BoundedVec, RuntimeDebug}; | ||||||||||
use sp_runtime::traits::Bounded; | ||||||||||
use sp_std::{fmt::Debug, prelude::*}; | ||||||||||
|
||||||||||
/// Re-export the solution generation macro. | ||||||||||
pub use frame_election_provider_solution_type::generate_solution_type; | ||||||||||
pub use frame_support::traits::Get; | ||||||||||
|
||||||||||
/// Re-export some type as they are used in the interface. | ||||||||||
pub use sp_arithmetic::PerThing; | ||||||||||
pub use sp_npos_elections::{ | ||||||||||
|
@@ -185,6 +187,13 @@ pub use sp_npos_elections::{ | |||||||||
}; | ||||||||||
pub use traits::NposSolution; | ||||||||||
|
||||||||||
/// The index used to indicate the page number. | ||||||||||
/// | ||||||||||
/// A u8 would have probably been enough until the end of universe, but since we use this as the | ||||||||||
/// bound of `BoundedVec` and similar, using `u32` will save us some hassle. | ||||||||||
// TODO: https://github.com/paritytech/substrate/issues/11076 | ||||||||||
pub type PageIndex = u32; | ||||||||||
|
||||||||||
// re-export for the solution macro, with the dependencies of the macro. | ||||||||||
#[doc(hidden)] | ||||||||||
pub use codec; | ||||||||||
|
@@ -275,6 +284,12 @@ pub trait ElectionDataProvider { | |||||||||
/// Maximum number of votes per voter that this data provider is providing. | ||||||||||
type MaxVotesPerVoter: Get<u32>; | ||||||||||
|
||||||||||
/// The maximum number of pages that this data provider is expected to be able to provide. An | ||||||||||
/// implementation could use this to verify the value of `remaining: PageIndex`. | ||||||||||
// NOTE: this should maybe be a generic, because a single type might want implement it with | ||||||||||
// different bounds. | ||||||||||
type Pages: Get<PageIndex>; | ||||||||||
|
||||||||||
/// All possible targets for the election, i.e. the targets that could become elected, thus | ||||||||||
/// "electable". | ||||||||||
/// | ||||||||||
|
@@ -283,8 +298,9 @@ pub trait ElectionDataProvider { | |||||||||
/// | ||||||||||
/// This should be implemented as a self-weighing function. The implementor should register its | ||||||||||
/// appropriate weight at the end of execution with the system pallet directly. | ||||||||||
fn electable_targets( | ||||||||||
fn electable_targets_paged( | ||||||||||
maybe_max_len: Option<usize>, | ||||||||||
remaining_pages: PageIndex, | ||||||||||
) -> data_provider::Result<Vec<Self::AccountId>>; | ||||||||||
|
||||||||||
/// All the voters that participate in the election, thus "electing". | ||||||||||
|
@@ -296,7 +312,27 @@ pub trait ElectionDataProvider { | |||||||||
/// | ||||||||||
/// This should be implemented as a self-weighing function. The implementor should register its | ||||||||||
/// appropriate weight at the end of execution with the system pallet directly. | ||||||||||
fn electing_voters(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<VoterOf<Self>>>; | ||||||||||
fn electing_voters_paged( | ||||||||||
maybe_max_len: Option<usize>, | ||||||||||
remaining_pages: PageIndex, | ||||||||||
) -> data_provider::Result<Vec<VoterOf<Self>>>; | ||||||||||
|
||||||||||
/// Same as [`Self::electable_targets_paged`], but the most significant page is assumed. | ||||||||||
/// | ||||||||||
/// This should almost only be used in the case where `Self::Pages` is `1`. | ||||||||||
fn electable_targets( | ||||||||||
maybe_max_len: Option<usize>, | ||||||||||
) -> data_provider::Result<Vec<Self::AccountId>> { | ||||||||||
Self::electable_targets_paged(maybe_max_len, Self::msp()) | ||||||||||
} | ||||||||||
|
||||||||||
/// Same as [`Self::electing_voters_paged`], but the page 0 is assumed. | ||||||||||
/// | ||||||||||
/// | ||||||||||
/// This should almost only be used in the case where `Self::Pages` is `1`. | ||||||||||
fn electing_voters(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<VoterOf<Self>>> { | ||||||||||
Self::electing_voters_paged(maybe_max_len, Self::msp()) | ||||||||||
} | ||||||||||
|
||||||||||
/// The number of targets to elect. | ||||||||||
/// | ||||||||||
|
@@ -306,8 +342,6 @@ pub trait ElectionDataProvider { | |||||||||
/// A sensible implementation should use the minimum between this value and | ||||||||||
/// [`Self::targets().len()`], since desiring a winner set larger than candidates is not | ||||||||||
/// feasible. | ||||||||||
/// | ||||||||||
/// This is documented further in issue: <https://github.com/paritytech/substrate/issues/9478> | ||||||||||
fn desired_targets() -> data_provider::Result<u32>; | ||||||||||
|
||||||||||
/// Provide a best effort prediction about when the next election is about to happen. | ||||||||||
|
@@ -318,8 +352,28 @@ pub trait ElectionDataProvider { | |||||||||
/// This is only useful for stateful election providers. | ||||||||||
fn next_election_prediction(now: Self::BlockNumber) -> Self::BlockNumber; | ||||||||||
|
||||||||||
/// Shorthand for "most significant page". | ||||||||||
/// | ||||||||||
/// The least significant, aka "first" page that this election provider is expected to receive. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Suggested change
|
||||||||||
fn msp() -> PageIndex { | ||||||||||
Self::Pages::get().defensive_saturating_sub(1) | ||||||||||
} | ||||||||||
|
||||||||||
/// Shorthand for "least significant page". | ||||||||||
/// | ||||||||||
/// The most significant, aka "first" page that this election provider is expected to receive. | ||||||||||
fn lsp() -> PageIndex { | ||||||||||
0 | ||||||||||
} | ||||||||||
|
||||||||||
/// The range of `take` pages, from most significant to least significant. | ||||||||||
fn range(take: PageIndex) -> Box<dyn Iterator<Item = PageIndex>> { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why use trait object? Can we just return the concrete type and save the v table look up? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why use trait object? Can we just return the concrete type and save the v table look up? |
||||||||||
Box::new((Self::lsp()..Self::Pages::get()).take(take as usize).rev()) | ||||||||||
} | ||||||||||
|
||||||||||
/// Utility function only to be used in benchmarking scenarios, to be implemented optionally, | ||||||||||
/// else a noop. | ||||||||||
|
||||||||||
#[cfg(any(feature = "runtime-benchmarks", test))] | ||||||||||
fn put_snapshot( | ||||||||||
_voters: Vec<VoterOf<Self>>, | ||||||||||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.