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

Update numeric store getters to return bool if value is missing #2169

Merged
merged 9 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
5 changes: 1 addition & 4 deletions app/inflation/inflation.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,13 @@ func (c Calculator) InflationRate(ctx sdk.Context, minter minttypes.Minter, mint
ugovKeeper := c.UgovKeeperB.Keeper(&ctx)
inflationParams := ugovKeeper.InflationParams()
maxSupplyAmount := inflationParams.MaxSupply.Amount

totalSupply := c.MintKeeper.StakingTokenSupply(ctx)
if totalSupply.GTE(maxSupplyAmount) {
// supply is already reached the maximum amount, so inflation should be zero
return sdk.ZeroDec()
}

cycleEnd, err := ugovKeeper.GetInflationCycleEnd()
util.Panic(err)

cycleEnd := ugovKeeper.GetInflationCycleEnd()
if ctx.BlockTime().After(cycleEnd) {
// new inflation cycle is starting , so we need to update the inflation max and min rate
factor := bpmath.One - inflationParams.InflationReductionRate
Expand Down
39 changes: 17 additions & 22 deletions util/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// GetValue loads value from the store using default Unmarshaler. Panics on failure to decode.
Expand Down Expand Up @@ -98,15 +97,15 @@ func SetValueCdc(store sdk.KVStore, cdc codec.Codec, key []byte, object codec.Pr
return nil
}

// GetInt retrieves an sdkmath.Int from a KVStore, or returns zero if no value is stored.
// GetInt retrieves an sdkmath.Int from a KVStore, or returns (0, false) if no value is stored.
// It panics if a stored value fails to unmarshal or is negative.
// Accepts an additional string which should describe the field being retrieved in custom error messages.
func GetInt(store sdk.KVStore, key []byte, errField string) sdkmath.Int {
func GetInt(store sdk.KVStore, key []byte, errField string) (sdkmath.Int, bool) {
val := GetValue[*sdkmath.Int](store, key, errField)
if val == nil { // Not found
return sdk.ZeroInt()
return sdk.ZeroInt(), false
}
return *val
return *val, true
}

// SetInt stores an sdkmath.Int in a KVStore, or clears if setting to zero or nil.
Expand All @@ -120,14 +119,14 @@ func SetInt(store sdk.KVStore, key []byte, val sdkmath.Int, errField string) err
return SetValue(store, key, &val, errField)
}

// GetDec retrieves an sdk.Dec from a KVStore, or returns zero if no value is stored.
// GetDec retrieves an sdk.Dec from a KVStore, or returns (0, false) if no value is stored.
// Accepts an additional string which should describe the field being retrieved in custom error messages.
func GetDec(store sdk.KVStore, key []byte, errField string) sdk.Dec {
func GetDec(store sdk.KVStore, key []byte, errField string) (sdk.Dec, bool) {
val := GetValue[*sdk.Dec](store, key, errField)
if val == nil { // Not found
return sdk.ZeroDec()
return sdk.ZeroDec(), false
}
return *val
return *val, true
}

// SetDec stores an sdk.Dec in a KVStore, or clears if setting to zero or nil.
Expand Down Expand Up @@ -162,13 +161,10 @@ func SetAddress(store sdk.KVStore, key []byte, val sdk.AccAddress) {
}

// GetTimeMs retrieves time saved as Unix time in Miliseconds.
// Returns sdkerrors.NotFound error if the value is not there, hence time = 0 is not supported.
func GetTimeMs(store sdk.KVStore, key []byte) (time.Time, error) {
t := GetInteger[int64](store, key)
if t == 0 {
return time.Time{}, sdkerrors.ErrNotFound
}
return time.UnixMilli(t), nil
// Returns if the value is not in the store, returns (0 unix time, false).
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
func GetTimeMs(store sdk.KVStore, key []byte) (time.Time, bool) {
t, ok := GetInteger[int64](store, key)
return time.UnixMilli(t), ok
}

// SetTimeMs saves time as Unix time in Miliseconds.
Expand Down Expand Up @@ -197,20 +193,19 @@ func SetInteger[T Integer](store sdk.KVStore, key []byte, v T) {
store.Set(key, bz)
}

func GetInteger[T Integer](store sdk.KVStore, key []byte) T {
func GetInteger[T Integer](store sdk.KVStore, key []byte) (T, bool) {
bz := store.Get(key)
if bz == nil {
return 0
return 0, false
}
var v T
switch any(v).(type) {
case int64, uint64:
v2 := binary.LittleEndian.Uint64(bz)
return T(v2)
return T(binary.LittleEndian.Uint64(bz)), true
case int32, uint32:
return T(binary.LittleEndian.Uint32(bz))
return T(binary.LittleEndian.Uint32(bz)), true
case byte:
return T(bz[0])
return T(bz[0]), true
}
panic("not possible: all types must be covered above")
}
38 changes: 24 additions & 14 deletions util/store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"

Expand All @@ -17,30 +16,41 @@ func TestGetAndSetDec(t *testing.T) {
t.Parallel()
store := tsdk.KVStore(t)
key := []byte("decKey")
val := sdk.MustNewDecFromStr("1234")
err := SetDec(store, key, val, "no error")
v1 := sdk.MustNewDecFromStr("1234.5679")
v2, ok := GetDec(store, key, "no error")
assert.Equal(t, false, ok)
assert.DeepEqual(t, sdk.ZeroDec(), v2)

err := SetDec(store, key, v1, "no error")
assert.NilError(t, err)

v := GetDec(store, key, "no error")
assert.DeepEqual(t, v, val)
v2, ok = GetDec(store, key, "no error")
assert.Equal(t, true, ok)
assert.DeepEqual(t, v2, v1)
}

func TestGetAndSetInt(t *testing.T) {
t.Parallel()
store := tsdk.KVStore(t)
key := []byte("intKey")
val, ok := sdk.NewIntFromString("1234")
v2, ok := GetInt(store, key, "no error")
assert.Equal(t, false, ok)
assert.DeepEqual(t, sdk.ZeroInt(), v2)

v1, ok := sdk.NewIntFromString("1234")
assert.Equal(t, true, ok)
err := SetInt(store, key, val, "no error")
err := SetInt(store, key, v1, "no error")
assert.NilError(t, err)

v := GetInt(store, key, "no error")
assert.DeepEqual(t, v, val)
v2, ok = GetInt(store, key, "no error")
assert.Equal(t, true, ok)
assert.DeepEqual(t, v2, v1)
}

func checkStoreNumber[T Integer](name string, val T, store sdk.KVStore, key []byte, t *testing.T) {
SetInteger(store, key, val)
vOut := GetInteger[T](store, key)
vOut, ok := GetInteger[T](store, key)
require.True(t, ok)
require.Equal(t, val, vOut, name)
}

Expand Down Expand Up @@ -75,14 +85,14 @@ func TestGetAndSetTime(t *testing.T) {
store := tsdk.KVStore(t)
key := []byte("tKey")

_, err := GetTimeMs(store, key)
assert.ErrorIs(t, err, sdkerrors.ErrNotFound)
_, ok := GetTimeMs(store, key)
assert.Equal(t, false, ok)

val := time.Now()
SetTimeMs(store, key, val)

val2, err := GetTimeMs(store, key)
assert.NilError(t, err)
val2, ok := GetTimeMs(store, key)
assert.Equal(t, true, ok)
val = val.Truncate(time.Millisecond)
assert.Equal(t, val, val2)
}
14 changes: 8 additions & 6 deletions x/incentive/keeper/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ func (k Keeper) deleteIncentiveProgram(ctx sdk.Context, id uint32) error {

// getNextProgramID gets the ID that will be assigned to the next incentive program passed by governance.
func (k Keeper) getNextProgramID(ctx sdk.Context) uint32 {
return store.GetInteger[uint32](k.KVStore(ctx), keyNextProgramID)
id, _ := store.GetInteger[uint32](k.KVStore(ctx), keyNextProgramID)
return id
}

// setNextProgramID sets the ID that will be assigned to the next incentive program passed by governance.
Expand All @@ -147,7 +148,8 @@ func (k Keeper) setNextProgramID(ctx sdk.Context, id uint32) error {
// getLastRewardsTime gets the last unix time incentive rewards were computed globally by EndBlocker.
// panics if it would return a negative value.
toteki marked this conversation as resolved.
Show resolved Hide resolved
func (k Keeper) GetLastRewardsTime(ctx sdk.Context) int64 {
return store.GetInteger[int64](k.KVStore(ctx), keyLastRewardsTime)
t, _ := store.GetInteger[int64](k.KVStore(ctx), keyLastRewardsTime)
return t
}

// setLastRewardsTime sets the last unix time incentive rewards were computed globally by EndBlocker.
Expand All @@ -164,14 +166,14 @@ func (k Keeper) setLastRewardsTime(ctx sdk.Context, time int64) error {
// getTotalBonded retrieves the total amount of uTokens of a given denom which are bonded to the incentive module
func (k Keeper) getTotalBonded(ctx sdk.Context, denom string) sdk.Coin {
key := keyTotalBonded(denom)
amount := store.GetInt(k.KVStore(ctx), key, "total bonded")
amount, _ := store.GetInt(k.KVStore(ctx), key, "total bonded")
return sdk.NewCoin(denom, amount)
}

// GetBonded retrieves the amount of uTokens of a given denom which are bonded by an account
func (k Keeper) GetBonded(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {
key := keyBondAmount(addr, denom)
amount := store.GetInt(k.KVStore(ctx), key, "bonded amount")
amount, _ := store.GetInt(k.KVStore(ctx), key, "bonded amount")
return sdk.NewCoin(denom, amount)
}

Expand All @@ -198,15 +200,15 @@ func (k Keeper) setBonded(ctx sdk.Context, addr sdk.AccAddress, uToken sdk.Coin)
// getUnbonding retrieves the amount of uTokens of a given denom which are unbonding by an account
func (k Keeper) getUnbondingAmount(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {
key := keyUnbondAmount(addr, denom)
amount := store.GetInt(k.KVStore(ctx), key, "unbonding amount")
amount, _ := store.GetInt(k.KVStore(ctx), key, "unbonding amount")
return sdk.NewCoin(denom, amount)
}

// getTotalUnbonding retrieves the total amount of uTokens of a given denom which are unbonding from
// the incentive module
func (k Keeper) getTotalUnbonding(ctx sdk.Context, denom string) sdk.Coin {
key := keyTotalUnbonding(denom)
amount := store.GetInt(k.KVStore(ctx), key, "total unbonding")
amount, _ := store.GetInt(k.KVStore(ctx), key, "total unbonding")
return sdk.NewCoin(denom, amount)
}

Expand Down
2 changes: 1 addition & 1 deletion x/incentive/keeper/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func (k Keeper) EndBlock(ctx sdk.Context) (skipped bool, err error) {

if blockTime <= prevTime {
// Avoids this and related issues: https://github.com/tendermint/tendermint/issues/8773
k.Logger(ctx).Error(
k.Logger(ctx).Debug(
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
"incentive module will wait for block time > prevRewardTime",
"current", blockTime,
"prev", prevTime,
Expand Down
10 changes: 2 additions & 8 deletions x/metoken/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,11 @@ func (k Keeper) InitGenesis(genState metoken.GenesisState) {

// ExportGenesis returns the x/metoken module's exported genesis state.
func (k Keeper) ExportGenesis() *metoken.GenesisState {
nextRebalancingTime, err := k.getNextRebalancingTime()
util.Panic(err)

nextInterestClaimTime, err := k.getNextInterestClaimTime()
util.Panic(err)

return &metoken.GenesisState{
Params: k.GetParams(),
Registry: k.GetAllRegisteredIndexes(),
Balances: k.GetAllIndexesBalances(),
NextRebalancingTime: nextRebalancingTime,
NextInterestClaimTime: nextInterestClaimTime,
NextRebalancingTime: k.getNextRebalancingTime(),
NextInterestClaimTime: k.getNextInterestClaimTime(),
}
}
12 changes: 8 additions & 4 deletions x/metoken/keeper/metoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ func (k Keeper) GetAllIndexesBalances() []metoken.IndexBalances {
}

// getNextRebalancingTime returns next x/metoken re-balancing time in Milliseconds.
func (k Keeper) getNextRebalancingTime() (time.Time, error) {
return store.GetTimeMs(k.store, keyPrefixNextRebalancingTime)
// Returns 0 unix time if the time was not set before.
func (k Keeper) getNextRebalancingTime() time.Time {
t, _ := store.GetTimeMs(k.store, keyPrefixNextRebalancingTime)
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
return t
}

// setNextRebalancingTime next x/metoken re-balancing time in Milliseconds.
Expand All @@ -53,8 +55,10 @@ func (k Keeper) setNextRebalancingTime(nextRebalancingTime time.Time) {
}

// getNextInterestClaimTime returns next x/metoken interest claiming time in Milliseconds.
func (k Keeper) getNextInterestClaimTime() (time.Time, error) {
return store.GetTimeMs(k.store, keyPrefixNextInterestClaimTime)
// Returns 0 unix time if the time was not set before.
func (k Keeper) getNextInterestClaimTime() time.Time {
t, _ := store.GetTimeMs(k.store, keyPrefixNextInterestClaimTime)
return t
}

// setNextInterestClaimTime next x/metoken interest claiming time in Milliseconds.
Expand Down
4 changes: 1 addition & 3 deletions x/ugov/keeper/genesis.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package keeper

import (
"github.com/umee-network/umee/v5/util"
"github.com/umee-network/umee/v5/x/ugov"
)

func (k Keeper) ExportGenesis() *ugov.GenesisState {
cycleEndTime, err := k.GetInflationCycleEnd()
util.Panic(err)
cycleEndTime := k.GetInflationCycleEnd()
return &ugov.GenesisState{
MinGasPrice: k.MinGasPrice(),
InflationParams: k.InflationParams(),
Expand Down
6 changes: 4 additions & 2 deletions x/ugov/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ func (k Keeper) SetInflationCycleEnd(startTime time.Time) error {
return nil
}

func (k Keeper) GetInflationCycleEnd() (time.Time, error) {
return store.GetTimeMs(k.store, keyInflationCycleEnd)
// Returns zero unix time if the inflation cycle was not set.
func (k Keeper) GetInflationCycleEnd() time.Time {
t, _ := store.GetTimeMs(k.store, keyInflationCycleEnd)
return t
}
10 changes: 4 additions & 6 deletions x/ugov/keeper/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,12 @@ func TestInflationCycleEnd(t *testing.T) {
st := time.Time{}
err := k.SetInflationCycleEnd(st)
require.NoError(err)
in_c, err := k.GetInflationCycleEnd()
require.NoError(err)
require.Equal(in_c.IsZero(), true, "it should be default zero time")
end := k.GetInflationCycleEnd()
require.Equal(end.IsZero(), true, "it should be default zero time")

cycleEnd := time.Now()
err = k.SetInflationCycleEnd(cycleEnd)
require.NoError(err)
end, err := k.GetInflationCycleEnd()
require.NoError(err)
require.Equal(end.UnixMilli(), cycleEnd.UnixMilli(), "inflation cycle end time should be same")
end = k.GetInflationCycleEnd()
require.Equal(end, cycleEnd.Truncate(time.Millisecond), "inflation cycle end time should be same")
}
5 changes: 1 addition & 4 deletions x/ugov/keeper/query_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ func (q Querier) InflationParams(ctx context.Context, _ *ugov.QueryInflationPara
func (q Querier) InflationCycleEnd(ctx context.Context, _ *ugov.QueryInflationCycleEnd) (
*ugov.QueryInflationCycleEndResponse, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cycleEndTime, err := q.Keeper(&sdkCtx).GetInflationCycleEnd()
if err != nil {
return nil, err
}
cycleEndTime := q.Keeper(&sdkCtx).GetInflationCycleEnd()
return &ugov.QueryInflationCycleEndResponse{End: &cycleEndTime}, nil
}
2 changes: 1 addition & 1 deletion x/uibc/quota/keeper/quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (k Keeper) GetAllOutflows() (sdk.DecCoins, error) {

// GetTokenOutflows returns sum of denom outflows in USD value in the DecCoin structure.
func (k Keeper) GetTokenOutflows(denom string) sdk.DecCoin {
amount := store.GetDec(k.store, KeyTotalOutflows(denom), "total_outflow")
amount, _ := store.GetDec(k.store, KeyTotalOutflows(denom), "total_outflow")
return sdk.NewDecCoinFromDec(denom, amount)
}

Expand Down
Loading