forked from cosmos/cosmos-sdk
/
validator.go
171 lines (141 loc) · 5.56 KB
/
validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
// check whether a validator has distribution info
func (k Keeper) HasValidatorDistInfo(ctx sdk.Context,
operatorAddr sdk.ValAddress) (exists bool) {
store := ctx.KVStore(k.storeKey)
return store.Has(GetValidatorDistInfoKey(operatorAddr))
}
// get the validator distribution info
func (k Keeper) GetValidatorDistInfo(ctx sdk.Context,
operatorAddr sdk.ValAddress) (vdi types.ValidatorDistInfo) {
store := ctx.KVStore(k.storeKey)
b := store.Get(GetValidatorDistInfoKey(operatorAddr))
if b == nil {
panic("Stored validator-distribution info should not have been nil")
}
k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &vdi)
return
}
// set the validator distribution info
func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInfo) {
store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinaryLengthPrefixed(vdi)
store.Set(GetValidatorDistInfoKey(vdi.OperatorAddr), b)
}
// remove a validator distribution info
func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) {
// defensive check
vdi := k.GetValidatorDistInfo(ctx, valAddr)
if vdi.DelAccum.Accum.IsPositive() {
panic("Should not delete validator with unwithdrawn delegator accum")
}
if !vdi.ValCommission.IsZero() {
panic("Should not delete validator with unwithdrawn validator commission")
}
store := ctx.KVStore(k.storeKey)
store.Delete(GetValidatorDistInfoKey(valAddr))
}
// remove all validator distribution infos
func (k Keeper) RemoveValidatorDistInfos(ctx sdk.Context) {
store := ctx.KVStore(k.storeKey)
iter := sdk.KVStorePrefixIterator(store, ValidatorDistInfoKey)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
store.Delete(iter.Key())
}
}
// iterate over all the validator distribution infos
func (k Keeper) IterateValidatorDistInfos(ctx sdk.Context,
fn func(index int64, distInfo types.ValidatorDistInfo) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iter := sdk.KVStorePrefixIterator(store, ValidatorDistInfoKey)
defer iter.Close()
index := int64(0)
for ; iter.Valid(); iter.Next() {
var vdi types.ValidatorDistInfo
k.cdc.MustUnmarshalBinaryLengthPrefixed(iter.Value(), &vdi)
if fn(index, vdi) {
return
}
index++
}
}
// Get the calculated accum of a validator at the current block
// without affecting the state.
func (k Keeper) GetValidatorAccum(ctx sdk.Context, operatorAddr sdk.ValAddress) (sdk.Dec, sdk.Error) {
if !k.HasValidatorDistInfo(ctx, operatorAddr) {
return sdk.Dec{}, types.ErrNoValidatorDistInfo(k.codespace)
}
// withdraw self-delegation
height := ctx.BlockHeight()
lastValPower := k.stakeKeeper.GetLastValidatorPower(ctx, operatorAddr)
valInfo := k.GetValidatorDistInfo(ctx, operatorAddr)
accum := valInfo.GetValAccum(height, sdk.NewDecFromInt(lastValPower))
return accum, nil
}
// takeValidatorFeePoolRewards updates the validator's distribution info
// from the global fee pool without withdrawing any rewards. This will be called
// from a onValidatorModified hook.
func (k Keeper) takeValidatorFeePoolRewards(ctx sdk.Context, operatorAddr sdk.ValAddress) sdk.Error {
if !k.HasValidatorDistInfo(ctx, operatorAddr) {
return types.ErrNoValidatorDistInfo(k.codespace)
}
accAddr := sdk.AccAddress(operatorAddr.Bytes())
// withdraw reward for self-delegation
if k.HasDelegationDistInfo(ctx, accAddr, operatorAddr) {
fp, vi, di, withdraw :=
k.withdrawDelegationReward(ctx, accAddr, operatorAddr)
k.SetFeePool(ctx, fp)
k.SetValidatorDistInfo(ctx, vi)
k.SetDelegationDistInfo(ctx, di)
k.WithdrawToDelegator(ctx, fp, accAddr, withdraw)
}
// withdrawal validator commission rewards
valInfo := k.GetValidatorDistInfo(ctx, operatorAddr)
wc := k.GetWithdrawContext(ctx, operatorAddr)
valInfo, feePool := valInfo.TakeFeePoolRewards(wc)
k.SetFeePool(ctx, feePool)
k.SetValidatorDistInfo(ctx, valInfo)
return nil
}
func (k Keeper) withdrawValidatorCommission(ctx sdk.Context, operatorAddr sdk.ValAddress) (types.FeePool, types.DecCoins) {
valInfo := k.GetValidatorDistInfo(ctx, operatorAddr)
wc := k.GetWithdrawContext(ctx, operatorAddr)
valInfo, feePool, commission := valInfo.WithdrawCommission(wc)
k.SetValidatorDistInfo(ctx, valInfo)
return feePool, commission
}
// withdrawal all the validator rewards including the commission
func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.ValAddress) sdk.Error {
if !k.HasValidatorDistInfo(ctx, operatorAddr) {
return types.ErrNoValidatorDistInfo(k.codespace)
}
// withdraw self-delegation
accAddr := sdk.AccAddress(operatorAddr.Bytes())
withdraw := k.withdrawDelegationRewardsAll(ctx, accAddr)
// withdrawal validator commission rewards
feePool, commission := k.withdrawValidatorCommission(ctx, operatorAddr)
withdraw = withdraw.Plus(commission)
k.WithdrawToDelegator(ctx, feePool, accAddr, withdraw)
return nil
}
// get all the validator rewards including the commission
func (k Keeper) CurrentValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.ValAddress) (sdk.Coins, sdk.Error) {
if !k.HasValidatorDistInfo(ctx, operatorAddr) {
return sdk.Coins{}, types.ErrNoValidatorDistInfo(k.codespace)
}
// withdraw self-delegation
accAddr := sdk.AccAddress(operatorAddr.Bytes())
withdraw := k.CurrentDelegationRewardsAll(ctx, accAddr)
// withdrawal validator commission rewards
valInfo := k.GetValidatorDistInfo(ctx, operatorAddr)
wc := k.GetWithdrawContext(ctx, operatorAddr)
commission := valInfo.CurrentCommissionRewards(wc)
withdraw = withdraw.Plus(commission)
truncated, _ := withdraw.TruncateDecimal()
return truncated, nil
}