diff --git a/substrate/frame/staking/src/migrations/v13_stake_tracker/mod.rs b/substrate/frame/staking/src/migrations/v13_stake_tracker/mod.rs index e40b96975ba5..208998dddded 100644 --- a/substrate/frame/staking/src/migrations/v13_stake_tracker/mod.rs +++ b/substrate/frame/staking/src/migrations/v13_stake_tracker/mod.rs @@ -20,13 +20,14 @@ //! sorted list of targets with a bags-list. use super::PALLET_MIGRATIONS_ID; -use crate::{log, weights, Config, Nominators, Pallet, StakerStatus, Validators}; +use crate::{log, weights, Config, Nominations, Nominators, Pallet, StakerStatus, Validators}; use core::marker::PhantomData; use frame_election_provider_support::{SortedListProvider, VoteWeight}; use frame_support::{ ensure, migrations::{MigrationId, SteppedMigration, SteppedMigrationError}, traits::Defensive, + BoundedVec, }; use sp_staking::StakingInterface; use sp_std::prelude::*; @@ -69,12 +70,8 @@ impl, W: weights::WeightInfo> SteppedMigration return Err(SteppedMigrationError::InsufficientWeight { required }); } - let mut chilled = 0; - // do as much progress as possible per step. while meter.try_consume(required).is_ok() { - //TODO: only bench a sub-step function, e.g. Self::do_migrate_nominatior(who); - // fetch the next nominator to migrate. let mut iter = if let Some(ref last_nom) = cursor { Nominators::::iter_from(Nominators::::hashed_key_for(last_nom)) @@ -83,19 +80,11 @@ impl, W: weights::WeightInfo> SteppedMigration }; if let Some((nominator, _)) = iter.next() { - // try chill nominator. If chilled, skip migration of this nominator. The nominator - // is force-chilled because it may need to re-nominate with a different set of - // nominations (see below). Thus it is better to just chill the nominator and move - // on. - if Self::try_chill_nominator(&nominator) { - chilled += 1; - cursor = Some(nominator); - continue; - } + let nominator_vote = Pallet::::weight_of(&nominator); + // clean the nominations before migrating. This will ensure that the voter is not // nominating duplicate and/or dangling targets. let nominations = Self::clean_nominations(&nominator)?; - let nominator_vote = Pallet::::weight_of(&nominator); // iter over up to `MaxNominationsOf` targets of `nominator` and insert or // update the target's approval's score. @@ -113,23 +102,17 @@ impl, W: weights::WeightInfo> SteppedMigration // done, return earlier. // TODO: do this as the migration is performed -- not a large step at the end. - - let mut a = 0; // but before, add active validators without any nominations. for (validator, _) in Validators::::iter() { if !::TargetList::contains(&validator) && as StakingInterface>::status(&validator) == Ok(StakerStatus::Validator) { - a += 1; let self_stake = Pallet::::weight_of(&validator); ::TargetList::on_insert(validator, self_stake.into()) .expect("node does not exist, checked above; qed."); } } - - log!(info, "Added validators with self stake: {:?}", a); - log!(info, "Chilled nominators: {:?}", chilled); return Ok(None) } } @@ -191,17 +174,6 @@ impl, W: weights::WeightInfo> MigrationV13 bool { - if Pallet::::active_stake(&who).unwrap_or_default() < - Pallet::::minimum_nominator_bond() - { - let _ = as StakingInterface>::chill(&who).defensive(); - return true; - } - false - } - /// Cleans up the nominations of `who`. /// /// After calling this method, the following invariants are respected: @@ -221,40 +193,50 @@ impl, W: weights::WeightInfo> MigrationV13::get(who) - .map(|n| n.targets.into_inner()) - .expect("who is nominator as per the check above; qed."); + let raw_nominations = + Nominators::::get(who).expect("who is nominator as per the check above; qed."); + let mut raw_targets = raw_nominations.targets.into_inner(); - let count_before = raw_nominations.len(); + let count_before = raw_targets.len(); // remove duplicate nominations. - let dedup_noms: Vec = raw_nominations - .drain(..) - .collect::>() - .into_iter() - .collect::>(); + let dedup_noms: Vec = + raw_targets.drain(..).collect::>().into_iter().collect::>(); // remove all non-validator nominations. - let nominations = dedup_noms + let targets = dedup_noms .into_iter() .filter(|n| Pallet::::status(n) == Ok(StakerStatus::Validator)) .collect::>(); - // update `who`'s nominations in staking or chill voter, if necessary. - if nominations.len() == 0 { + if targets.len() == 0 { + // if no nominations are left, chill the nominator. let _ = as StakingInterface>::chill(&who) .map_err(|e| { - log!(error, "ERROR when chilling {:?}", who); + log!(error, "error when chilling {:?}", who); e }) .defensive(); - } else if count_before > nominations.len() { - as StakingInterface>::nominate(who, nominations.clone()).map_err(|e| { - log!(error, "failed to migrate nominations {:?}.", e); - SteppedMigrationError::Failed - })?; + } else if count_before > targets.len() { + // force update the nominations. + let bounded_targets = targets + .clone() + .into_iter() + .collect::>() + .try_into() + .expect( + "new bound should be within the existent set of targets, thus it should fit; qed.", + ); + + let nominations = Nominations { + targets: bounded_targets, + submitted_in: raw_nominations.submitted_in, + suppressed: raw_nominations.suppressed, + }; + + >::do_add_nominator(who, nominations); } - Ok(nominations) + Ok(targets) } } diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index a3fff07e05b0..81a3c9c4a46a 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -2445,8 +2445,6 @@ impl Pallet { Ok(()) } - /// TODO: implement checks when voter list is strictly sorted. - /// Stake-tracker: checks if the approvals stake of the targets in the target list are correct. /// /// These try-state checks generate a map with approval stake of all the targets based on @@ -2496,19 +2494,6 @@ impl Pallet { ); for target in nominations.into_iter() { - // skip if for some reason there is a nominator being nominated. - match Self::status(&target) { - Ok(StakerStatus::Nominator(_)) => { - log!( - warn, - "nominated stakers {:?} is a nominator, not a validator.", - target - ); - continue; - }, - _ => (), - } - if let Some(approvals) = approvals_map.get_mut(&target) { *approvals += vote.into(); } else {