Skip to content

Commit

Permalink
[Staking] Split candidate state for PoV optimization (#1117)
Browse files Browse the repository at this point in the history
* join candidates leave candidates go online offline

* wip

* still wip on delegation changes

* in progress much more complicated now because of the necessity of maintaining Total storage item and im unsure we need it

* add highest bottom delegation amount to candidate metadata and start increase and decrease delegations

* edge cases

* complete impl still needs tests

* impl more efficient candidate snapshot

* passing unit pallet units but need to update migration unit test

* fix some benchmark and save start migration

* migration impl with minimal pre post checks

* more tests and make all bound checks more strict

* patch sorted insertion bug to enforce first come first serve for delegations with same amount

* patch patch

* update configs and need to update the migration

* fix migration to work if old bottom delegations len is greater than the configured max bottom delegations per candidate

* save

* update parachain staking precompile

* fmt

* fix 1 of 4 migration tests

* wip last migration test

* complete migration testing of revocation and exit delegator paths

* update TS test

* update most weights

* update round transition on initialize

* fix TS test

* replace unstable sorts with stable sorts

* set max bottom delegations per candidate to 50

* insert highest bottom into top when removing a top delegation

* address most comments

* update benchmarking code and add weight hint unit test for execute leave candidates

* update only benchmarks that changed a lot relative to existing weights

* address most review comments

* address edge case and fix comments
  • Loading branch information
4meta5 authored Jan 26, 2022
1 parent fed025b commit 5e62387
Show file tree
Hide file tree
Showing 13 changed files with 3,626 additions and 1,340 deletions.
38 changes: 21 additions & 17 deletions pallets/parachain-staking/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ const USER_SEED: u32 = 999666;
benchmarks! {
// HOTFIX BENCHMARK
hotfix_remove_delegation_requests {
let x in 5..200;
let x in 2..<<T as Config>::MaxTopDelegationsPerCandidate as Get<u32>>::get()
+ <<T as Config>::MaxBottomDelegationsPerCandidate as Get<u32>>::get();
let mut delegators: Vec<T::AccountId> = Vec::new();
let collator = create_funded_collator::<T>(
"candidate",
Expand Down Expand Up @@ -207,7 +208,9 @@ benchmarks! {

// ROOT DISPATCHABLES

set_total_selected {}: _(RawOrigin::Root, 100u32)
set_total_selected {
Pallet::<T>::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?;
}: _(RawOrigin::Root, 100u32)
verify {
assert_eq!(Pallet::<T>::total_selected(), 100u32);
}
Expand Down Expand Up @@ -272,12 +275,13 @@ benchmarks! {
candidate_count += 1u32;
}: _(RawOrigin::Signed(caller.clone()), candidate_count)
verify {
assert!(Pallet::<T>::candidate_state(&caller).unwrap().is_leaving());
assert!(Pallet::<T>::candidate_info(&caller).unwrap().is_leaving());
}

execute_leave_candidates {
// x is total number of delegations for the candidate
let x in 2..310;
let x in 2..(<<T as Config>::MaxTopDelegationsPerCandidate as Get<u32>>::get()
+ <<T as Config>::MaxBottomDelegationsPerCandidate as Get<u32>>::get());
let candidate: T::AccountId = create_funded_collator::<T>(
"unique_caller",
USER_SEED - 100,
Expand Down Expand Up @@ -326,8 +330,8 @@ benchmarks! {
roll_to_and_author::<T>(2, candidate.clone());
}: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count)
verify {
assert!(Pallet::<T>::candidate_state(&candidate).is_none());
assert!(Pallet::<T>::candidate_state(&second_candidate).is_some());
assert!(Pallet::<T>::candidate_info(&candidate).is_none());
assert!(Pallet::<T>::candidate_info(&second_candidate).is_some());
for delegator in delegators {
assert!(Pallet::<T>::is_delegator(&delegator));
}
Expand Down Expand Up @@ -363,7 +367,7 @@ benchmarks! {
candidate_count -= 1u32;
}: _(RawOrigin::Signed(caller.clone()), candidate_count)
verify {
assert!(Pallet::<T>::candidate_state(&caller).unwrap().is_active());
assert!(Pallet::<T>::candidate_info(&caller).unwrap().is_active());
}

go_offline {
Expand All @@ -376,7 +380,7 @@ benchmarks! {
)?;
}: _(RawOrigin::Signed(caller.clone()))
verify {
assert!(!Pallet::<T>::candidate_state(&caller).unwrap().is_active());
assert!(!Pallet::<T>::candidate_info(&caller).unwrap().is_active());
}

go_online {
Expand All @@ -390,7 +394,7 @@ benchmarks! {
Pallet::<T>::go_offline(RawOrigin::Signed(caller.clone()).into())?;
}: _(RawOrigin::Signed(caller.clone()))
verify {
assert!(Pallet::<T>::candidate_state(&caller).unwrap().is_active());
assert!(Pallet::<T>::candidate_info(&caller).unwrap().is_active());
}

candidate_bond_more {
Expand Down Expand Up @@ -419,7 +423,7 @@ benchmarks! {
)?;
}: _(RawOrigin::Signed(caller.clone()), min_candidate_stk)
verify {
let state = Pallet::<T>::candidate_state(&caller).expect("request bonded less so exists");
let state = Pallet::<T>::candidate_info(&caller).expect("request bonded less so exists");
assert_eq!(
state.request,
Some(CandidateBondLessRequest {
Expand Down Expand Up @@ -471,13 +475,13 @@ benchmarks! {
)?;
} verify {
assert!(
Pallet::<T>::candidate_state(&caller).unwrap().request.is_none()
Pallet::<T>::candidate_info(&caller).unwrap().request.is_none()
);
}

delegate {
let x in 3..<<T as Config>::MaxDelegationsPerDelegator as Get<u32>>::get();
let y in 2..<<T as Config>::MaxDelegatorsPerCandidate as Get<u32>>::get();
let y in 2..<<T as Config>::MaxTopDelegationsPerCandidate as Get<u32>>::get();
// Worst Case is full of delegations before calling `delegate`
let mut collators: Vec<T::AccountId> = Vec::new();
// Initialize MaxDelegationsPerDelegator collator candidates
Expand Down Expand Up @@ -856,9 +860,9 @@ benchmarks! {
// TOTAL SELECTED COLLATORS PER ROUND
let x in 1..28;
// DELEGATIONS
let y in 0..(<<T as Config>::MaxDelegatorsPerCandidate as Get<u32>>::get() * 28);
let y in 0..(<<T as Config>::MaxTopDelegationsPerCandidate as Get<u32>>::get() * 28);
let max_delegators_per_collator =
<<T as Config>::MaxDelegatorsPerCandidate as Get<u32>>::get();
<<T as Config>::MaxTopDelegationsPerCandidate as Get<u32>>::get();
let max_delegations = x * max_delegators_per_collator;
// y should depend on x but cannot directly, we overwrite y here if necessary to bound it
let total_delegations: u32 = if max_delegations < y { max_delegations } else { y };
Expand Down Expand Up @@ -930,7 +934,7 @@ benchmarks! {
if remaining_delegations > 0 {
for (col, n_count) in col_del_count.iter_mut() {
if n_count < &mut (delegators.len() as u32) {
// assumes delegators.len() <= MaxDelegatorsPerCandidate
// assumes delegators.len() <= MaxTopDelegationsPerCandidate
let mut open_spots = delegators.len() as u32 - *n_count;
while open_spots > 0 && remaining_delegations > 0 {
let caller = delegators[open_spots as usize - 1usize].clone();
Expand Down Expand Up @@ -999,9 +1003,9 @@ benchmarks! {

pay_one_collator_reward {
// y controls number of delegators
// TODO: mock.rs sets MaxDelegatorsPerCandidate to 4, which is too low for this test to be
// TODO: mock.rs sets MaxTopDelegationsPerCandidate to 4, which is too low for this test to be
// meaningful. we use a higher value here, which works so long as we don't invoke any of
// pallet_staking's logic which uses MaxDelegatorsPerCandidate as a constraint. this is
// pallet_staking's logic which uses MaxTopDelegationsPerCandidate as a constraint. this is
// brittle, to say the least...
let y in 0..2000;

Expand Down
Loading

0 comments on commit 5e62387

Please sign in to comment.