Use proper bounded vector type for nominations (#10601)

* Use proper bounded vector type for nominations

* add docs and tweak chill_other for cleanup purposes

* Fix the build

* remove TODO

* add a bit more doc

* even more docs
gushc

* Update frame/staking/src/pallet/mod.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* Update frame/staking/src/pallet/mod.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* Fix the nasty bug

* also bound the Snapshot type

* fix doc test

* document bounded_vec

* self-review

* remove unused

* Fix build

* frame-support: repetition overload for bounded_vec

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fix

* remove the need to allocate into unbounded voters etc etc

* Don't expect

* unbreal the build again

* handle macro a bit better

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
Kian Paimani
2022-01-25 15:44:10 +01:00
committed by GitHub
parent d94b5e32c5
commit 38d94d6323
34 changed files with 419 additions and 252 deletions
@@ -22,11 +22,12 @@ use frame_election_provider_support::{
};
pub use frame_support::{assert_noop, assert_ok};
use frame_support::{
parameter_types,
bounded_vec, parameter_types,
traits::{ConstU32, Hooks},
weights::Weight,
BoundedVec,
};
use multi_phase::unsigned::{IndexAssignmentOf, Voter};
use multi_phase::unsigned::{IndexAssignmentOf, VoterOf};
use parking_lot::RwLock;
use sp_core::{
offchain::{
@@ -100,7 +101,7 @@ pub fn roll_to_with_ocw(n: BlockNumber) {
}
pub struct TrimHelpers {
pub voters: Vec<Voter<Runtime>>,
pub voters: Vec<VoterOf<Runtime>>,
pub assignments: Vec<IndexAssignmentOf<Runtime>>,
pub encoded_size_of:
Box<dyn Fn(&[IndexAssignmentOf<Runtime>]) -> Result<usize, sp_npos_elections::Error>>,
@@ -131,13 +132,8 @@ pub fn trim_helpers() -> TrimHelpers {
let desired_targets = MultiPhase::desired_targets().unwrap();
let ElectionResult { mut assignments, .. } = seq_phragmen::<_, SolutionAccuracyOf<Runtime>>(
desired_targets as usize,
targets.clone(),
voters.clone(),
None,
)
.unwrap();
let ElectionResult::<_, SolutionAccuracyOf<Runtime>> { mut assignments, .. } =
seq_phragmen(desired_targets as usize, targets.clone(), voters.clone(), None).unwrap();
// sort by decreasing order of stake
assignments.sort_unstable_by_key(|assignment| {
@@ -163,14 +159,8 @@ pub fn raw_solution() -> RawSolution<SolutionOf<Runtime>> {
let RoundSnapshot { voters, targets } = MultiPhase::snapshot().unwrap();
let desired_targets = MultiPhase::desired_targets().unwrap();
let ElectionResult { winners: _, assignments } =
seq_phragmen::<_, SolutionAccuracyOf<Runtime>>(
desired_targets as usize,
targets.clone(),
voters.clone(),
None,
)
.unwrap();
let ElectionResult::<_, SolutionAccuracyOf<Runtime>> { winners: _, assignments } =
seq_phragmen(desired_targets as usize, targets.clone(), voters.clone(), None).unwrap();
// closures
let cache = helpers::generate_voter_cache::<Runtime>(&voters);
@@ -246,16 +236,16 @@ impl pallet_balances::Config for Runtime {
parameter_types! {
pub static Targets: Vec<AccountId> = vec![10, 20, 30, 40];
pub static Voters: Vec<(AccountId, VoteWeight, Vec<AccountId>)> = vec![
(1, 10, vec![10, 20]),
(2, 10, vec![30, 40]),
(3, 10, vec![40]),
(4, 10, vec![10, 20, 30, 40]),
pub static Voters: Vec<VoterOf<Runtime>> = vec![
(1, 10, bounded_vec![10, 20]),
(2, 10, bounded_vec![30, 40]),
(3, 10, bounded_vec![40]),
(4, 10, bounded_vec![10, 20, 30, 40]),
// self votes.
(10, 10, vec![10]),
(20, 20, vec![20]),
(30, 30, vec![30]),
(40, 40, vec![40]),
(10, 10, bounded_vec![10]),
(20, 20, bounded_vec![20]),
(30, 30, bounded_vec![30]),
(40, 40, bounded_vec![40]),
];
pub static DesiredTargets: u32 = 2;
@@ -436,6 +426,10 @@ where
pub type Extrinsic = sp_runtime::testing::TestXt<Call, ()>;
parameter_types! {
pub MaxNominations: u32 = <TestNposSolution as NposSolution>::LIMIT as u32;
}
#[derive(Default)]
pub struct ExtBuilder {}
@@ -443,7 +437,7 @@ pub struct StakingMock;
impl ElectionDataProvider for StakingMock {
type AccountId = AccountId;
type BlockNumber = u64;
const MAXIMUM_VOTES_PER_VOTER: u32 = <TestNposSolution as NposSolution>::LIMIT as u32;
type MaxVotesPerVoter = MaxNominations;
fn targets(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<AccountId>> {
let targets = Targets::get();
@@ -454,9 +448,7 @@ impl ElectionDataProvider for StakingMock {
Ok(targets)
}
fn voters(
maybe_max_len: Option<usize>,
) -> data_provider::Result<Vec<(AccountId, VoteWeight, Vec<AccountId>)>> {
fn voters(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<VoterOf<Runtime>>> {
let mut voters = Voters::get();
if let Some(max_len) = maybe_max_len {
voters.truncate(max_len)
@@ -475,7 +467,7 @@ impl ElectionDataProvider for StakingMock {
#[cfg(feature = "runtime-benchmarks")]
fn put_snapshot(
voters: Vec<(AccountId, VoteWeight, Vec<AccountId>)>,
voters: Vec<VoterOf<Runtime>>,
targets: Vec<AccountId>,
_target_stake: Option<VoteWeight>,
) {
@@ -490,7 +482,11 @@ impl ElectionDataProvider for StakingMock {
}
#[cfg(feature = "runtime-benchmarks")]
fn add_voter(voter: AccountId, weight: VoteWeight, targets: Vec<AccountId>) {
fn add_voter(
voter: AccountId,
weight: VoteWeight,
targets: frame_support::BoundedVec<AccountId, Self::MaxVotesPerVoter>,
) {
let mut current = Voters::get();
current.push((voter, weight, targets));
Voters::set(current);
@@ -505,7 +501,7 @@ impl ElectionDataProvider for StakingMock {
// to be on-par with staking, we add a self vote as well. the stake is really not that
// important.
let mut current = Voters::get();
current.push((target, ExistentialDeposit::get() as u64, vec![target]));
current.push((target, ExistentialDeposit::get() as u64, bounded_vec![target]));
Voters::set(current);
}
}
@@ -540,7 +536,12 @@ impl ExtBuilder {
<DesiredTargets>::set(t);
self
}
pub fn add_voter(self, who: AccountId, stake: Balance, targets: Vec<AccountId>) -> Self {
pub fn add_voter(
self,
who: AccountId,
stake: Balance,
targets: BoundedVec<AccountId, MaxNominations>,
) -> Self {
VOTERS.with(|v| v.borrow_mut().push((who, stake, targets)));
self
}