-
Notifications
You must be signed in to change notification settings - Fork 208
/
update_exchange_rates.go
122 lines (97 loc) · 4.22 KB
/
update_exchange_rates.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
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/NibiruChain/collections"
"github.com/NibiruChain/nibiru/x/oracle/types"
)
// UpdateExchangeRates updates the ExchangeRates, this is supposed to be executed on EndBlock.
func (k Keeper) UpdateExchangeRates(ctx sdk.Context) {
k.Logger(ctx).Info("processing validator price votes")
k.resetExchangeRates(ctx)
validatorPerformanceMap := k.newValidatorPerformanceMap(ctx)
pairBallotMap, whitelistedPairsMap := k.getPairBallotMapAndWhitelistedPairsMap(ctx, validatorPerformanceMap)
k.countVotesAndUpdateExchangeRates(ctx, pairBallotMap, validatorPerformanceMap)
k.registerMissedVotes(ctx, whitelistedPairsMap, validatorPerformanceMap)
k.rewardBallotWinners(ctx, whitelistedPairsMap, validatorPerformanceMap)
params := k.GetParams(ctx)
k.clearBallots(ctx, params.VotePeriod)
k.applyWhitelist(ctx, params.Whitelist, whitelistedPairsMap)
}
// registerMissedVotes it parses all validators performance and increases the missed vote of those that did not vote.
func (k Keeper) registerMissedVotes(ctx sdk.Context, whitelistedPairsMap map[string]struct{}, validatorPerformanceMap map[string]types.ValidatorPerformance) {
whitelistedPairsLen := len(whitelistedPairsMap)
for _, validatorPerformance := range validatorPerformanceMap {
if int(validatorPerformance.WinCount) == whitelistedPairsLen {
continue
}
k.MissCounters.Insert(ctx, validatorPerformance.ValAddress, k.MissCounters.GetOr(ctx, validatorPerformance.ValAddress, 0)+1)
k.Logger(ctx).Info("vote miss", "validator", validatorPerformance.ValAddress.String())
}
}
// countVotesAndUpdateExchangeRates processes the votes and updates the ExchangeRates based on the results.
func (k Keeper) countVotesAndUpdateExchangeRates(
ctx sdk.Context,
pairBallotMap map[string]types.ExchangeRateBallot,
validatorPerformanceMap map[string]types.ValidatorPerformance,
) {
params := k.GetParams(ctx)
for pair, ballot := range pairBallotMap {
exchangeRate := Tally(ballot, params.RewardBand, validatorPerformanceMap)
k.ExchangeRates.Insert(ctx, pair, exchangeRate)
ctx.EventManager().EmitEvent(
sdk.NewEvent(types.EventTypeExchangeRateUpdate,
sdk.NewAttribute(types.AttributeKeyPair, pair),
sdk.NewAttribute(types.AttributeKeyExchangeRate, exchangeRate.String()),
),
)
}
}
// getPairBallotMapAndWhitelistedPairsMap returns a map of pairs and ballots excluding invalid Ballots
// and a map with all whitelisted pairs.
func (k Keeper) getPairBallotMapAndWhitelistedPairsMap(
ctx sdk.Context,
validatorPerformanceMap map[string]types.ValidatorPerformance,
) (map[string]types.ExchangeRateBallot, map[string]struct{}) {
pairBallotMap := k.mapBallotByPair(ctx, validatorPerformanceMap)
return k.RemoveInvalidBallots(ctx, pairBallotMap)
}
// getWhitelistedPairsMap returns a map containing all the pairs as the key.
func (k Keeper) getWhitelistedPairsMap(ctx sdk.Context) map[string]struct{} {
pairsMap := make(map[string]struct{})
for _, p := range k.GetWhitelistedPairs(ctx) {
pairsMap[p] = struct{}{}
}
return pairsMap
}
// resetExchangeRates removes all exchange rates from the state
func (k Keeper) resetExchangeRates(ctx sdk.Context) {
for _, key := range k.ExchangeRates.Iterate(ctx, collections.Range[string]{}).Keys() {
err := k.ExchangeRates.Delete(ctx, key)
if err != nil {
panic(err)
}
}
}
// newValidatorPerformanceMap creates a new map of validators and their performance, excluding validators that are
// not bonded.
func (k Keeper) newValidatorPerformanceMap(ctx sdk.Context) map[string]types.ValidatorPerformance {
validatorPerformanceMap := make(map[string]types.ValidatorPerformance)
maxValidators := k.StakingKeeper.MaxValidators(ctx)
powerReduction := k.StakingKeeper.PowerReduction(ctx)
iterator := k.StakingKeeper.ValidatorsPowerStoreIterator(ctx)
defer iterator.Close()
i := 0
for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
validator := k.StakingKeeper.Validator(ctx, iterator.Value())
// exclude not bonded
if !validator.IsBonded() {
continue
}
valAddr := validator.GetOperator()
validatorPerformanceMap[valAddr.String()] = types.NewValidatorPerformance(
validator.GetConsensusPower(powerReduction), valAddr,
)
i++
}
return validatorPerformanceMap
}