From 8785bd559c374419d3a378b47b6402678ea2c543 Mon Sep 17 00:00:00 2001 From: Yun Date: Wed, 20 Nov 2019 00:12:43 +0900 Subject: [PATCH] align oracle parameters to units of blocks --- x/oracle/abci_test.go | 20 ++++++++++---------- x/oracle/internal/keeper/reward.go | 4 ++-- x/oracle/internal/keeper/reward_test.go | 8 ++++---- x/oracle/internal/types/params.go | 18 +++++++++--------- x/oracle/internal/types/params_test.go | 4 ++-- x/oracle/slash_test.go | 9 +++++---- x/oracle/slashing.go | 6 +++--- x/oracle/test_utils.go | 2 ++ 8 files changed, 37 insertions(+), 34 deletions(-) diff --git a/x/oracle/abci_test.go b/x/oracle/abci_test.go index 1332e0064..a7de52efe 100644 --- a/x/oracle/abci_test.go +++ b/x/oracle/abci_test.go @@ -293,8 +293,8 @@ func TestOracleRewardDistribution(t *testing.T) { EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) - rewardDistributionWindow := input.OracleKeeper.RewardDistributionWindow(input.Ctx) - expectedRewardAmt := sdk.NewDecFromInt(rewardsAmt.QuoRaw(2)).QuoInt64(rewardDistributionWindow).TruncateInt() + votePeriodsPerWindow := sdk.NewDec(input.OracleKeeper.RewardDistributionWindow(input.Ctx)).QuoInt64(input.OracleKeeper.VotePeriod(input.Ctx)).TruncateInt64() + expectedRewardAmt := sdk.NewDecFromInt(rewardsAmt.QuoRaw(2)).QuoInt64(votePeriodsPerWindow).TruncateInt() rewards := input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[0]) require.Equal(t, expectedRewardAmt, rewards.AmountOf(core.MicroLunaDenom).TruncateInt()) rewards = input.DistrKeeper.GetValidatorOutstandingRewards(input.Ctx.WithBlockHeight(2), keeper.ValAddrs[1]) @@ -342,11 +342,11 @@ func TestInvalidVotesSlashing(t *testing.T) { params.Whitelist = types.DenomList{core.MicroKRWDenom} input.OracleKeeper.SetParams(input.Ctx, params) - slashWindow := input.OracleKeeper.SlashWindow(input.Ctx) + votePeriodsPerWindow := sdk.NewDec(input.OracleKeeper.SlashWindow(input.Ctx)).QuoInt64(input.OracleKeeper.VotePeriod(input.Ctx)).TruncateInt64() slashFraction := input.OracleKeeper.SlashFraction(input.Ctx) minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx) - for i := int64(0); i < sdk.OneDec().Sub(minValidPerWindow).MulInt64(slashWindow).TruncateInt64(); i++ { + for i := int64(0); i < sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64(); i++ { input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) // Account 1, KRW @@ -375,7 +375,7 @@ func TestInvalidVotesSlashing(t *testing.T) { // Account 3, KRW makePrevoteAndVote(t, input, h, 0, core.MicroKRWDenom, randomExchangeRate, 2) - input.Ctx = input.Ctx.WithBlockHeight(slashWindow - 1) + input.Ctx = input.Ctx.WithBlockHeight(votePeriodsPerWindow - 1) EndBlocker(input.Ctx, input.OracleKeeper) validator = input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[1]) require.Equal(t, sdk.OneDec().Sub(slashFraction).MulInt(stakingAmt).TruncateInt(), validator.GetBondedTokens()) @@ -384,11 +384,11 @@ func TestInvalidVotesSlashing(t *testing.T) { func TestWhitelistSlashing(t *testing.T) { input, h := setup(t) - slashWindow := input.OracleKeeper.SlashWindow(input.Ctx) + votePeriodsPerWindow := sdk.NewDec(input.OracleKeeper.SlashWindow(input.Ctx)).QuoInt64(input.OracleKeeper.VotePeriod(input.Ctx)).TruncateInt64() slashFraction := input.OracleKeeper.SlashFraction(input.Ctx) minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx) - for i := int64(0); i < sdk.OneDec().Sub(minValidPerWindow).MulInt64(slashWindow).TruncateInt64(); i++ { + for i := int64(0); i < sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64(); i++ { input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) // Account 1, KRW @@ -405,7 +405,7 @@ func TestWhitelistSlashing(t *testing.T) { // Account 1, KRW makePrevoteAndVote(t, input, h, 0, core.MicroKRWDenom, randomExchangeRate, 0) - input.Ctx = input.Ctx.WithBlockHeight(slashWindow - 1) + input.Ctx = input.Ctx.WithBlockHeight(votePeriodsPerWindow - 1) EndBlocker(input.Ctx, input.OracleKeeper) validator = input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[0]) require.Equal(t, sdk.OneDec().Sub(slashFraction).MulInt(stakingAmt).TruncateInt(), validator.GetBondedTokens()) @@ -417,10 +417,10 @@ func TestAbstainSlashing(t *testing.T) { params.Whitelist = types.DenomList{core.MicroKRWDenom} input.OracleKeeper.SetParams(input.Ctx, params) - slashWindow := input.OracleKeeper.SlashWindow(input.Ctx) + votePeriodsPerWindow := sdk.NewDec(input.OracleKeeper.SlashWindow(input.Ctx)).QuoInt64(input.OracleKeeper.VotePeriod(input.Ctx)).TruncateInt64() minValidPerWindow := input.OracleKeeper.MinValidPerWindow(input.Ctx) - for i := int64(0); i <= sdk.OneDec().Sub(minValidPerWindow).MulInt64(slashWindow).TruncateInt64(); i++ { + for i := int64(0); i <= sdk.OneDec().Sub(minValidPerWindow).MulInt64(votePeriodsPerWindow).TruncateInt64(); i++ { input.Ctx = input.Ctx.WithBlockHeight(input.Ctx.BlockHeight() + 1) // Account 1, KRW diff --git a/x/oracle/internal/keeper/reward.go b/x/oracle/internal/keeper/reward.go index 07ae8b195..28c91f534 100644 --- a/x/oracle/internal/keeper/reward.go +++ b/x/oracle/internal/keeper/reward.go @@ -31,9 +31,9 @@ func (k Keeper) RewardBallotWinners(ctx sdk.Context, ballotWinners map[string]ty return } - // rewardCoin = oraclePool / rewardDistributionWindow + // rewardCoin = oraclePool * VotePeriod / RewardDistributionWindow periodRewards := sdk.NewDecFromInt(rewardPool.AmountOf(core.MicroLunaDenom)). - QuoInt64(k.RewardDistributionWindow(ctx)) + MulInt64(k.VotePeriod(ctx)).QuoInt64(k.RewardDistributionWindow(ctx)) // Dole out rewards var distributedReward sdk.Coins diff --git a/x/oracle/internal/keeper/reward_test.go b/x/oracle/internal/keeper/reward_test.go index c9d227498..5a11c63cc 100644 --- a/x/oracle/internal/keeper/reward_test.go +++ b/x/oracle/internal/keeper/reward_test.go @@ -49,21 +49,21 @@ func TestRewardBallotWinners(t *testing.T) { } // Prepare reward pool - givingAmt := sdk.NewCoins(sdk.NewInt64Coin(core.MicroLunaDenom, 3000000)) + givingAmt := sdk.NewCoins(sdk.NewInt64Coin(core.MicroLunaDenom, 30000000)) acc := input.SupplyKeeper.GetModuleAccount(ctx, types.ModuleName) err := acc.SetCoins(givingAmt) require.NoError(t, err) input.SupplyKeeper.SetModuleAccount(ctx, acc) - rewardDistributionWindow := input.OracleKeeper.RewardDistributionWindow(input.Ctx) + votePeriodsPerWindow := sdk.NewDec(input.OracleKeeper.RewardDistributionWindow(input.Ctx)).QuoInt64(input.OracleKeeper.VotePeriod(input.Ctx)).TruncateInt64() input.OracleKeeper.RewardBallotWinners(ctx, claims) outstandingRewardsDec := input.DistrKeeper.GetValidatorOutstandingRewards(ctx, addr) outstandingRewards, _ := outstandingRewardsDec.TruncateDecimal() - require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroLunaDenom)).QuoInt64(rewardDistributionWindow).QuoInt64(3).TruncateInt(), + require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroLunaDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).TruncateInt(), outstandingRewards.AmountOf(core.MicroLunaDenom)) outstandingRewardsDec1 := input.DistrKeeper.GetValidatorOutstandingRewards(ctx, addr1) outstandingRewards1, _ := outstandingRewardsDec1.TruncateDecimal() - require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroLunaDenom)).QuoInt64(rewardDistributionWindow).QuoInt64(3).MulInt64(2).TruncateInt(), + require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroLunaDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).MulInt64(2).TruncateInt(), outstandingRewards1.AmountOf(core.MicroLunaDenom)) } diff --git a/x/oracle/internal/types/params.go b/x/oracle/internal/types/params.go index 91bbdfa8a..599f0810c 100644 --- a/x/oracle/internal/types/params.go +++ b/x/oracle/internal/types/params.go @@ -26,9 +26,9 @@ var ( // Default parameter values const ( - DefaultVotePeriod = core.BlocksPerMinute / 2 // 30 seconds - DefaultSlashWindow = core.BlocksPerDay / DefaultVotePeriod // window for a day - DefaultRewardDistributionWindow = core.BlocksPerMonth / DefaultVotePeriod // window for a month + DefaultVotePeriod = core.BlocksPerMinute / 2 // 30 seconds + DefaultSlashWindow = core.BlocksPerWeek // window for a week + DefaultRewardDistributionWindow = core.BlocksPerYear // window for a year ) // Default parameter values @@ -47,10 +47,10 @@ type Params struct { VotePeriod int64 `json:"vote_period" yaml:"vote_period"` // the number of blocks during which voting takes place. VoteThreshold sdk.Dec `json:"vote_threshold" yaml:"vote_threshold"` // the minimum percentage of votes that must be received for a ballot to pass. RewardBand sdk.Dec `json:"reward_band" yaml:"reward_band"` // the ratio of allowable exchange rate error that can be rewared. - RewardDistributionWindow int64 `json:"reward_distribution_window" yaml:"reward_distribution_window"` // the number of vote periods during which seigiornage reward comes in and then is distributed. + RewardDistributionWindow int64 `json:"reward_distribution_window" yaml:"reward_distribution_window"` // the number of blocks during which seigiornage reward comes in and then is distributed. Whitelist DenomList `json:"whitelist" yaml:"whitelist"` // the denom list that can be acitivated, SlashFraction sdk.Dec `json:"slash_fraction" yaml:"slash_fraction"` // the ratio of penalty on bonded tokens - SlashWindow int64 `json:"slash_window" yaml:"slash_window"` // the number of vote periods for slashing tallying + SlashWindow int64 `json:"slash_window" yaml:"slash_window"` // the number of blocks for slashing tallying MinValidPerWindow sdk.Dec `json:"min_valid_per_window" yaml:"min_valid_per_window"` // the ratio of minimum valid oracle votes per slash window to avoid slashing } @@ -79,14 +79,14 @@ func (params Params) Validate() error { if params.RewardBand.IsNegative() || params.RewardBand.GT(sdk.OneDec()) { return fmt.Errorf("oracle parameter RewardBand must be between [0, 1]") } - if params.RewardDistributionWindow < 100 { - return fmt.Errorf("oracle parameter RewardDistributionWindow must be bigger or equal than 100 votes period") + if params.RewardDistributionWindow < params.VotePeriod { + return fmt.Errorf("oracle parameter RewardDistributionWindow must be greater than or equal with votes period") } if params.SlashFraction.GT(sdk.OneDec()) || params.SlashFraction.IsNegative() { return fmt.Errorf("oracle parameter SlashRraction must be between [0, 1]") } - if params.SlashWindow < 50 { - return fmt.Errorf("oracle parameter SlashWindow must be greater than or equal 50 votes period") + if params.SlashWindow < params.VotePeriod { + return fmt.Errorf("oracle parameter SlashWindow must be greater than or equal with votes period") } if params.MinValidPerWindow.GT(sdk.NewDecWithPrec(5, 1)) || params.MinValidPerWindow.IsNegative() { return fmt.Errorf("oracle parameter MinValidPerWindow must be between [0, 0.5]") diff --git a/x/oracle/internal/types/params_test.go b/x/oracle/internal/types/params_test.go index 66a919328..1f7cadf39 100644 --- a/x/oracle/internal/types/params_test.go +++ b/x/oracle/internal/types/params_test.go @@ -44,13 +44,13 @@ func TestParamsEqual(t *testing.T) { // small slash window p6 := DefaultParams() - p6.SlashWindow = int64(49) + p6.SlashWindow = int64(1) err = p6.Validate() require.Error(t, err) // small distribution window p7 := DefaultParams() - p7.RewardDistributionWindow = int64(99) + p7.RewardDistributionWindow = int64(1) err = p7.Validate() require.Error(t, err) } diff --git a/x/oracle/slash_test.go b/x/oracle/slash_test.go index 9fa5a75fa..bc4608496 100644 --- a/x/oracle/slash_test.go +++ b/x/oracle/slash_test.go @@ -7,17 +7,18 @@ import ( "github.com/terra-project/core/x/oracle/internal/keeper" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/staking" ) func TestSlashAndResetMissCounters(t *testing.T) { input, _ := setup(t) - slashWindow := input.OracleKeeper.SlashWindow(input.Ctx) + votePeriodsPerWindow := sdk.NewDec(input.OracleKeeper.SlashWindow(input.Ctx)).QuoInt64(input.OracleKeeper.VotePeriod(input.Ctx)).TruncateInt64() slashFraction := input.OracleKeeper.SlashFraction(input.Ctx) - minValidVotes := input.OracleKeeper.MinValidPerWindow(input.Ctx).MulInt64(slashWindow).TruncateInt64() + minValidVotes := input.OracleKeeper.MinValidPerWindow(input.Ctx).MulInt64(votePeriodsPerWindow).TruncateInt64() // Case 1, no slash - input.OracleKeeper.SetMissCounter(input.Ctx, keeper.ValAddrs[0], slashWindow-minValidVotes) + input.OracleKeeper.SetMissCounter(input.Ctx, keeper.ValAddrs[0], votePeriodsPerWindow-minValidVotes) SlashAndResetMissCounters(input.Ctx, input.OracleKeeper) staking.EndBlocker(input.Ctx, input.StakingKeeper) @@ -25,7 +26,7 @@ func TestSlashAndResetMissCounters(t *testing.T) { require.Equal(t, stakingAmt, validator.GetBondedTokens()) // Case 2, slash - input.OracleKeeper.SetMissCounter(input.Ctx, keeper.ValAddrs[0], slashWindow-minValidVotes+1) + input.OracleKeeper.SetMissCounter(input.Ctx, keeper.ValAddrs[0], votePeriodsPerWindow-minValidVotes+1) SlashAndResetMissCounters(input.Ctx, input.OracleKeeper) validator = input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[0]) require.Equal(t, stakingAmt.Sub(slashFraction.MulInt(stakingAmt).TruncateInt()), validator.GetBondedTokens()) diff --git a/x/oracle/slashing.go b/x/oracle/slashing.go index 034102709..f5874ccd1 100644 --- a/x/oracle/slashing.go +++ b/x/oracle/slashing.go @@ -9,15 +9,15 @@ func SlashAndResetMissCounters(ctx sdk.Context, k Keeper) { height := ctx.BlockHeight() distributionHeight := height - sdk.ValidatorUpdateDelay - 1 - slashWindow := k.SlashWindow(ctx) + votePeriodsPerWindow := sdk.NewDec(k.SlashWindow(ctx)).QuoInt64(k.VotePeriod(ctx)).TruncateInt64() minValidPerWindow := k.MinValidPerWindow(ctx) slashFraction := k.SlashFraction(ctx) k.IterateMissCounters(ctx, func(operator sdk.ValAddress, missCounter int64) bool { // Calculate valid vote rate; (SlashWindow - MissCounter)/SlashWindow validVoteRate := sdk.NewDecFromInt( - sdk.NewInt(slashWindow - missCounter)). - QuoInt64(k.SlashWindow(ctx)) + sdk.NewInt(votePeriodsPerWindow - missCounter)). + QuoInt64(votePeriodsPerWindow) // Penalize the validator whoes the valid vote rate is smaller than min threshold if validVoteRate.LT(minValidPerWindow) { diff --git a/x/oracle/test_utils.go b/x/oracle/test_utils.go index 92628724f..1fb1e85e5 100644 --- a/x/oracle/test_utils.go +++ b/x/oracle/test_utils.go @@ -25,6 +25,8 @@ func setup(t *testing.T) (keeper.TestInput, sdk.Handler) { input := keeper.CreateTestInput(t) params := input.OracleKeeper.GetParams(input.Ctx) params.VotePeriod = 1 + params.SlashWindow = 100 + params.RewardDistributionWindow = 100 input.OracleKeeper.SetParams(input.Ctx, params) h := NewHandler(input.OracleKeeper)