Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Align oracle parameters to units of blocks #279

Merged
merged 1 commit into from
Nov 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions x/oracle/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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())
Expand All @@ -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
Expand All @@ -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())
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions x/oracle/internal/keeper/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions x/oracle/internal/keeper/reward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
18 changes: 9 additions & 9 deletions x/oracle/internal/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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]")
Expand Down
4 changes: 2 additions & 2 deletions x/oracle/internal/types/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
9 changes: 5 additions & 4 deletions x/oracle/slash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,26 @@ 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)

validator := input.StakingKeeper.Validator(input.Ctx, keeper.ValAddrs[0])
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())
Expand Down
6 changes: 3 additions & 3 deletions x/oracle/slashing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions x/oracle/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down