mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 23:21:06 +00:00
Fixes NPoS reward, along with tests, cleanups & docs corrections (#3595)
* Minor cleanups and tests * Add another test * fix * Fix tests * Fix tests * Update srml/staking/src/tests.rs Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
@@ -292,24 +292,27 @@ const STAKING_ID: LockIdentifier = *b"staking ";
|
||||
/// Counter for the number of eras that have passed.
|
||||
pub type EraIndex = u32;
|
||||
|
||||
/// Counter for the number of "reward" points earned by a given validator.
|
||||
pub type Points = u32;
|
||||
|
||||
/// Reward points of an era. Used to split era total payout between validators.
|
||||
#[derive(Encode, Decode, Default)]
|
||||
pub struct EraRewards {
|
||||
pub struct EraPoints {
|
||||
/// Total number of points. Equals the sum of reward points for each validator.
|
||||
total: u32,
|
||||
/// Reward at one index correspond to reward for validator in current_elected of this index.
|
||||
/// Thus this reward vec is only valid for one elected set.
|
||||
rewards: Vec<u32>,
|
||||
total: Points,
|
||||
/// The reward points earned by a given validator. The index of this vec corresponds to the
|
||||
/// index into the current validator set.
|
||||
individual: Vec<Points>,
|
||||
}
|
||||
|
||||
impl EraRewards {
|
||||
impl EraPoints {
|
||||
/// Add the reward to the validator at the given index. Index must be valid
|
||||
/// (i.e. `index < current_elected.len()`).
|
||||
fn add_points_to_index(&mut self, index: u32, points: u32) {
|
||||
if let Some(new_total) = self.total.checked_add(points) {
|
||||
self.total = new_total;
|
||||
self.rewards.resize((index as usize + 1).max(self.rewards.len()), 0);
|
||||
self.rewards[index as usize] += points; // Addition is less than total
|
||||
self.individual.resize((index as usize + 1).max(self.individual.len()), 0);
|
||||
self.individual[index as usize] += points; // Addition is less than total
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -590,7 +593,7 @@ decl_storage! {
|
||||
pub CurrentEraStartSessionIndex get(current_era_start_session_index): SessionIndex;
|
||||
|
||||
/// Rewards for the current era. Using indices of current elected set.
|
||||
CurrentEraRewards get(current_era_reward): EraRewards;
|
||||
CurrentEraPointsEarned get(current_era_reward): EraPoints;
|
||||
|
||||
/// The amount of balance actively at stake for each validator slot, currently.
|
||||
///
|
||||
@@ -1161,7 +1164,7 @@ impl<T: Trait> Module<T> {
|
||||
/// get a chance to set their session keys.
|
||||
fn new_era(start_session_index: SessionIndex) -> Option<Vec<T::AccountId>> {
|
||||
// Payout
|
||||
let rewards = CurrentEraRewards::take();
|
||||
let points = CurrentEraPointsEarned::take();
|
||||
let now = T::Time::now();
|
||||
let previous_era_start = <CurrentEraStart<T>>::mutate(|v| {
|
||||
rstd::mem::replace(v, now)
|
||||
@@ -1176,21 +1179,22 @@ impl<T: Trait> Module<T> {
|
||||
let total_payout = inflation::compute_total_payout(
|
||||
total_rewarded_stake.clone(),
|
||||
T::Currency::total_issuance(),
|
||||
// Era of duration more than u32::MAX is rewarded as u32::MAX.
|
||||
<BalanceOf<T>>::from(era_duration.saturated_into::<u32>()),
|
||||
// Duration of era; more than u64::MAX is rewarded as u64::MAX.
|
||||
era_duration.saturated_into::<u64>(),
|
||||
);
|
||||
|
||||
let mut total_imbalance = <PositiveImbalanceOf<T>>::zero();
|
||||
|
||||
let total_points = rewards.total;
|
||||
for (v, points) in validators.iter().zip(rewards.rewards.into_iter()) {
|
||||
if points != 0 {
|
||||
let reward = multiply_by_rational(total_payout, points, total_points);
|
||||
for (v, p) in validators.iter().zip(points.individual.into_iter()) {
|
||||
if p != 0 {
|
||||
let reward = multiply_by_rational(total_payout, p, points.total);
|
||||
total_imbalance.subsume(Self::reward_validator(v, reward));
|
||||
}
|
||||
}
|
||||
|
||||
let total_reward = total_imbalance.peek();
|
||||
// assert!(total_reward <= total_payout)
|
||||
|
||||
Self::deposit_event(RawEvent::Reward(total_reward));
|
||||
T::Reward::on_unbalanced(total_imbalance);
|
||||
T::OnRewardMinted::on_dilution(total_reward, total_rewarded_stake);
|
||||
@@ -1376,7 +1380,7 @@ impl<T: Trait> Module<T> {
|
||||
/// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`.
|
||||
/// If you need to reward lots of validator consider using `reward_by_indices`.
|
||||
pub fn reward_by_ids(validators_points: impl IntoIterator<Item = (T::AccountId, u32)>) {
|
||||
CurrentEraRewards::mutate(|rewards| {
|
||||
CurrentEraPointsEarned::mutate(|rewards| {
|
||||
let current_elected = <Module<T>>::current_elected();
|
||||
for (validator, points) in validators_points.into_iter() {
|
||||
if let Some(index) = current_elected.iter()
|
||||
@@ -1396,7 +1400,7 @@ impl<T: Trait> Module<T> {
|
||||
// TODO: This can be optimised once #3302 is implemented.
|
||||
let current_elected_len = <Module<T>>::current_elected().len() as u32;
|
||||
|
||||
CurrentEraRewards::mutate(|rewards| {
|
||||
CurrentEraPointsEarned::mutate(|rewards| {
|
||||
for (validator_index, points) in validators_points.into_iter() {
|
||||
if validator_index < current_elected_len {
|
||||
rewards.add_points_to_index(validator_index, points);
|
||||
|
||||
Reference in New Issue
Block a user