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