Skip to content

Commit 090945a

Browse files
authored
Refactoring for new distribution model (paritytech#735)
* Split out reward.rs * Move reward related to reward.rs * Extract try_funding_team * Build wasm
1 parent 7cb8730 commit 090945a

File tree

7 files changed

+241
-220
lines changed

7 files changed

+241
-220
lines changed
-46 Bytes
Binary file not shown.
Binary file not shown.

xrml/xmining/staking/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![cfg_attr(not(feature = "std"), no_std)]
55

66
mod mock;
7+
mod reward;
78
mod shifter;
89
pub mod slash;
910
mod tests;
@@ -29,7 +30,7 @@ use xsupport::debug;
2930
#[cfg(feature = "std")]
3031
use xsupport::who;
3132

32-
pub use self::shifter::{OnReward, OnRewardCalculation};
33+
pub use self::reward::{OnReward, OnRewardCalculation};
3334
pub use self::types::*;
3435
pub use self::vote_weight::VoteWeight;
3536

xrml/xmining/staking/src/mock.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,12 @@ impl xmultisig::GenesisMultiSig<u64> for DummyGenesisMultiSig {
128128

129129
pub struct DummyDetermineIntentionJackpotAccountId;
130130
impl xaccounts::IntentionJackpotAccountIdFor<u64> for DummyDetermineIntentionJackpotAccountId {
131-
fn accountid_for(origin: &u64) -> u64 {
131+
fn accountid_for_unsafe(origin: &u64) -> u64 {
132132
origin + 100
133133
}
134+
fn accountid_for_safe(origin: &u64) -> Option<u64> {
135+
Some(origin + 100)
136+
}
134137
}
135138

136139
impl xassets::Trait for Test {

xrml/xmining/staking/src/reward.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
use super::*;
2+
use xaccounts::IntentionJackpotAccountIdFor;
3+
4+
pub trait OnRewardCalculation<AccountId: Default, Balance> {
5+
fn psedu_intentions_info() -> Vec<(RewardHolder<AccountId>, Balance)>;
6+
}
7+
8+
impl<AccountId: Default, Balance> OnRewardCalculation<AccountId, Balance> for () {
9+
fn psedu_intentions_info() -> Vec<(RewardHolder<AccountId>, Balance)> {
10+
Vec::new()
11+
}
12+
}
13+
14+
pub trait OnReward<AccountId: Default, Balance> {
15+
fn reward(_: &Token, _: Balance);
16+
}
17+
18+
impl<AccountId: Default, Balance> OnReward<AccountId, Balance> for () {
19+
fn reward(_: &Token, _: Balance) {}
20+
}
21+
22+
impl<T: Trait> Module<T> {
23+
/// Get the reward for the session, assuming it ends with this block.
24+
fn this_session_reward() -> T::Balance {
25+
let current_index = <xsession::Module<T>>::current_index().as_();
26+
let reward = Self::initial_reward().as_()
27+
/ u64::from(u32::pow(2, (current_index / SESSIONS_PER_ROUND) as u32));
28+
T::Balance::sa(reward as u64)
29+
}
30+
31+
/// Reward a given (potential) validator by a specific amount.
32+
/// Add the reward to their balance, and their jackpot, pro-rata.
33+
fn reward(who: &T::AccountId, reward: T::Balance) {
34+
// Validator only gains 10%, the rest 90% goes to the jackpot.
35+
let off_the_table = T::Balance::sa(reward.as_() / 10);
36+
let _ = <xassets::Module<T>>::pcx_issue(who, off_the_table);
37+
38+
let to_jackpot = reward - off_the_table;
39+
// issue to jackpot
40+
let jackpot_addr = T::DetermineIntentionJackpotAccountId::accountid_for_unsafe(who);
41+
let _ = <xassets::Module<T>>::pcx_issue(&jackpot_addr, to_jackpot);
42+
debug!(
43+
"[reward] issue to {:?}'s jackpot: {:?}",
44+
who!(who),
45+
to_jackpot
46+
);
47+
}
48+
49+
/// Collect the active intentions and psedu intentions.
50+
fn collect_reward_holders() -> Vec<(RewardHolder<T::AccountId>, T::Balance)> {
51+
let mut active_intentions = Self::intention_set()
52+
.into_iter()
53+
.filter(|i| Self::is_active(i))
54+
.map(|id| {
55+
let total_nomination = Self::total_nomination_of(&id);
56+
(RewardHolder::Intention(id), total_nomination)
57+
})
58+
.collect::<Vec<_>>();
59+
60+
// Extend non-intention reward holders, i.e., Tokens currently, who are always considered as active.
61+
let psedu_intentions = T::OnRewardCalculation::psedu_intentions_info();
62+
active_intentions.extend(psedu_intentions);
63+
64+
active_intentions
65+
}
66+
67+
/// In the first round, 20% reward of each session goes to the team.
68+
fn try_fund_team(this_session_reward: T::Balance) -> T::Balance {
69+
let current_index = <xsession::Module<T>>::current_index().as_();
70+
71+
if current_index < SESSIONS_PER_ROUND {
72+
let to_team = T::Balance::sa(this_session_reward.as_() / 5);
73+
debug!("[reward] issue to the team: {:?}", to_team);
74+
let _ =
75+
<xassets::Module<T>>::pcx_issue(&xaccounts::Module::<T>::team_account(), to_team);
76+
this_session_reward - to_team
77+
} else {
78+
this_session_reward
79+
}
80+
}
81+
82+
/// Distribute the session reward for (psedu-)intentions.
83+
pub(super) fn distribute_session_reward(validators: &mut Vec<T::AccountId>) {
84+
// apply good session reward
85+
let this_session_reward = Self::this_session_reward();
86+
87+
let mut session_reward = Self::try_fund_team(this_session_reward);
88+
89+
let active_intentions = Self::collect_reward_holders();
90+
91+
let mut total_active_stake = active_intentions
92+
.iter()
93+
.fold(Zero::zero(), |acc: T::Balance, (_, x)| acc + *x);
94+
95+
Self::deposit_event(RawEvent::Reward(total_active_stake, this_session_reward));
96+
97+
for (holder, stake) in active_intentions.iter() {
98+
// May become zero after meeting the last one.
99+
if !total_active_stake.is_zero() {
100+
// stake * session_reward could overflow.
101+
let reward = match (u128::from(stake.as_()))
102+
.checked_mul(u128::from(session_reward.as_()))
103+
{
104+
Some(x) => {
105+
let r = x / u128::from(total_active_stake.as_());
106+
if r < u128::from(u64::max_value()) {
107+
T::Balance::sa(r as u64)
108+
} else {
109+
panic!("reward of per intention definitely less than u64::max_value()")
110+
}
111+
}
112+
None => panic!("stake * session_reward overflow!"),
113+
};
114+
match holder {
115+
RewardHolder::Intention(ref intention) => {
116+
Self::reward(intention, reward);
117+
118+
// It the intention was an offline validator, we should enforce a slash.
119+
if <MissedOfPerSession<T>>::exists(intention) {
120+
// FIXME Don't pass validators in slash_active_offline_validator()
121+
Self::slash_active_offline_validator(intention, reward, validators);
122+
}
123+
}
124+
RewardHolder::PseduIntention(ref token) => {
125+
// Reward to token entity.
126+
T::OnReward::reward(token, reward)
127+
}
128+
}
129+
total_active_stake -= *stake;
130+
session_reward -= reward;
131+
}
132+
}
133+
}
134+
}

0 commit comments

Comments
 (0)