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

Commit

Permalink
Remove old staking
Browse files Browse the repository at this point in the history
  • Loading branch information
shawntabrizi committed May 2, 2020
1 parent c0df5ce commit 95262b1
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 702 deletions.
219 changes: 9 additions & 210 deletions frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1037,9 +1037,6 @@ decl_storage! {
///
/// This is set to v3.0.0 for new networks.
StorageVersion build(|_: &GenesisConfig<T>| Releases::V3_0_0): Releases;

/// The era where we migrated from Lazy Payouts to Simple Payouts
MigrateEra: Option<EraIndex>;
}
add_extra_genesis {
config(stakers):
Expand Down Expand Up @@ -1246,6 +1243,15 @@ decl_module! {
}
}

fn on_runtime_upgrade() -> Weight {
use frame_support::storage::migration::take_storage_value;
if let Some(_) = take_storage_value::<EraIndex>(b"Staking", b"MigrateEra", b"") {
T::DbWeight::get().reads_writes(1, 1)
} else {
T::DbWeight::get().reads(1)
}
}

/// Take the origin account as a stash and lock up `value` of its balance. `controller` will
/// be the account that controls it.
///
Expand Down Expand Up @@ -1664,69 +1670,6 @@ decl_module! {
<Self as Store>::UnappliedSlashes::insert(&era, &unapplied);
}

/// **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving
/// opportunity for users to claim all rewards before moving to Simple Payouts. After this
/// time, you should use `payout_stakers` instead.**
///
/// Make one nominator's payout for one era.
///
/// - `who` is the controller account of the nominator to pay out.
/// - `era` may not be lower than one following the most recently paid era. If it is higher,
/// then it indicates an instruction to skip the payout of all previous eras.
/// - `validators` is the list of all validators that `who` had exposure to during `era`,
/// alongside the index of `who` in the clipped exposure of the validator.
/// I.e. each element is a tuple of
/// `(validator, index of `who` in clipped exposure of validator)`.
/// If it is incomplete, then less than the full reward will be paid out.
/// It must not exceed `MAX_NOMINATIONS`.
///
/// WARNING: once an era is payed for a validator such validator can't claim the payout of
/// previous era.
///
/// WARNING: Incorrect arguments here can result in loss of payout. Be very careful.
///
/// # <weight>
/// - Number of storage read of `O(validators)`; `validators` is the argument of the call,
/// and is bounded by `MAX_NOMINATIONS`.
/// - Each storage read is `O(N)` size and decode complexity; `N` is the maximum
/// nominations that can be given to a single validator.
/// - Computation complexity: `O(MAX_NOMINATIONS * logN)`; `MAX_NOMINATIONS` is the
/// maximum number of validators that may be nominated by a single nominator, it is
/// bounded only economically (all nominators are required to place a minimum stake).
/// # </weight>
#[weight = 500_000_000]
fn payout_nominator(origin, era: EraIndex, validators: Vec<(T::AccountId, u32)>)
-> DispatchResult
{
let ctrl = ensure_signed(origin)?;
Self::do_payout_nominator(ctrl, era, validators)
}

/// **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving
/// opportunity for users to claim all rewards before moving to Simple Payouts. After this
/// time, you should use `payout_stakers` instead.**
///
/// Make one validator's payout for one era.
///
/// - `who` is the controller account of the validator to pay out.
/// - `era` may not be lower than one following the most recently paid era. If it is higher,
/// then it indicates an instruction to skip the payout of all previous eras.
///
/// WARNING: once an era is payed for a validator such validator can't claim the payout of
/// previous era.
///
/// WARNING: Incorrect arguments here can result in loss of payout. Be very careful.
///
/// # <weight>
/// - Time complexity: O(1).
/// - Contains a limited number of reads and writes.
/// # </weight>
#[weight = 500_000_000]
fn payout_validator(origin, era: EraIndex) -> DispatchResult {
let ctrl = ensure_signed(origin)?;
Self::do_payout_validator(ctrl, era)
}

/// Pay out all the stakers behind a single validator for a single era.
///
/// - `validator_stash` is the stash account of the validator. Their nominators, up to
Expand Down Expand Up @@ -1974,143 +1917,6 @@ impl<T: Trait> Module<T> {
<SnapshotNominators<T>>::kill();
}

