Skip to content

Commit

Permalink
Merge branch 'realu/refactor-no-unnamed' into realu/oracle-miss
Browse files Browse the repository at this point in the history
  • Loading branch information
Unique-Divine committed Sep 5, 2023
2 parents 8b9dae1 + 9adc9e4 commit c6a592d
Show file tree
Hide file tree
Showing 17 changed files with 1,750 additions and 1,692 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1536](https://github.com/NibiruChain/nibiru/pull/1536) - test(perp): add more tests to perp module and cli
* [#1533](https://github.com/NibiruChain/nibiru/pull/1533) - feat(perp): add differential fields to PositionChangedEvent
* [#1541](https://github.com/NibiruChain/nibiru/pull/1541) - feat(perp): add clamp to premium fractions
* [#1556](https://github.com/NibiruChain/nibiru/pull/1556) - refactor(perp): remove usage of unnamed dot imports
* [#1555](https://github.com/NibiruChain/nibiru/pull/1555) - feat(devgas): Convert legacy ABCI events to typed proto events
* [#1558](https://github.com/NibiruChain/nibiru/pull/1558) - feat(perp): paginated query to read the position store
* [#1554](https://github.com/NibiruChain/nibiru/pull/1554) - refactor: runs gofumpt formatter, which has nice conventions: go install mvdan.cc/gofumpt@latest
Expand Down
31 changes: 21 additions & 10 deletions x/oracle/keeper/ballot.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,17 @@ func (k Keeper) removeInvalidBallots(
return pairBallotsMap, whitelistedPairs
}

// Tally calculates the median and returns it. Sets the set of voters to be rewarded, i.e. voted within
// a reasonable spread from the weighted median to the store
// Tally calculates the median and returns it. Sets the set of voters to be
// rewarded, i.e. voted within a reasonable spread from the weighted median to
// the store.
//
// ALERT: This function mutates validatorPerformances slice based on the votes made by the validators.
func Tally(ballots types.ExchangeRateBallots, rewardBand sdk.Dec, validatorPerformances types.ValidatorPerformances) sdk.Dec {
// ALERT: This function mutates validatorPerformances slice based on the votes
// made by the validators.
func Tally(
ballots types.ExchangeRateBallots,
rewardBand sdk.Dec,
validatorPerformances types.ValidatorPerformances,
) sdk.Dec {
weightedMedian := ballots.WeightedMedianWithAssertion()
standardDeviation := ballots.StandardDeviation(weightedMedian)
rewardSpread := weightedMedian.Mul(rewardBand.QuoInt64(2))
Expand All @@ -155,15 +161,20 @@ func Tally(ballots types.ExchangeRateBallots, rewardBand sdk.Dec, validatorPerfo
voteInsideSpread := ballot.ExchangeRate.GTE(weightedMedian.Sub(rewardSpread)) &&
ballot.ExchangeRate.LTE(weightedMedian.Add(rewardSpread))
isAbstainVote := !ballot.ExchangeRate.IsPositive()

if voteInsideSpread || isAbstainVote {
voterAddr := ballot.Voter.String()

validatorPerformance := validatorPerformances[voterAddr]
isMiss := !(voteInsideSpread || isAbstainVote)

voterAddr := ballot.Voter.String()
validatorPerformance := validatorPerformances[voterAddr]
switch {
case isAbstainVote:
validatorPerformance.AbstainCount++
case voteInsideSpread:
validatorPerformance.RewardWeight += ballot.Power
validatorPerformance.WinCount++
validatorPerformances[voterAddr] = validatorPerformance
case isMiss:
validatorPerformance.MissCount++
}
validatorPerformances[voterAddr] = validatorPerformance
}

return weightedMedian
Expand Down
7 changes: 5 additions & 2 deletions x/oracle/keeper/slash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,10 @@ func TestWhitelistSlashing(t *testing.T) {
slashFraction := input.OracleKeeper.SlashFraction(input.Ctx)
minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx)

for i := uint64(0); i < uint64(sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64()); i++ {
allowedMissPct := sdk.OneDec().Sub(minValidPerWindow)
allowedMissPeriods := allowedMissPct.MulInt64(votePeriodsPerWindow).
TruncateInt64()
for idxMissPeriod := uint64(0); idxMissPeriod < uint64(allowedMissPeriods); idxMissPeriod++ {
input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1)

// Account 2, govstable
Expand All @@ -181,7 +184,7 @@ func TestWhitelistSlashing(t *testing.T) {
input.OracleKeeper.UpdateExchangeRates(input.Ctx)
// input.OracleKeeper.SlashAndResetMissCounters(input.Ctx)
// input.OracleKeeper.UpdateExchangeRates(input.Ctx)
require.Equal(t, i+1, input.OracleKeeper.MissCounters.GetOr(input.Ctx, ValAddrs[0], 0))
require.Equal(t, idxMissPeriod+1, input.OracleKeeper.MissCounters.GetOr(input.Ctx, ValAddrs[0], 0))
}

validator := input.StakingKeeper.Validator(input.Ctx, ValAddrs[0])
Expand Down
22 changes: 14 additions & 8 deletions x/oracle/keeper/update_exchange_rates.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,25 @@ func (k Keeper) UpdateExchangeRates(ctx sdk.Context) {
k.updateWhitelist(ctx, params.Whitelist, whitelistedPairs)
}

// registerMissedVotes it parses all validators performance and increases the missed vote of those that did not vote.
func (k Keeper) registerMissedVotes(ctx sdk.Context, whitelistedPairs set.Set[asset.Pair], validatorPerformances types.ValidatorPerformances) {
// registerMissedVotes it parses all validators performance and increases the
// missed vote of those that did not vote.
func (k Keeper) registerMissedVotes(
ctx sdk.Context,
whitelistedPairs set.Set[asset.Pair],
validatorPerformances types.ValidatorPerformances,
) {
for _, validatorPerformance := range validatorPerformances {
if int(validatorPerformance.WinCount) == len(whitelistedPairs) {
continue
if int(validatorPerformance.MissCount) > 0 {
k.MissCounters.Insert(
ctx, validatorPerformance.ValAddress,
k.MissCounters.GetOr(ctx, validatorPerformance.ValAddress, 0)+1)
k.Logger(ctx).Info("vote miss", "validator", validatorPerformance.ValAddress.String())
}

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.
// countVotesAndUpdateExchangeRates processes the votes and updates the
// ExchangeRates based on the results.
func (k Keeper) countVotesAndUpdateExchangeRates(
ctx sdk.Context,
pairBallotsMap map[asset.Pair]types.ExchangeRateBallots,
Expand Down
38 changes: 19 additions & 19 deletions x/oracle/keeper/update_exchange_rates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,10 @@ func TestOracleTally(t *testing.T) {

validatorClaimMap := make(types.ValidatorPerformances)
for _, valAddr := range valAddrs {
validatorClaimMap[valAddr.String()] = types.ValidatorPerformance{
Power: stakingKeeper.Validator(fixture.Ctx, valAddr).GetConsensusPower(sdk.DefaultPowerReduction),
RewardWeight: int64(0),
WinCount: int64(0),
ValAddress: valAddr,
}
validatorClaimMap[valAddr.String()] = types.NewValidatorPerformance(
stakingKeeper.Validator(fixture.Ctx, valAddr).GetConsensusPower(sdk.DefaultPowerReduction),
valAddr,
)
}
sort.Sort(ballot)
weightedMedian := ballot.WeightedMedianWithAssertion()
Expand All @@ -188,27 +186,29 @@ func TestOracleTally(t *testing.T) {

expectedValidatorClaimMap := make(types.ValidatorPerformances)
for _, valAddr := range valAddrs {
expectedValidatorClaimMap[valAddr.String()] = types.ValidatorPerformance{
Power: stakingKeeper.Validator(fixture.Ctx, valAddr).GetConsensusPower(sdk.DefaultPowerReduction),
RewardWeight: int64(0),
WinCount: int64(0),
ValAddress: valAddr,
}
expectedValidatorClaimMap[valAddr.String()] = types.NewValidatorPerformance(
stakingKeeper.Validator(fixture.Ctx, valAddr).GetConsensusPower(sdk.DefaultPowerReduction),
valAddr,
)
}

for _, vote := range ballot {
if (vote.ExchangeRate.GTE(weightedMedian.Sub(maxSpread)) &&
vote.ExchangeRate.LTE(weightedMedian.Add(maxSpread))) ||
!vote.ExchangeRate.IsPositive() {
key := vote.Voter.String()
claim := expectedValidatorClaimMap[key]
key := vote.Voter.String()
claim := expectedValidatorClaimMap[key]
if vote.ExchangeRate.GTE(weightedMedian.Sub(maxSpread)) &&
vote.ExchangeRate.LTE(weightedMedian.Add(maxSpread)) {
claim.RewardWeight += vote.Power
claim.WinCount++
expectedValidatorClaimMap[key] = claim
} else if !vote.ExchangeRate.IsPositive() {
claim.AbstainCount++
} else {
claim.MissCount++
}
expectedValidatorClaimMap[key] = claim
}

tallyMedian := Tally(ballot, fixture.OracleKeeper.RewardBand(fixture.Ctx), validatorClaimMap)
tallyMedian := Tally(
ballot, fixture.OracleKeeper.RewardBand(fixture.Ctx), validatorClaimMap)

assert.Equal(t, expectedValidatorClaimMap, validatorClaimMap)
assert.Equal(t, tallyMedian.MulInt64(100).TruncateInt(), weightedMedian.MulInt64(100).TruncateInt())
Expand Down
13 changes: 10 additions & 3 deletions x/oracle/types/ballot.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,14 @@ func (pb ExchangeRateBallots) Swap(i, j int) {

// ValidatorPerformance keeps track of a validator performance in the voting period.
type ValidatorPerformance struct {
Power int64 // tendermint consensus power
RewardWeight int64 // how much of the rewards this validator should receive, units of consensus power
WinCount int64
// Tendermint consensus voting power
Power int64
// RewardWeight: Weight of rewards the validator should receive in units of
// consensus power.
RewardWeight int64
WinCount int64 // Number of valid votes for which the validator will be rewarded
AbstainCount int64 // Number of abstained votes for which there will be no reward or punishment
MissCount int64 // Number of invalid/punishable votes
ValAddress sdk.ValAddress
}

Expand All @@ -185,6 +190,8 @@ func NewValidatorPerformance(power int64, recipient sdk.ValAddress) ValidatorPer
Power: power,
RewardWeight: 0,
WinCount: 0,
AbstainCount: 0,
MissCount: 0,
ValAddress: recipient,
}
}
Expand Down
28 changes: 14 additions & 14 deletions x/perp/v2/keeper/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"

. "github.com/NibiruChain/nibiru/x/common/testutil/action"
"github.com/NibiruChain/nibiru/x/common/testutil/mock"
. "github.com/NibiruChain/nibiru/x/perp/v2/integration/action"
. "github.com/NibiruChain/nibiru/x/perp/v2/integration/assertion"
tutilaction "github.com/NibiruChain/nibiru/x/common/testutil/action"
tutilmock "github.com/NibiruChain/nibiru/x/common/testutil/mock"
perpaction "github.com/NibiruChain/nibiru/x/perp/v2/integration/action"
perpassert "github.com/NibiruChain/nibiru/x/perp/v2/integration/assertion"
"github.com/NibiruChain/nibiru/x/perp/v2/keeper"

"github.com/NibiruChain/nibiru/app"
Expand Down Expand Up @@ -91,28 +91,28 @@ func TestAdmin_WithdrawFromInsuranceFund(t *testing.T) {
func TestEnableMarket(t *testing.T) {
pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD)

tests := TestCases{
TC("true -> false").
tests := tutilaction.TestCases{
tutilaction.TC("true -> false").
Given(
CreateCustomMarket(pair),
MarketShouldBeEqual(pair, Market_EnableShouldBeEqualTo(true)),
perpaction.CreateCustomMarket(pair),
perpassert.MarketShouldBeEqual(pair, perpassert.Market_EnableShouldBeEqualTo(true)),
).
When(
SetMarketEnabled(pair, false),
MarketShouldBeEqual(pair, Market_EnableShouldBeEqualTo(false)),
SetMarketEnabled(pair, true),
perpaction.SetMarketEnabled(pair, false),
perpassert.MarketShouldBeEqual(pair, perpassert.Market_EnableShouldBeEqualTo(false)),
perpaction.SetMarketEnabled(pair, true),
).
Then(
MarketShouldBeEqual(pair, Market_EnableShouldBeEqualTo(true)),
perpassert.MarketShouldBeEqual(pair, perpassert.Market_EnableShouldBeEqualTo(true)),
),
}

NewTestSuite(t).WithTestCases(tests...).Run()
tutilaction.NewTestSuite(t).WithTestCases(tests...).Run()
}

func TestCreateMarketFail(t *testing.T) {
pair := asset.Registry.Pair(denoms.BTC, denoms.NUSD)
amm := *mock.TestAMMDefault()
amm := *tutilmock.TestAMMDefault()
app, ctx := testapp.NewNibiruTestAppAndContext()

// Error because of invalid market
Expand Down
Loading

0 comments on commit c6a592d

Please sign in to comment.