[Enhancement] Convert fast-unstake to use StakingInterface, decouplin… (#12424)

* [Enhancement] Convert fast-unstake to use StakingInterface, decoupling it from Staking

* Update primitives/staking/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update primitives/staking/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* fix validator comment

* remove todo

* ideas from Kian (#12474)

Co-authored-by: kianenigma <kian@parity.io>

* Rename StakingInterface -> Staking for nomination-pools

* Staking fixes

* StakingInterface changes

* fix fast-unstake

* fix nomination-pools

* Fix fast-unstake tests

* Fix benches for fast-unstake

* fix is_unbonding

* fix nomination pools

* fix node code

* add mock comments

* fix imports

* remove todo

* more fixes

* more fixes

* bench fixes

* more fixes

* more fixes

* import fix

* more fixes

* more bench fix

* refix

* refix

* Update primitives/staking/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* is_unbonding returns a result

* fix

* review fixes

* more review fixes

* more fixes

* more fixes

* Update frame/fast-unstake/src/benchmarking.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* remove redundant CurrencyBalance from nom-pools

* remove CB

* rephrase

* Apply suggestions from code review

* Update frame/nomination-pools/src/tests.rs

* finish damn renamed

* clippy fix

* fix

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: kianenigma <kian@parity.io>
Co-authored-by: parity-processbot <>
Co-authored-by: Squirrel <gilescope@gmail.com>
This commit is contained in:
Roman Useinov
2022-10-29 11:22:58 +02:00
committed by GitHub
parent 3faa0bd20d
commit 4bc091f4a9
16 changed files with 371 additions and 304 deletions
+80 -27
View File
@@ -18,8 +18,8 @@
//! Implementations for the Staking FRAME Pallet.
use frame_election_provider_support::{
data_provider, ElectionDataProvider, ElectionProvider, ScoreProvider, SortedListProvider,
Supports, VoteWeight, VoterOf,
data_provider, ElectionDataProvider, ElectionProvider, ElectionProviderBase, ScoreProvider,
SortedListProvider, Supports, VoteWeight, VoterOf,
};
use frame_support::{
dispatch::WithPostDispatchInfo,
@@ -38,7 +38,7 @@ use sp_runtime::{
};
use sp_staking::{
offence::{DisableStrategy, OffenceDetails, OnOffenceHandler},
EraIndex, SessionIndex, StakingInterface,
EraIndex, SessionIndex, Stake, StakingInterface,
};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
@@ -1482,14 +1482,44 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsAndValidatorsM
}
}
// NOTE: in this entire impl block, the assumption is that `who` is a stash account.
impl<T: Config> StakingInterface for Pallet<T> {
type AccountId = T::AccountId;
type Balance = BalanceOf<T>;
fn minimum_bond() -> Self::Balance {
fn minimum_nominator_bond() -> Self::Balance {
MinNominatorBond::<T>::get()
}
fn minimum_validator_bond() -> Self::Balance {
MinValidatorBond::<T>::get()
}
fn desired_validator_count() -> u32 {
ValidatorCount::<T>::get()
}
fn election_ongoing() -> bool {
<T::ElectionProvider as ElectionProviderBase>::ongoing()
}
fn force_unstake(who: Self::AccountId) -> sp_runtime::DispatchResult {
let num_slashing_spans = Self::slashing_spans(&who).iter().count() as u32;
Self::force_unstake(RawOrigin::Root.into(), who.clone(), num_slashing_spans)
}
fn stash_by_ctrl(controller: &Self::AccountId) -> Result<Self::AccountId, DispatchError> {
Self::ledger(controller)
.map(|l| l.stash)
.ok_or(Error::<T>::NotController.into())
}
fn is_exposed_in_era(who: &Self::AccountId, era: &EraIndex) -> bool {
ErasStakers::<T>::iter_prefix(era).any(|(validator, exposures)| {
validator == *who || exposures.others.iter().any(|i| i.who == *who)
})
}
fn bonding_duration() -> EraIndex {
T::BondingDuration::get()
}
@@ -1498,58 +1528,81 @@ impl<T: Config> StakingInterface for Pallet<T> {
Self::current_era().unwrap_or(Zero::zero())
}
fn active_stake(controller: &Self::AccountId) -> Option<Self::Balance> {
Self::ledger(controller).map(|l| l.active)
fn stake(who: &Self::AccountId) -> Result<Stake<Self>, DispatchError> {
Self::bonded(who)
.and_then(|c| Self::ledger(c))
.map(|l| Stake { stash: l.stash, total: l.total, active: l.active })
.ok_or(Error::<T>::NotStash.into())
}
fn total_stake(controller: &Self::AccountId) -> Option<Self::Balance> {
Self::ledger(controller).map(|l| l.total)
fn bond_extra(who: &Self::AccountId, extra: Self::Balance) -> DispatchResult {
Self::bond_extra(RawOrigin::Signed(who.clone()).into(), extra)
}
fn bond_extra(stash: Self::AccountId, extra: Self::Balance) -> DispatchResult {
Self::bond_extra(RawOrigin::Signed(stash).into(), extra)
fn unbond(who: &Self::AccountId, value: Self::Balance) -> DispatchResult {
let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
Self::unbond(RawOrigin::Signed(ctrl).into(), value)
}
fn unbond(controller: Self::AccountId, value: Self::Balance) -> DispatchResult {
Self::unbond(RawOrigin::Signed(controller).into(), value)
}
fn chill(controller: Self::AccountId) -> DispatchResult {
Self::chill(RawOrigin::Signed(controller).into())
fn chill(who: &Self::AccountId) -> DispatchResult {
// defensive-only: any account bonded via this interface has the stash set as the
// controller, but we have to be sure. Same comment anywhere else that we read this.
let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
Self::chill(RawOrigin::Signed(ctrl).into())
}
fn withdraw_unbonded(
controller: Self::AccountId,
who: Self::AccountId,
num_slashing_spans: u32,
) -> Result<bool, DispatchError> {
Self::withdraw_unbonded(RawOrigin::Signed(controller.clone()).into(), num_slashing_spans)
.map(|_| !Ledger::<T>::contains_key(&controller))
let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
Self::withdraw_unbonded(RawOrigin::Signed(ctrl.clone()).into(), num_slashing_spans)
.map(|_| !Ledger::<T>::contains_key(&ctrl))
.map_err(|with_post| with_post.error)
}
fn bond(
stash: Self::AccountId,
controller: Self::AccountId,
who: &Self::AccountId,
value: Self::Balance,
payee: Self::AccountId,
payee: &Self::AccountId,
) -> DispatchResult {
Self::bond(
RawOrigin::Signed(stash).into(),
T::Lookup::unlookup(controller),
RawOrigin::Signed(who.clone()).into(),
T::Lookup::unlookup(who.clone()),
value,
RewardDestination::Account(payee),
RewardDestination::Account(payee.clone()),
)
}
fn nominate(controller: Self::AccountId, targets: Vec<Self::AccountId>) -> DispatchResult {
fn nominate(who: &Self::AccountId, targets: Vec<Self::AccountId>) -> DispatchResult {
let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
let targets = targets.into_iter().map(T::Lookup::unlookup).collect::<Vec<_>>();
Self::nominate(RawOrigin::Signed(controller).into(), targets)
Self::nominate(RawOrigin::Signed(ctrl).into(), targets)
}
#[cfg(feature = "runtime-benchmarks")]
fn nominations(who: Self::AccountId) -> Option<Vec<T::AccountId>> {
Nominators::<T>::get(who).map(|n| n.targets.into_inner())
}
#[cfg(feature = "runtime-benchmarks")]
fn add_era_stakers(
current_era: &EraIndex,
stash: &T::AccountId,
exposures: Vec<(Self::AccountId, Self::Balance)>,
) {
let others = exposures
.iter()
.map(|(who, value)| IndividualExposure { who: who.clone(), value: value.clone() })
.collect::<Vec<_>>();
let exposure = Exposure { total: Default::default(), own: Default::default(), others };
Self::add_era_stakers(current_era.clone(), stash.clone(), exposure)
}
#[cfg(feature = "runtime-benchmarks")]
fn set_current_era(era: EraIndex) {
CurrentEra::<T>::put(era);
}
}
#[cfg(any(test, feature = "try-runtime"))]
+1 -1
View File
@@ -262,7 +262,7 @@ pub mod pallet {
type WeightInfo: WeightInfo;
}
/// The ideal number of staking participants.
/// The ideal number of active validators.
#[pallet::storage]
#[pallet::getter(fn validator_count)]
pub type ValidatorCount<T> = StorageValue<_, u32, ValueQuery>;