@@ -305,6 +305,15 @@ const STAKING_ID: LockIdentifier = *b"staking ";
305305/// Counter for the number of eras that have passed.
306306pub type EraIndex = u32 ;
307307
308+ /// Reward of an era.
309+ #[ derive( Encode , Decode , Default ) ]
310+ pub struct EraRewards {
311+ total : u32 ,
312+ /// Reward at one index correspond to reward for validator in current_elected of this index.
313+ /// Thus this reward vec is only valid for one elected set.
314+ rewards : Vec < u32 > ,
315+ }
316+
308317/// Indicates the initial status of the staker.
309318#[ cfg_attr( feature = "std" , derive( Debug , Serialize , Deserialize ) ) ]
310319pub enum StakerStatus < AccountId > {
@@ -483,8 +492,6 @@ decl_storage! {
483492 /// Minimum number of staking participants before emergency conditions are imposed.
484493 pub MinimumValidatorCount get( minimum_validator_count) config( ) :
485494 u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT ;
486- /// Maximum reward, per validator, that is provided per acceptable session.
487- pub SessionReward get( session_reward) config( ) : Perbill = Perbill :: from_parts( 60 ) ;
488495 /// Slash, per validator that is taken for the first time they are found to be offline.
489496 pub OfflineSlash get( offline_slash) config( ) : Perbill = Perbill :: from_millionths( 1000 ) ;
490497 /// Number of instances of offline reports before slashing begins for validators.
@@ -531,14 +538,11 @@ decl_storage! {
531538 /// The current era index.
532539 pub CurrentEra get( current_era) config( ) : EraIndex ;
533540
534- /// The accumulated reward for the current era. Reset to zero at the beginning of the era and
535- /// increased for every successfully finished session.
541+ /// The start of the current era.
536542 pub CurrentEraStart get( current_era_start) : T :: Moment ;
537543
538- /// A vec of validator to reward and their associated number of points.
539- /// A validator can appear in many elements of this vec.
540- // TODO TODO: should we use such a structure ? aggregate with an existing one ? use a map ?
541- pub CurrentEraRewards : Vec <( T :: AccountId , u32 ) >;
544+ /// Rewards for the current era. Using indices of current elected set.
545+ pub CurrentEraRewards : EraRewards ;
542546
543547 /// The amount of balance actively at stake for each validator slot, currently.
544548 ///
@@ -905,8 +909,18 @@ decl_module! {
905909 ///
906910 /// At the end of the era each the total payout will be distributed among validator
907911 /// relatively to their points.
908- fn add_reward_points_to_validators( add: Vec <( T :: AccountId , u32 ) >) {
909- <CurrentEraRewards <T >>:: append( & add[ ..] ) . unwrap( ) ;
912+ fn add_reward_points_to_validator( validator: T :: AccountId , points: u32 ) {
913+ <Module <T >>:: current_elected( ) . iter( )
914+ . position( |elected| * elected == validator)
915+ . map( |index| {
916+ <CurrentEraRewards <T >>:: mutate( |rewards| {
917+ if let Some ( new_total) = rewards. total. checked_add( points) {
918+ rewards. total = new_total;
919+ rewards. rewards. resize( index + 1 , 0 ) ;
920+ rewards. rewards[ index] += points; // Addition is less than total
921+ }
922+ } )
923+ } ) ;
910924 }
911925 }
912926}
@@ -1018,8 +1032,6 @@ impl<T: Trait> Module<T> {
10181032
10191033 /// Session has just ended. Provide the validator set for the next session if it's an era-end.
10201034 fn new_session ( session_index : SessionIndex ) -> Option < Vec < T :: AccountId > > {
1021- // TODO TODO: previous implementation was accumulating reward here, should we accumulate
1022- // duration in a way ?
10231035 if <ForceNewEra < T > >:: take ( ) || session_index % T :: SessionsPerEra :: get ( ) == 0 {
10241036 Self :: new_era ( )
10251037 } else {
@@ -1045,34 +1057,21 @@ impl<T: Trait> Module<T> {
10451057 let validator_len: BalanceOf < T > = ( validators. len ( ) as u32 ) . into ( ) ;
10461058 let total_rewarded_stake = Self :: slot_stake ( ) * validator_len;
10471059
1048- let mut total_points = 0u32 ;
1049- let mut points_for_validator = BTreeMap :: new ( ) ;
1050- for ( validator, reward) in rewards {
1051- // If the total number of points exceed u32::MAX then they are dismissed
1052- // TODO TODO: if this is a problem we can use u64
1053- if let Some ( p) = total_points. checked_add ( reward) {
1054- total_points = p;
1055-
1056- // Cannot overflow as inferior to total_points
1057- * points_for_validator. entry ( validator) . or_insert ( 0 ) += reward;
1058- }
1059- }
1060-
1061- // TODO TODO: does this should be generic ?
10621060 let total_payout = inflation:: compute_total_payout (
10631061 total_rewarded_stake. clone ( ) ,
10641062 T :: Currency :: total_issuance ( ) ,
10651063 <BalanceOf < T > >:: from (
1066- // Era of duration more than u32::MAX is rewarded as u32::max_value .
1064+ // Era of duration more than u32::MAX is rewarded as u32::MAX .
10671065 TryInto :: < u32 > :: try_into ( era_duration) . unwrap_or ( u32:: max_value ( ) )
10681066 ) ,
10691067 ) ;
10701068
10711069 let mut total_imbalance = <PositiveImbalanceOf < T > >:: zero ( ) ;
10721070
1073- for v in validators. iter ( ) {
1074- if let Some ( & points) = points_for_validator. get ( v) {
1075- let reward = multiply_by_fraction ( total_payout, points, total_points) ;
1071+ let total_points = rewards. total ;
1072+ for ( v, points) in validators. iter ( ) . zip ( rewards. rewards . into_iter ( ) ) {
1073+ if points != 0 {
1074+ let reward = multiply_by_rational ( total_payout, points, total_points) ;
10761075 total_imbalance. subsume ( Self :: reward_validator ( v, reward) ) ;
10771076 }
10781077 }
@@ -1289,7 +1288,7 @@ impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
12891288
12901289// This is guarantee not to overflow on whatever values.
12911290// `num` must be inferior to `den` otherwise it will be reduce to `den`.
1292- fn multiply_by_fraction < N > ( value : N , num : u32 , den : u32 ) -> N
1291+ fn multiply_by_rational < N > ( value : N , num : u32 , den : u32 ) -> N
12931292 where N : SimpleArithmetic + Clone
12941293{
12951294 let num = num. min ( den) ;
@@ -1303,8 +1302,7 @@ fn multiply_by_fraction<N>(value: N, num: u32, den: u32) -> N
13031302 let rem_u32 = rem. saturated_into :: < u32 > ( ) ;
13041303
13051304 // Multiplication fits into u64 as both term are u32
1306- let rem_part = rem_u32 as u64 * num as u64
1307- / den as u64 ;
1305+ let rem_part = rem_u32 as u64 * num as u64 / den as u64 ;
13081306
13091307 // Result fits into u32 as num < total_points
13101308 ( rem_part as u32 ) . into ( )
0 commit comments