fn do_payout_nominator(ctrl: T::AccountId, era: EraIndex, validators: Vec<(T::AccountId, u32)>)
-> DispatchResult
{
// validators len must not exceed `MAX_NOMINATIONS` to avoid querying more validator
// exposure than necessary.
if validators.len() > MAX_NOMINATIONS {
return Err(Error::<T>::InvalidNumberOfNominations.into());
}
// If migrate_era is not populated, then you should use `payout_stakers`
let migrate_era = MigrateEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
// This payout mechanism will only work for eras before the migration.
// Subsequent payouts should use `payout_stakers`.
ensure!(era < migrate_era, Error::<T>::InvalidEraToReward);
let current_era = CurrentEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
ensure!(era <= current_era, Error::<T>::InvalidEraToReward);
let history_depth = Self::history_depth();
ensure!(era >= current_era.saturating_sub(history_depth), Error::<T>::InvalidEraToReward);

// Note: if era has no reward to be claimed, era may be future. better not to update
// `nominator_ledger.last_reward` in this case.
let era_payout = <ErasValidatorReward<T>>::get(&era)
.ok_or_else(|| Error::<T>::InvalidEraToReward)?;

let mut nominator_ledger = <Ledger<T>>::get(&ctrl).ok_or_else(|| Error::<T>::NotController)?;

ensure!(
Self::era_election_status().is_closed() || Self::payee(&nominator_ledger.stash) != RewardDestination::Staked,
Error::<T>::CallNotAllowed,
);

nominator_ledger.claimed_rewards.retain(|&x| x >= current_era.saturating_sub(history_depth));
match nominator_ledger.claimed_rewards.binary_search(&era) {
Ok(_) => Err(Error::<T>::AlreadyClaimed)?,
Err(pos) => nominator_ledger.claimed_rewards.insert(pos, era),
}

<Ledger<T>>::insert(&ctrl, &nominator_ledger);

let mut reward = Perbill::zero();
let era_reward_points = <ErasRewardPoints<T>>::get(&era);

for (validator, nominator_index) in validators.into_iter() {
let commission = Self::eras_validator_prefs(&era, &validator).commission;
let validator_exposure = <ErasStakersClipped<T>>::get(&era, &validator);

if let Some(nominator_exposure) = validator_exposure.others
.get(nominator_index as usize)
{
if nominator_exposure.who != nominator_ledger.stash {
continue;
}

let nominator_exposure_part = Perbill::from_rational_approximation(
nominator_exposure.value,
validator_exposure.total,
);
let validator_point = era_reward_points.individual.get(&validator)
.map(|points| *points)
.unwrap_or_else(|| Zero::zero());
let validator_point_part = Perbill::from_rational_approximation(
validator_point,
era_reward_points.total,
);
reward = reward.saturating_add(
validator_point_part
.saturating_mul(Perbill::one().saturating_sub(commission))
.saturating_mul(nominator_exposure_part)
);
}
}

if let Some(imbalance) = Self::make_payout(&nominator_ledger.stash, reward * era_payout) {
Self::deposit_event(RawEvent::Reward(ctrl, imbalance.peek()));
}

Ok(())
}

