Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
500bc9d
Implement the new validator-in-bags-list scenario + migration
kianenigma Feb 8, 2022
ddcc81b
Apply suggestions from code review
kianenigma Feb 15, 2022
41540f2
some review comments
kianenigma Feb 15, 2022
8ba2563
Merge branch 'kiz-validators-in-bags' of github.com:paritytech/substr…
kianenigma Feb 15, 2022
c293a0c
Merge branch 'master' of github.com:paritytech/substrate into kiz-val…
kianenigma Feb 16, 2022
398cf70
guard the migration
kianenigma Feb 16, 2022
66fc7d2
some review comments
kianenigma Feb 16, 2022
75989de
Fix tests 🤦‍♂️
kianenigma Feb 16, 2022
db2a7b8
Fix build
kianenigma Feb 16, 2022
53561cb
Merge branch 'kiz-validators-in-bags' of github.com:paritytech/substr…
kianenigma Feb 28, 2022
18fb2f4
lay the groundwork to store validators in a bags-list instance
kianenigma Feb 28, 2022
ae8165f
add migration struct
kianenigma Feb 28, 2022
3e0a25d
make node-runtime build fine
kianenigma Feb 28, 2022
8f74872
Merge branch 'master' of github.com:paritytech/substrate into kiz-val…
kianenigma Feb 28, 2022
ac6473b
Merge branch 'master' of github.com:paritytech/substrate into kiz-rev…
kianenigma Feb 28, 2022
5c48b57
make instantiable
Doordashcon Mar 1, 2022
90d09f2
update
Doordashcon Mar 4, 2022
7d6cb8d
cargo fmt
Doordashcon Mar 4, 2022
0304977
Merge branch 'paritytech:master' into ddc-BPL-T1
Doordashcon Mar 4, 2022
dc7bd89
Most things work now
kianenigma Mar 8, 2022
7a55fad
Master.into()
kianenigma Mar 8, 2022
44d1281
Upstream.into()
kianenigma Mar 8, 2022
b3f93c5
most things wokr now
kianenigma Mar 9, 2022
1ac8c34
Master.into()
kianenigma Mar 9, 2022
8cdd144
Everything merged, tests need a lot of fixing
kianenigma Mar 10, 2022
700141e
All tests work now
kianenigma Mar 10, 2022
93d79a4
dead-end with restricted nominations
kianenigma Mar 11, 2022
2f295b7
dead-end with restricted nominations
kianenigma Mar 11, 2022
29071fc
most tests work again
kianenigma Mar 11, 2022
34b1d8a
use balance as the type for TargetList
kianenigma Mar 11, 2022
8a431dd
a little bit of self-review
kianenigma Mar 11, 2022
0ce73d5
Merge branch 'master' of github.com:paritytech/substrate into kiz-val…
kianenigma Mar 11, 2022
f892d04
fix weight_of_fn
kianenigma Mar 11, 2022
5640da7
reformat line width
kianenigma Mar 11, 2022
3aefa00
make const
kianenigma Mar 11, 2022
0923d5b
use weight of fn cached
kianenigma Mar 11, 2022
2ea0769
SortedListProvider -> VoterList
kianenigma Mar 11, 2022
4c9ef4b
Fix all build and docs
kianenigma Mar 11, 2022
b311d03
check post migration
kianenigma Mar 11, 2022
a4bbda1
better doc
kianenigma Mar 11, 2022
4c275a6
Upstream.into()
kianenigma Mar 11, 2022
19bd4cd
mostly stable and working stuff
kianenigma Mar 11, 2022
bfe5d2a
Master.into()
kianenigma Mar 25, 2022
43cec35
some fixes to make node-runtime work
kianenigma Mar 25, 2022
0d395bb
Master.into()
kianenigma Apr 13, 2022
0c8a891
Update frame/bags-list/src/list/mod.rs
kianenigma Apr 19, 2022
dbae8a5
small fixes + add an important TODO about a potential leftover bug
kianenigma May 1, 2022
96948e0
Merge branch 'kiz-revamp-sorted-list-providers-2-approval-stake' of g…
kianenigma May 1, 2022
7837d07
Master.into()
kianenigma May 1, 2022
cc7ee91
Fix a few things in the bags-list pallet
kianenigma May 1, 2022
a10ff10
cleanup a few things
kianenigma May 3, 2022
488362c
Merge branch 'master' into kiz-revamp-sorted-list-providers-2-approva…
shawntabrizi May 3, 2022
10a7ced
Update frame/staking/src/pallet/impls.rs
shawntabrizi May 3, 2022
20bc48e
Update frame/bags-list/src/list/tests.rs
shawntabrizi May 3, 2022
4e7821d
Fix everything build related
kianenigma May 3, 2022
b3ac3c4
Merge branch 'kiz-revamp-sorted-list-providers-2-approval-stake' of g…
kianenigma May 3, 2022
3381b4c
Update frame/staking/src/pallet/mod.rs
kianenigma May 3, 2022
b3aeb44
some feedback
kianenigma May 3, 2022
3258cc4
Merge branch 'kiz-revamp-sorted-list-providers-2-approval-stake' of g…
kianenigma May 3, 2022
d60d2ab
some review feedback
kianenigma May 3, 2022
8e54545
fix compile
shawntabrizi May 3, 2022
f93563f
Merge branch 'master' into kiz-revamp-sorted-list-providers-2-approva…
shawntabrizi May 4, 2022
518ffb3
fix warning
shawntabrizi May 4, 2022
8457800
Merge branch 'master' into kiz-revamp-sorted-list-providers-2-approva…
shawntabrizi Jul 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
dead-end with restricted nominations
  • Loading branch information
