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

Nd kavamint touchups #1422

Merged
merged 6 commits into from
Dec 8, 2022
Merged

Conversation

nddeluca
Copy link
Member

@nddeluca nddeluca commented Dec 8, 2022

draft for review -- will rebase into feat branch instead of merging

for genesis and params (and other store objects)
repace proto stringers and remove getters; keep sdk.Dec values strings
in protos; increase validation of sdk.Dec values in params; increase
coverage; add module account permission checks; ensure import and export
of genesis does not change state
@@ -216,6 +216,23 @@
]
}
},
{
"url": "./out/swagger/kava/kavamint/v1beta1/query.swagger.json",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required for the swagger to be generated

import "gogoproto/gogo.proto";

option go_package = "github.com/kava-labs/kava/x/kavamint/types";

// Params wraps the governance parameters for the kavamint module
message Params {
option (gogoproto.goproto_stringer) = false;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We override the stringer since sdk.Dec doesn't work well with the built-in method

// yearly inflation of total token supply minted to the community pool.
bytes community_pool_inflation = 1 [
string community_pool_inflation = 1 [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sdk.Dec should be strings - cosmos/cosmos-sdk#10863

@@ -11,7 +12,7 @@ option go_package = "github.com/kava-labs/kava/x/kavamint/types";
service Query {
// Params queries the parameters of x/kavamint module.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/kava/kavamint/v1beta1/parameters";
option (google.api.http).get = "/kava/kavamint/v1beta1/params";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

standard is params, though not all modules have followed it

@@ -12,8 +12,8 @@ import (
func BeginBlocker(ctx sdk.Context, k keeper.KeeperI) {
params := k.GetParams(ctx)
// determine seconds since last mint
previousBlockTime, found := k.GetPreviousBlockTime(ctx)
if !found || previousBlockTime.IsZero() {
previousBlockTime := k.GetPreviousBlockTime(ctx)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just need to protect the zero case -- found is redundant since we have zero value


if macc := ak.GetModuleAccount(ctx, types.ModuleName); macc == nil {
// get module account -- creates one with allowed permissions if it does not exist
macc := ak.GetModuleAccount(ctx, types.ModuleName)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually creates the module account, so the panic is just a double check incase that behavior changes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, originally had no check but @DracoLi suggested i add one.

is pulling the call out of the nil check just for clarity on the fact this code potentially does something rather than just checks if an account exists?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote it both ways, but thought this was cleaner and easier to read without the permission check nested.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could go either way on it, basically just increased the scope of macc to use below

panic(fmt.Sprintf("%s module account has not been set", types.ModuleName))
}

// check module account has minter permissions
if !macc.HasPermission(authtypes.Minter) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to check required permissions as well


// set store state from genesis
keeper.SetParams(ctx, gs.Params)
keeper.SetPreviousBlockTime(ctx, gs.PreviousBlockTime)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change in behavior here -- we allow the zero value to be set, which then gets populated on the first block. Genesis assumes to previous block

previousBlockTime = ctx.BlockTime()
}
return types.NewGenesisState(params, previousBlockTime)
return types.NewGenesisState(keeper.GetParams(ctx), keeper.GetPreviousBlockTime(ctx))
Copy link
Member Author

@nddeluca nddeluca Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No modifications to genesis on export.

We test that an imported genesis always results in the same exported genesis -- best not to make modifications outside of abci

if err := blockTime.UnmarshalBinary(b); err != nil {
panic(err)
}
return blockTime, true

return
}

// SetPreviousBlockTime set the time of the previous block
func (k Keeper) SetPreviousBlockTime(ctx sdk.Context, blockTime time.Time) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We delete the key if the previous block time is blank

time "time"
)

var (
// DefaultPreviousBlockTime represents a time that is unset -- no previous block has occured
DefaultPreviousBlockTime = time.Time{}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change of default to assume no previous block and no accumulation on the first height after initgenesis

@pirtleshell we can set a previous block time explicity in the upgrade handler if we want

return fmt.Errorf("previous block time not set")
}
return nil
return gs.Params.Validate()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unset is a valid case for new chains since there are no previous blocks

}
})
}
}

func TestGenesis_JSONEncoding(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These json tests help serve as examples and prevent regressions in protobuf encoding/tags

// TODO consider lowering max rate. when it's this large the precision is very bad.
MaxMintingRate = sdk.NewDecWithPrec(1765, 1)
// MaxMintingRate returns the per second rate equivalent to 10,000% per year
MaxMintingRate = sdk.MustNewDecFromStr("0.000000146028999310")
Copy link
Member Author

@nddeluca nddeluca Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduced the max per second rate significantly -- we should never need a value higher than this. The previous max was too high imo, which if a proposal had a typo could result in a lot of coins minted before another proposal could correct it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to be the yearly value -- I got confused with the per second rates used in other modules

// String implements fmt.Stringer
func (p Params) String() string {
return fmt.Sprintf(`Params:
CommunityPoolInflation: %s
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a helpful change -- protobuf Stringer() doesn't show sdk.Dec with a decimal place

return fmt.Errorf("rate out of bounds. the max allowed rate is %s", MaxMintingRate)
// validateRate ensures rate is properly initialized (non-nil), not negative, and not greater than the max rate
func validateRate(rate sdk.Dec) error {
if rate.IsNil() || rate.IsNegative() || rate.GT(MaxMintingRate) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's important to check that sdk.Dec values are not nill as they will panic if somehow set

@@ -1,48 +0,0 @@
package keeper

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed -- the legacy querier paths are not needed for new modules

@@ -44,7 +42,7 @@ func (suite *abciTestSuite) CheckCommunityPoolBalance(ctx sdk.Context, expectedA
}

func TestGRPCQueryTestSuite(t *testing.T) {
suite.Run(t, new(abciTestSuite))
//suite.Run(t, new(abciTestSuite))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reminder to re-enable this test


if macc := ak.GetModuleAccount(ctx, types.ModuleName); macc == nil {
// get module account -- creates one with allowed permissions if it does not exist
macc := ak.GetModuleAccount(ctx, types.ModuleName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, originally had no check but @DracoLi suggested i add one.

is pulling the call out of the nil check just for clarity on the fact this code potentially does something rather than just checks if an account exists?

}

// SetPreviousBlockTime set the time of the previous block
func (k Keeper) SetPreviousBlockTime(ctx sdk.Context, blockTime time.Time) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PreviousBlockTimeKey)

if blockTime.IsZero() {
store.Delete(types.PreviousBlockTimeKey)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧠 nice, this makes sense.

},
{
"invalid - no time set",
"vali - no time set",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"vali - no time set",
"valid - no time set",

)

// PreviousBlockTimeKey is the store key for the previous block time
var PreviousBlockTimeKey = []byte{0x00}
var PreviousBlockTimeKey = []byte{0x01}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start w/ 1 to prevent confusion with nil value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I think I fat fingered a key here, didn't mean to modify it

@nddeluca nddeluca merged commit 3053443 into feat/community-pool-enhancements Dec 8, 2022
@nddeluca nddeluca deleted the nd-kavamint-touchups branch December 8, 2022 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants