Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

ideas from Kian #12474

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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(),
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