kianenigma committed Mar 11, 2022
commit 93d79a4539fc853f966caba6571ef26657cfaad0
17 changes: 9 additions & 8 deletions frame/staking/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,21 @@ impl<T: Config> InjectValidatorsApprovalStakeIntoTargetList<T> {
pub(crate) fn build_approval_stakes() -> BTreeMap<T::AccountId, VoteWeight> {
let mut approval_stakes = BTreeMap::<T::AccountId, VoteWeight>::new();

NominatorsHelper::<T>::iter_all().for_each(|(who, nomination)| {
let stake = Pallet::<T>::weight_of(&who);
for target in nomination.targets {
let current = approval_stakes.entry(target).or_default();
*current = current.saturating_add(stake);
}
});

Validators::<T>::iter().for_each(|(v, _)| {
let stake = Pallet::<T>::weight_of(&v);
let current = approval_stakes.entry(v).or_default();
*current = current.saturating_add(stake);
});

NominatorsHelper::<T>::iter_all().for_each(|(who, nomination)| {
let stake = Pallet::<T>::weight_of(&who);
for target in nomination.targets {
if let Some(current) = approval_stakes.get_mut(&target) {
*current = current.saturating_add(stake);
}
}
});

approval_stakes
}
}
Expand Down
26 changes: 19 additions & 7 deletions frame/staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,13 +820,6 @@ pub(crate) fn reward_all_elected() {
<Pallet<Test>>::reward_by_ids(rewards)
}

pub(crate) fn validator_controllers() -> Vec<AccountId> {
Session::validators()
.into_iter()
.map(|s| Staking::bonded(&s).expect("no controller for validator"))
.collect()
}

pub(crate) fn on_offence_in_era(
offenders: &[OffenceDetails<
AccountId,
Expand Down Expand Up @@ -925,3 +918,22 @@ pub(crate) fn staking_events() -> Vec<crate::Event<Test>> {
pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) {
(Balances::free_balance(who), Balances::reserved_balance(who))
}

pub(crate) fn validator_ids() -> Vec<AccountId> {
Validators::<Test>::iter().map(|(v, _)| v).collect::<Vec<_>>()
}

pub(crate) fn nominator_ids() -> Vec<AccountId> {
Nominators::<Test>::iter().map(|(n, _)| n).collect::<Vec<_>>()
}

pub(crate) fn nominator_targets(who: AccountId) -> Vec<AccountId> {
Nominators::<Test>::get(&who).map(|n| n.targets).unwrap().into_inner()
}

pub(crate) fn validator_controllers() -> Vec<AccountId> {
Session::validators()
.into_iter()
.map(|s| Staking::bonded(&s).expect("no controller for validator"))
.collect()
}
90 changes: 68 additions & 22 deletions frame/staking/src/pallet/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,22 +212,18 @@ impl<T: Config> Pallet<T> {
<Ledger<T>>::insert(controller, ledger);

let total_issuance = T::Currency::total_issuance();
let apply_change = |who: &T::AccountId| {
let to_vote = |x| T::CurrencyToVote::to_vote(x, total_issuance);

let update_target_list = |who: &T::AccountId| {
use sp_std::cmp::Ordering;
match ledger.active.cmp(&prev_active) {
Ordering::Greater => {
let _ = T::TargetList::on_increase(
who,
T::CurrencyToVote::to_vote(ledger.active - prev_active, total_issuance),
)
.defensive();
let _ = T::TargetList::on_increase(who, to_vote(ledger.active - prev_active))
.defensive();
},
Ordering::Less => {
let _ = T::TargetList::on_decrease(
who,
T::CurrencyToVote::to_vote(prev_active - ledger.active, total_issuance),
)
.defensive();
let _ = T::TargetList::on_decrease(who, to_vote(prev_active - ledger.active))
.defensive();
},
Ordering::Equal => (),
};
Expand All @@ -237,16 +233,26 @@ impl<T: Config> Pallet<T> {
if let Some(targets) =
NominatorsHelper::<T>::get_any(&ledger.stash).map(|nomination| nomination.targets)
{
// update the target list.
for target in targets {
apply_change(&target);
update_target_list(&target);
}

// update the voter list.
let _ = T::VoterList::on_update(&ledger.stash, to_vote(ledger.active))
.defensive_proof("any nominator should an entry in the voter list.");

#[cfg(debug_assertions)]
Self::sanity_check_list_providers();
}

// if this ledger belonged to a validator..
if Validators::<T>::contains_key(&ledger.stash) {
apply_change(&ledger.stash);
update_target_list(&ledger.stash);

let _ = T::VoterList::on_update(&ledger.stash, to_vote(ledger.active))
.defensive_proof("any validator should an entry in the voter list.");

#[cfg(debug_assertions)]
Self::sanity_check_list_providers();
}
Expand All @@ -259,6 +265,9 @@ impl<T: Config> Pallet<T> {
if chilled_as_validator || chilled_as_nominator {
Self::deposit_event(Event::<T>::Chilled(stash.clone()));
}

#[cfg(debug_assertions)]
Self::sanity_check_approval_stakes();
}

/// Actually make a payment to a staker. This uses the currency's reward function
Expand Down Expand Up @@ -610,6 +619,9 @@ impl<T: Config> Pallet<T> {
Self::do_remove_validator(stash);
Self::do_remove_nominator(stash);

#[cfg(debug_assertions)]
Self::sanity_check_approval_stakes();

<Bonded<T>>::remove(stash);
<Ledger<T>>::remove(&controller);
<Payee<T>>::remove(stash);
Expand Down Expand Up @@ -808,13 +820,42 @@ impl<T: Config> Pallet<T> {
/// NOTE: you must ALWAYS use this function to add nominator or update their targets. Any access
/// to `Nominators` or `VoterList` outside of this function is almost certainly
/// wrong.
pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations<T>) {
if !NominatorsHelper::<T>::contains_any(who) {
pub fn do_add_nominator(
stash: &T::AccountId,
old: Vec<T::AccountId>,
nominations: Nominations<T>,
) {
if !NominatorsHelper::<T>::contains_any(stash) {
// maybe update sorted list.
let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who))
.defensive_unwrap_or_default();
let _ = T::VoterList::on_insert(stash.clone(), Self::weight_of(stash)).defensive();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting that we must ensure the account is removed as a validator prior to being added as a nominator. otherwise this would be a second insert of an account that already was added to the list as a nominator

}
Nominators::<T>::insert(who, nominations);

let incoming = nominations.targets.iter().filter(|x| !old.contains(x)).collect::<Vec<_>>();
let outgoing =
old.into_iter().filter(|x| !nominations.targets.contains(x)).collect::<Vec<_>>();

// TODO: edge case: some wanker nominating themselves? should only be possible if they are a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to just add this as a condition to the above filters

// validator and now they nominate themselves.
// TODO: these are all rather inefficient now based on how vote_weight is
// implemented, but I don't care because: https://github.com/paritytech/substrate/issues/10990
let weight = Self::weight_of(stash);
incoming.into_iter().for_each(|i| {
if T::TargetList::contains(i) {
let _ = T::TargetList::on_increase(i, weight).defensive();
} else {
defensive!("no incoming target can not have an entry in the target-list");
}
});
outgoing.into_iter().for_each(|o| {
if T::TargetList::contains(&o) {
let _ = T::TargetList::on_decrease(&o, weight);
} else {
// probably the validator has already been chilled and their target list entry
// removed.
}
});

Nominators::<T>::insert(stash, nominations);

#[cfg(debug_assertions)]
Self::sanity_check_list_providers();
Expand Down Expand Up @@ -861,8 +902,7 @@ impl<T: Config> Pallet<T> {
pub fn do_add_validator(who: &T::AccountId, prefs: ValidatorPrefs) {
if !Validators::<T>::contains_key(who) {
// maybe update sorted list.
let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who))
.defensive_unwrap_or_default();
let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who)).defensive();

if T::TargetList::contains(who) {
let _ = T::TargetList::on_increase(who, Self::weight_of(who)).defensive();
Expand Down Expand Up @@ -890,7 +930,8 @@ impl<T: Config> Pallet<T> {
let outcome = if Validators::<T>::contains_key(who) {
Validators::<T>::remove(who);
let _ = T::VoterList::on_remove(who).defensive();
let _ = T::TargetList::on_decrease(who, Self::weight_of(who)).defensive();
// NOTE: simply remove, not decrease.
let _ = T::TargetList::on_remove(who).defensive();
true
} else {
false
Expand Down Expand Up @@ -1024,7 +1065,11 @@ impl<T: Config> ElectionDataProvider for Pallet<T> {
},
);

Self::do_add_nominator(&voter, Nominations { targets, submitted_in: 0, suppressed: false });
Self::do_add_nominator(
&voter,
Default::default(),
Nominations { targets, submitted_in: 0, suppressed: false },
);
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down Expand Up @@ -1101,6 +1146,7 @@ impl<T: Config> ElectionDataProvider for Pallet<T> {
);
Self::do_add_nominator(
&v,
Default::default(),
Nominations { targets: t.try_into().unwrap(), submitted_in: 0, suppressed: false },
);
});
Expand Down
53 changes: 11 additions & 42 deletions frame/staking/src/pallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,16 +878,7 @@ pub mod pallet {
Error::<T>::InsufficientBond
);

// NOTE: ledger must be updated prior to calling `Self::weight_of`.
Self::update_ledger(&controller, &ledger);

// update this staker in the sorted list, if they exist in it.
if T::VoterList::contains(&stash) {
let _ =
T::VoterList::on_update(&stash, Self::weight_of(&ledger.stash)).defensive();
debug_assert_eq!(T::VoterList::sanity_check(), Ok(()));
}

Self::deposit_event(Event::<T>::Bonded(stash.clone(), extra));
}
Ok(())
Expand Down Expand Up @@ -962,16 +953,8 @@ pub mod pallet {
.try_push(UnlockChunk { value, era })
.map_err(|_| Error::<T>::NoMoreChunks)?;
};
// NOTE: ledger must be updated prior to calling `Self::weight_of`.
Self::update_ledger(&controller, &ledger);

// TODO: we do some of the update in update ledger and some here... not good.
// update this staker in the sorted list, if they exist in it.
if T::VoterList::contains(&ledger.stash) {
let _ = T::VoterList::on_update(&ledger.stash, Self::weight_of(&ledger.stash))
.defensive();
}

Self::update_ledger(&controller, &ledger);
Self::deposit_event(Event::<T>::Unbonded(ledger.stash, value));
}
Ok(())
Expand Down Expand Up @@ -1066,6 +1049,10 @@ pub mod pallet {

Self::do_remove_nominator(stash);
Self::do_add_validator(stash, prefs);

#[cfg(debug_assertions)]
Self::sanity_check_approval_stakes();

Ok(())
}

Expand Down Expand Up @@ -1113,7 +1100,9 @@ pub mod pallet {
.map(|t| T::Lookup::lookup(t).map_err(DispatchError::from))
.map(|n| {
n.and_then(|n| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this logic with adding targets be abstracted to do_add_nominator? Should be able to reduce some code redundancy

if old.contains(&n) || !Validators::<T>::get(&n).blocked {
if Validators::<T>::contains_key(&n) &&
(old.contains(&n) || !Validators::<T>::get(&n).blocked)
{
Ok(n)
} else {
Err(Error::<T>::BadTarget.into())
Expand All @@ -1133,27 +1122,6 @@ pub mod pallet {
Error::<T>::DuplicateTarget
);

let incoming = targets.iter().cloned().filter(|x| !old.contains(x)).collect::<Vec<_>>();
let outgoing = old.iter().cloned().filter(|x| !targets.contains(x)).collect::<Vec<_>>();

// TODO: these are all rather inefficient now based on how vote_weight is
// implemented, but I don't care because: https://github.com/paritytech/substrate/issues/10990
let weight = Self::weight_of(stash);
incoming.into_iter().for_each(|i| {
if T::TargetList::contains(&i) {
let _ = T::TargetList::on_increase(&i, weight).defensive();
} else {
let _ = T::TargetList::on_insert(i, weight).defensive();
}
});
outgoing.into_iter().for_each(|o| {
if T::TargetList::contains(&o) {
let _ = T::TargetList::on_decrease(&o, weight);
} else {
frame_support::defensive!("this validator must have, at some point in the past, been inserted into `TargetList`");
}
});

let nominations = Nominations {
targets,
// Initial nominations are considered submitted at era 0. See `Nominations` doc.
Expand All @@ -1162,7 +1130,7 @@ pub mod pallet {
};

Self::do_remove_validator(stash);
Self::do_add_nominator(stash, nominations);
Self::do_add_nominator(stash, old, nominations);

// NOTE: we need to do this after all validators and nominators have been updated in the
// previous two function calls.
Expand Down Expand Up @@ -1488,7 +1456,8 @@ pub mod pallet {
Self::update_ledger(&controller, &ledger);

if T::VoterList::contains(&ledger.stash) {
T::VoterList::on_update(&ledger.stash, Self::weight_of(&ledger.stash)).defensive();
let _ = T::VoterList::on_update(&ledger.stash, Self::weight_of(&ledger.stash))
.defensive();
}

let removed_chunks = 1u32 // for the case where the last iterated chunk is not removed
Expand Down
Loading