fn do_payout_validator(ctrl: T::AccountId, era: EraIndex) -> DispatchResult {
// If migrate_era is not populated, then you should use `payout_stakers`
let migrate_era = MigrateEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
// This payout mechanism will only work for eras before the migration.
// Subsequent payouts should use `payout_stakers`.
ensure!(era < migrate_era, Error::<T>::InvalidEraToReward);
let current_era = CurrentEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
ensure!(era <= current_era, Error::<T>::InvalidEraToReward);
let history_depth = Self::history_depth();
ensure!(era >= current_era.saturating_sub(history_depth), Error::<T>::InvalidEraToReward);

// Note: if era has no reward to be claimed, era may be future. better not to update
// `ledger.last_reward` in this case.
let era_payout = <ErasValidatorReward<T>>::get(&era)
.ok_or_else(|| Error::<T>::InvalidEraToReward)?;

let mut ledger = <Ledger<T>>::get(&ctrl).ok_or_else(|| Error::<T>::NotController)?;

ensure!(
Self::era_election_status().is_closed() || Self::payee(&ledger.stash) != RewardDestination::Staked,
Error::<T>::CallNotAllowed,
);

ledger.claimed_rewards.retain(|&x| x >= current_era.saturating_sub(history_depth));
match ledger.claimed_rewards.binary_search(&era) {
Ok(_) => Err(Error::<T>::AlreadyClaimed)?,
Err(pos) => ledger.claimed_rewards.insert(pos, era),
}

<Ledger<T>>::insert(&ctrl, &ledger);

let era_reward_points = <ErasRewardPoints<T>>::get(&era);
let commission = Self::eras_validator_prefs(&era, &ledger.stash).commission;
let exposure = <ErasStakersClipped<T>>::get(&era, &ledger.stash);

let exposure_part = Perbill::from_rational_approximation(
exposure.own,
exposure.total,
);
let validator_point = era_reward_points.individual.get(&ledger.stash)
.map(|points| *points)
.unwrap_or_else(|| Zero::zero());
let validator_point_part = Perbill::from_rational_approximation(
validator_point,
era_reward_points.total,
);
let reward = validator_point_part.saturating_mul(
commission.saturating_add(
Perbill::one().saturating_sub(commission).saturating_mul(exposure_part)
)
);

if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) {
Self::deposit_event(RawEvent::Reward(ctrl, imbalance.peek()));
}

Ok(())
}

fn do_payout_stakers(
validator_stash: T::AccountId,
era: EraIndex,
Expand All @@ -2121,13 +1927,6 @@ impl<T: Trait> Module<T> {
let history_depth = Self::history_depth();
ensure!(era >= current_era.saturating_sub(history_depth), Error::<T>::InvalidEraToReward);

// If there was no migration, then this function is always valid.
if let Some(migrate_era) = MigrateEra::get() {
// This payout mechanism will only work for eras on and after the migration.
// Payouts before then should use `payout_nominator`/`payout_validator`.
ensure!(migrate_era <= era, Error::<T>::InvalidEraToReward);
}

// Note: if era has no reward to be claimed, era may be future. better not to update
// `ledger.claimed_rewards` in this case.
let era_payout = <ErasValidatorReward<T>>::get(&era)
Expand Down
34 changes: 1 addition & 33 deletions frame/staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! Test utilities

use std::{collections::{HashSet, HashMap}, cell::RefCell};
use std::{collections::HashSet, cell::RefCell};
use sp_runtime::Perbill;
use sp_runtime::curve::PiecewiseLinear;
use sp_runtime::traits::{IdentityLookup, Convert, SaturatedConversion, Zero};
Expand Down Expand Up @@ -948,38 +948,6 @@ pub(crate) fn prepare_submission_with(
(compact, winners, score)
}

/// Make all validator and nominator request their payment
pub(crate) fn make_all_reward_payment_before_migration(era: EraIndex) {
let validators_with_reward = ErasRewardPoints::<Test>::get(era).individual.keys()
.cloned()
.collect::<Vec<_>>();

// reward nominators
let mut nominator_controllers = HashMap::new();
for validator in Staking::eras_reward_points(era).individual.keys() {
let validator_exposure = Staking::eras_stakers_clipped(era, validator);
for (nom_index, nom) in validator_exposure.others.iter().enumerate() {
if let Some(nom_ctrl) = Staking::bonded(nom.who) {
nominator_controllers.entry(nom_ctrl)
.or_insert(vec![])
.push((validator.clone(), nom_index as u32));
}
}
}
for (nominator_controller, validators_with_nom_index) in nominator_controllers {
assert_ok!(Staking::payout_nominator(
Origin::signed(nominator_controller),
era,
validators_with_nom_index,
));
}

// reward validators
for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) {
assert_ok!(Staking::payout_validator(Origin::signed(validator_controller), era));
}
}

/// Make all validator and nominator request their payment
pub(crate) fn make_all_reward_payment(era: EraIndex) {
let validators_with_reward = ErasRewardPoints::<Test>::get(era).individual.keys()
Expand Down
Loading

0 comments on commit 95262b1

Please sign in to comment.