Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3a11e89
[Enhancement] Convert fast-unstake to use StakingInterface, decouplin…
ruseinov Oct 5, 2022
4f39589
Update primitives/staking/src/lib.rs
ruseinov Oct 6, 2022
9b8e123
Update primitives/staking/src/lib.rs
ruseinov Oct 6, 2022
25520d6
fix validator comment
ruseinov Oct 6, 2022
ad90903
remove todo
ruseinov Oct 10, 2022
89b32b5
ideas from Kian (#12474)
ruseinov Oct 11, 2022
f51c073
Merge remote-tracking branch 'origin/master' into ru/feature/fast-uns…
Oct 11, 2022
41d04ad
Rename StakingInterface -> Staking for nomination-pools
ruseinov Oct 12, 2022
7fc52f8
Staking fixes
ruseinov Oct 12, 2022
d3958ba
StakingInterface changes
ruseinov Oct 12, 2022
2ff689c
fix fast-unstake
ruseinov Oct 12, 2022
1fc6510
fix nomination-pools
ruseinov Oct 12, 2022
28d15d7
Merge remote-tracking branch 'origin/master' into ru/feature/fast-uns…
Oct 18, 2022
0705029
Fix fast-unstake tests
ruseinov Oct 18, 2022
39cf580
Fix benches for fast-unstake
ruseinov Oct 18, 2022
8093567
fix is_unbonding
ruseinov Oct 18, 2022
30a5882
fix nomination pools
ruseinov Oct 18, 2022
37107ef
fix node code
ruseinov Oct 19, 2022
097a9d1
add mock comments
ruseinov Oct 19, 2022
613a701
fix imports
ruseinov Oct 19, 2022
e785dd5
remove todo
ruseinov Oct 19, 2022
03586d7
more fixes
ruseinov Oct 19, 2022
20a4f29
more fixes
ruseinov Oct 19, 2022
9807cf2
bench fixes
ruseinov Oct 19, 2022
3639af8
more fixes
ruseinov Oct 19, 2022
b7827d5
more fixes
ruseinov Oct 20, 2022
5232b99
import fix
ruseinov Oct 20, 2022
f881456
more fixes
ruseinov Oct 20, 2022
c3cee71
more bench fix
ruseinov Oct 20, 2022
068c565
refix
ruseinov Oct 20, 2022
ff36f90
refix
ruseinov Oct 20, 2022
6f862e4
Update primitives/staking/src/lib.rs
ruseinov Oct 25, 2022
bff58a4
is_unbonding returns a result
ruseinov Oct 20, 2022
bdb525e
fix
ruseinov Oct 25, 2022
4bd57b1
review fixes
ruseinov Oct 25, 2022
f6040ec
more review fixes
ruseinov Oct 25, 2022
8c5604d
more fixes
ruseinov Oct 25, 2022
731fab2
more fixes
ruseinov Oct 25, 2022
b90082a
Update frame/fast-unstake/src/benchmarking.rs
ruseinov Oct 26, 2022
1eee8a5
remove redundant CurrencyBalance from nom-pools
ruseinov Oct 26, 2022
1f4fad2
remove CB
ruseinov Oct 26, 2022
27530dc
Merge remote-tracking branch 'origin/master' into ru/feature/fast-uns…
Oct 26, 2022
90cec9f
rephrase
ruseinov Oct 26, 2022
b1560aa
Apply suggestions from code review
kianenigma Oct 27, 2022
75a36bb
Update frame/nomination-pools/src/tests.rs
kianenigma Oct 27, 2022
b3e843e
finish damn renamed
kianenigma Oct 27, 2022
963837b
clippy fix
ruseinov Oct 27, 2022
cbed2f9
fix
ruseinov Oct 27, 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
ideas from Kian (#12474)
Co-authored-by: kianenigma <[email protected]>
  • Loading branch information
ruseinov and kianenigma authored Oct 11, 2022
commit 89b32b56eecb6d5639734ba7ed970b8002d50b03
3 changes: 0 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions frame/fast-unstake/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/
sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" }
sp-staking = { default-features = false, path = "../../primitives/staking" }

pallet-balances = { default-features = false, path = "../balances" }
pallet-timestamp = { default-features = false, path = "../timestamp" }
pallet-staking = { default-features = false, path = "../staking" }
frame-election-provider-support = { default-features = false, path = "../election-provider-support" }

frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" }
Expand All @@ -53,16 +49,12 @@ std = [
"sp-runtime/std",
"sp-std/std",

"pallet-staking/std",
"pallet-balances/std",
"pallet-timestamp/std",
"frame-election-provider-support/std",

"frame-benchmarking/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-staking/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
1 change: 0 additions & 1 deletion frame/fast-unstake/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use frame_support::{
traits::{Currency, EnsureOrigin, Get, Hooks},
};
use frame_system::RawOrigin;
use pallet_staking::Pallet as Staking;
use sp_runtime::traits::{StaticLookup, Zero};
use sp_staking::EraIndex;
use sp_std::prelude::*;
Expand Down
45 changes: 18 additions & 27 deletions frame/fast-unstake/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,11 @@ pub mod pallet {
traits::{Defensive, ReservableCurrency},
};
use frame_system::{pallet_prelude::*, RawOrigin};
use pallet_staking::Pallet as Staking;
use sp_runtime::{
traits::{Saturating, Zero},
DispatchResult,
};
use sp_staking::EraIndex;
use sp_staking::{EraIndex, StakingInterface};
use sp_std::{prelude::*, vec::Vec};
pub use weights::WeightInfo;

Expand All @@ -101,7 +100,7 @@ pub mod pallet {
pub struct MaxChecking<T: Config>(sp_std::marker::PhantomData<T>);
impl<T: Config> frame_support::traits::Get<u32> for MaxChecking<T> {
fn get() -> u32 {
<T as pallet_staking::Config>::BondingDuration::get() + 1
T::StakingInterface::bonding_duration() + 1
}
}

Expand All @@ -126,7 +125,10 @@ pub mod pallet {
type ControlOrigin: frame_support::traits::EnsureOrigin<Self::RuntimeOrigin>;

/// The access to staking functionality.
type Staking: StakingInterface<Balance = BalanceOf<Self>, AccountId = Self::AccountId>;
type StakingInterface: StakingInterface<
Balance = BalanceOf<Self>,
AccountId = Self::AccountId,
>;

/// The weight information of this pallet.
type WeightInfo: WeightInfo;
Expand Down Expand Up @@ -224,23 +226,19 @@ pub mod pallet {
let ctrl = ensure_signed(origin)?;

ensure!(ErasToCheckPerBlock::<T>::get() != 0, <Error<T>>::CallNotAllowed);

let ledger =
pallet_staking::Ledger::<T>::get(&ctrl).ok_or(Error::<T>::NotController)?;
ensure!(!Queue::<T>::contains_key(&ledger.stash), Error::<T>::AlreadyQueued);
let stash = T::StakingInterface::can_control(&ctrl)?;
ensure!(!Queue::<T>::contains_key(&stash), Error::<T>::AlreadyQueued);
ensure!(
Head::<T>::get().map_or(true, |UnstakeRequest { stash, .. }| stash != ledger.stash),
Error::<T>::AlreadyHead
);

// second part of the && is defensive.
ensure!(
ledger.active == ledger.total && ledger.unlocking.is_empty(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still need to check for ledger.unlocking.is_empty() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, we are not exposing the ledger anymore, so the defensive condition has to go.

Error::<T>::NotFullyBonded
);
ensure!(!T::StakingInterface::is_unbonding(&who), Error::<T>::NotFullyBonded);

// chill and fully unstake.
Staking::<T>::chill(RawOrigin::Signed(ctrl.clone()).into())?;
Staking::<T>::unbond(RawOrigin::Signed(ctrl).into(), ledger.total)?;
T::StakingInterface::chill(&stash)?;
T::StakingInterface::fully_unbond(&stash)?;

T::DepositCurrency::reserve(&ledger.stash, T::Deposit::get())?;

Expand All @@ -262,9 +260,7 @@ pub mod pallet {

ensure!(ErasToCheckPerBlock::<T>::get() != 0, <Error<T>>::CallNotAllowed);

let stash = pallet_staking::Ledger::<T>::get(&ctrl)
.map(|l| l.stash)
.ok_or(Error::<T>::NotController)?;
let stash = T::StakingInterface::can_control(&ctrl)?;
ensure!(Queue::<T>::contains_key(&stash), Error::<T>::NotQueued);
ensure!(
Head::<T>::get().map_or(true, |UnstakeRequest { stash, .. }| stash != stash),
Expand Down Expand Up @@ -317,7 +313,7 @@ pub mod pallet {

// NOTE: here we're assuming that the number of validators has only ever increased,
// meaning that the number of exposures to check is either this per era, or less.
let validator_count = pallet_staking::ValidatorCount::<T>::get();
let validator_count = T::StakingInterface::desired_validator_count();

// determine the number of eras to check. This is based on both `ErasToCheckPerBlock`
// and `remaining_weight` passed on to us from the runtime executive.
Expand All @@ -333,8 +329,7 @@ pub mod pallet {
}
}

if <<T as pallet_staking::Config>::ElectionProvider as ElectionProviderBase>::ongoing()
{
if T::StakingInterface::election_ongoing() {
// NOTE: we assume `ongoing` does not consume any weight.
// there is an ongoing election -- we better not do anything. Imagine someone is not
// exposed anywhere in the last era, and the snapshot for the election is already
Expand Down Expand Up @@ -369,8 +364,8 @@ pub mod pallet {
);

// the range that we're allowed to check in this round.
let current_era = pallet_staking::CurrentEra::<T>::get().unwrap_or_default();
let bonding_duration = <T as pallet_staking::Config>::BondingDuration::get();
let current_era = T::StakingInterface::current_era();
let bonding_duration = T::StakingInterface::bonding_duration();
// prune all the old eras that we don't care about. This will help us keep the bound
// of `checked`.
checked.retain(|e| *e >= current_era.saturating_sub(bonding_duration));
Expand Down Expand Up @@ -407,11 +402,7 @@ pub mod pallet {
// `stash` is not exposed in any era now -- we can let go of them now.
let num_slashing_spans = Staking::<T>::slashing_spans(&stash).iter().count() as u32;

let result = pallet_staking::Pallet::<T>::force_unstake(
RawOrigin::Root.into(),
stash.clone(),
num_slashing_spans,
);
let result = T::StakingInterface::force_unstake(stash.clone());

let remaining = T::DepositCurrency::unreserve(&stash, deposit);
if !remaining.is_zero() {
Expand Down
78 changes: 54 additions & 24 deletions frame/staking/src/pallet/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -1482,14 +1482,39 @@ 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 {
todo!();
}

fn can_control(controller: &Self::AccountId) -> Result<Self::AccountId, DispatchError> {
Self::ledger(controller).map(|l| l.stash).ok_or(Error::<T>::NotController)
}

fn is_exposed_in_era(who: &Self::AccountId, era: &EraIndex) -> bool {
todo!()
}

fn bonding_duration() -> EraIndex {
T::BondingDuration::get()
}
Expand All @@ -1498,52 +1523,57 @@ 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 active_stake(who: &Self::AccountId) -> Option<Self::Balance> {
Self::bonded(who).and_then(|c| Self::ledger(c)).map(|l| l.active)
}

fn total_stake(controller: &Self::AccountId) -> Option<Self::Balance> {
Self::ledger(controller).map(|l| l.total)
fn total_stake(who: &Self::AccountId) -> Option<Self::Balance> {
Self::bonded(who).and_then(|c| Self::ledger(c)).map(|l| l.active)
}

fn bond_extra(stash: Self::AccountId, extra: Self::Balance) -> DispatchResult {
Self::bond_extra(RawOrigin::Signed(stash).into(), extra)
fn bond_extra(who: &Self::AccountId, extra: Self::Balance) -> DispatchResult {
Self::bond_extra(RawOrigin::Signed(who.clone()).into(), extra)
}

fn unbond(controller: Self::AccountId, value: Self::Balance) -> DispatchResult {
Self::unbond(RawOrigin::Signed(controller).into(), value)
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 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")]
Expand Down
Loading