github.com/Finschia/finschia-sdk@v0.48.1/x/distribution/keeper/validator.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 6 sdk "github.com/Finschia/finschia-sdk/types" 7 8 "github.com/Finschia/finschia-sdk/x/distribution/types" 9 stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" 10 ) 11 12 // initialize rewards for a new validator 13 func (k Keeper) initializeValidator(ctx sdk.Context, val stakingtypes.ValidatorI) { 14 // set initial historical rewards (period 0) with reference count of 1 15 k.SetValidatorHistoricalRewards(ctx, val.GetOperator(), 0, types.NewValidatorHistoricalRewards(sdk.DecCoins{}, 1)) 16 17 // set current rewards (starting at period 1) 18 k.SetValidatorCurrentRewards(ctx, val.GetOperator(), types.NewValidatorCurrentRewards(sdk.DecCoins{}, 1)) 19 20 // set accumulated commission 21 k.SetValidatorAccumulatedCommission(ctx, val.GetOperator(), types.InitialValidatorAccumulatedCommission()) 22 23 // set outstanding rewards 24 k.SetValidatorOutstandingRewards(ctx, val.GetOperator(), types.ValidatorOutstandingRewards{Rewards: sdk.DecCoins{}}) 25 } 26 27 // increment validator period, returning the period just ended 28 func (k Keeper) IncrementValidatorPeriod(ctx sdk.Context, val stakingtypes.ValidatorI) uint64 { 29 // fetch current rewards 30 rewards := k.GetValidatorCurrentRewards(ctx, val.GetOperator()) 31 32 // calculate current ratio 33 var current sdk.DecCoins 34 if val.GetTokens().IsZero() { 35 36 // can't calculate ratio for zero-token validators 37 // ergo we instead add to the community pool 38 feePool := k.GetFeePool(ctx) 39 outstanding := k.GetValidatorOutstandingRewards(ctx, val.GetOperator()) 40 feePool.CommunityPool = feePool.CommunityPool.Add(rewards.Rewards...) 41 outstanding.Rewards = outstanding.GetRewards().Sub(rewards.Rewards) 42 k.SetFeePool(ctx, feePool) 43 k.SetValidatorOutstandingRewards(ctx, val.GetOperator(), outstanding) 44 45 current = sdk.DecCoins{} 46 } else { 47 // note: necessary to truncate so we don't allow withdrawing more rewards than owed 48 current = rewards.Rewards.QuoDecTruncate(val.GetTokens().ToDec()) 49 } 50 51 // fetch historical rewards for last period 52 historical := k.GetValidatorHistoricalRewards(ctx, val.GetOperator(), rewards.Period-1).CumulativeRewardRatio 53 54 // decrement reference count 55 k.decrementReferenceCount(ctx, val.GetOperator(), rewards.Period-1) 56 57 // set new historical rewards with reference count of 1 58 k.SetValidatorHistoricalRewards(ctx, val.GetOperator(), rewards.Period, types.NewValidatorHistoricalRewards(historical.Add(current...), 1)) 59 60 // set current rewards, incrementing period by 1 61 k.SetValidatorCurrentRewards(ctx, val.GetOperator(), types.NewValidatorCurrentRewards(sdk.DecCoins{}, rewards.Period+1)) 62 63 return rewards.Period 64 } 65 66 // increment the reference count for a historical rewards value 67 func (k Keeper) incrementReferenceCount(ctx sdk.Context, valAddr sdk.ValAddress, period uint64) { 68 historical := k.GetValidatorHistoricalRewards(ctx, valAddr, period) 69 if historical.ReferenceCount > 2 { 70 panic("reference count should never exceed 2") 71 } 72 historical.ReferenceCount++ 73 k.SetValidatorHistoricalRewards(ctx, valAddr, period, historical) 74 } 75 76 // decrement the reference count for a historical rewards value, and delete if zero references remain 77 func (k Keeper) decrementReferenceCount(ctx sdk.Context, valAddr sdk.ValAddress, period uint64) { 78 historical := k.GetValidatorHistoricalRewards(ctx, valAddr, period) 79 if historical.ReferenceCount == 0 { 80 panic("cannot set negative reference count") 81 } 82 historical.ReferenceCount-- 83 if historical.ReferenceCount == 0 { 84 k.DeleteValidatorHistoricalReward(ctx, valAddr, period) 85 } else { 86 k.SetValidatorHistoricalRewards(ctx, valAddr, period, historical) 87 } 88 } 89 90 func (k Keeper) updateValidatorSlashFraction(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) { 91 if fraction.GT(sdk.OneDec()) || fraction.IsNegative() { 92 panic(fmt.Sprintf("fraction must be >=0 and <=1, current fraction: %v", fraction)) 93 } 94 95 val := k.stakingKeeper.Validator(ctx, valAddr) 96 97 // increment current period 98 newPeriod := k.IncrementValidatorPeriod(ctx, val) 99 100 // increment reference count on period we need to track 101 k.incrementReferenceCount(ctx, valAddr, newPeriod) 102 103 slashEvent := types.NewValidatorSlashEvent(newPeriod, fraction) 104 height := uint64(ctx.BlockHeight()) 105 106 k.SetValidatorSlashEvent(ctx, valAddr, height, newPeriod, slashEvent) 107 }