diff --git a/x/community/genesis.go b/x/community/genesis.go index 4a187e5990..c68a972063 100644 --- a/x/community/genesis.go +++ b/x/community/genesis.go @@ -10,10 +10,22 @@ import ( "github.com/kava-labs/kava/x/community/types" ) -// InitGenesis initializes the community module account -func InitGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper) { +// InitGenesis initializes the community module account and stores the genesis state +func InitGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper, gs types.GenesisState) { // check if the module account exists if moduleAcc := ak.GetModuleAccount(ctx, types.ModuleAccountName); moduleAcc == nil { panic(fmt.Sprintf("%s module account has not been set", types.ModuleAccountName)) } + + k.SetParams(ctx, gs.Params) +} + +// ExportGenesis exports the store to a genesis state +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { + params, found := k.GetParams(ctx) + if !found { + params = types.Params{} + } + + return types.NewGenesisState(params) } diff --git a/x/community/genesis_test.go b/x/community/genesis_test.go index cf45cd3a63..4904e45c48 100644 --- a/x/community/genesis_test.go +++ b/x/community/genesis_test.go @@ -2,12 +2,15 @@ package community_test import ( "testing" + "time" "github.com/stretchr/testify/suite" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/kava-labs/kava/x/community" "github.com/kava-labs/kava/x/community/testutil" + "github.com/kava-labs/kava/x/community/types" ) type genesisTestSuite struct { @@ -23,12 +26,15 @@ func TestGenesisTestSuite(t *testing.T) { } func (suite *genesisTestSuite) TestInitGenesis() { - suite.SetupTest() accountKeeper := suite.App.GetAccountKeeper() + genesisState := types.NewGenesisState( + types.NewParams(time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)), + ) + suite.NotPanics(func() { - community.InitGenesis(suite.Ctx, suite.Keeper, accountKeeper) + community.InitGenesis(suite.Ctx, suite.Keeper, accountKeeper, genesisState) }) // check for module account this way b/c GetModuleAccount creates if not existing. @@ -36,4 +42,29 @@ func (suite *genesisTestSuite) TestInitGenesis() { suite.NotNil(acc) _, ok := acc.(authtypes.ModuleAccountI) suite.True(ok) + + storedParams, found := suite.App.GetCommunityKeeper().GetParams(suite.Ctx) + suite.True(found) + suite.Equal(genesisState.Params, storedParams) +} + +func (suite *genesisTestSuite) TestExportGenesis() { + + params := types.NewParams(time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)) + suite.Keeper.SetParams(suite.Ctx, params) + + genesisState := community.ExportGenesis(suite.Ctx, suite.Keeper) + + suite.Equal(params, genesisState.Params) +} + +func (suite *genesisTestSuite) TestInitExportIsLossless() { + genesisState := types.NewGenesisState( + types.NewParams(time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)), + ) + + community.InitGenesis(suite.Ctx, suite.Keeper, suite.App.GetAccountKeeper(), genesisState) + exportedState := community.ExportGenesis(suite.Ctx, suite.Keeper) + + suite.Equal(genesisState, exportedState) } diff --git a/x/community/keeper/keeper_test.go b/x/community/keeper/keeper_test.go index 482b3bcb02..25c61dc8e2 100644 --- a/x/community/keeper/keeper_test.go +++ b/x/community/keeper/keeper_test.go @@ -2,7 +2,6 @@ package keeper_test import ( "testing" - "time" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -66,32 +65,3 @@ func (suite *KeeperTestSuite) TestCommunityPool() { suite.Require().ErrorContains(err, "insufficient funds") }) } - -func (suite *KeeperTestSuite) TestGetSetParams() { - suite.Run("get params returns not found when store empty", func() { - _, found := suite.Keeper.GetParams(suite.Ctx) - suite.Require().False(found) - }) - - suite.Run("get params returns stored params", func() { - err := suite.Keeper.SetParams(suite.Ctx, types.DefaultParams()) - suite.Require().NoError(err) - - readParams, found := suite.Keeper.GetParams(suite.Ctx) - suite.True(found) - suite.Equal(types.DefaultParams(), readParams) - }) - - suite.Run("set overwrite previous value", func() { - err := suite.Keeper.SetParams(suite.Ctx, types.DefaultParams()) - suite.Require().NoError(err) - params := types.NewParams(time.Date(1998, 0, 0, 0, 0, 0, 0, time.UTC)) - err = suite.Keeper.SetParams(suite.Ctx, params) - suite.Require().NoError(err) - - readParams, found := suite.Keeper.GetParams(suite.Ctx) - suite.True(found) - suite.NotEqual(params, types.DefaultParams()) - suite.Equal(params, readParams) - }) -} diff --git a/x/community/keeper/params.go b/x/community/keeper/params.go index 23e2d5a27a..f5607bb2bd 100644 --- a/x/community/keeper/params.go +++ b/x/community/keeper/params.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/kava-labs/kava/x/community/types" @@ -22,17 +24,13 @@ func (k Keeper) GetParams(ctx sdk.Context) (types.Params, bool) { } // SetParams sets params on the store -func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error { +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { if err := params.Validate(); err != nil { - return err + panic(fmt.Sprintf("invalid params: %s", err)) } store := ctx.KVStore(k.key) - bz, err := k.cdc.Marshal(¶ms) - if err != nil { - return err - } + bz := k.cdc.MustMarshal(¶ms) store.Set(types.ParamsKey, bz) - return nil } diff --git a/x/community/keeper/params_test.go b/x/community/keeper/params_test.go new file mode 100644 index 0000000000..c0b4008f85 --- /dev/null +++ b/x/community/keeper/params_test.go @@ -0,0 +1,70 @@ +package keeper_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtime "github.com/tendermint/tendermint/types/time" + + "github.com/kava-labs/kava/app" + "github.com/kava-labs/kava/x/community/keeper" + "github.com/kava-labs/kava/x/community/types" +) + +// Test suite used for all store tests +type StoreTestSuite struct { + suite.Suite + + App app.TestApp + Ctx sdk.Context + Keeper keeper.Keeper +} + +// The default state used by each test +func (suite *StoreTestSuite) SetupTest() { + app.SetSDKConfig() + suite.App = app.NewTestApp() + suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + suite.Keeper = suite.App.GetCommunityKeeper() +} + +func TestStoreTestSuite(t *testing.T) { + suite.Run(t, new(StoreTestSuite)) +} + +func (suite *StoreTestSuite) TestGetSetParams() { + suite.Run("get params returns not found on empty store", func() { + _, found := suite.Keeper.GetParams(suite.Ctx) + suite.Require().False(found) + }) + + suite.Run("set params cannot store invalid params", func() { + invalid := types.Params{UpgradeTimeDisableInflation: time.Date(-1, 1, 1, 0, 0, 0, 0, time.UTC)} + suite.Panics(func() { + suite.Keeper.SetParams(suite.Ctx, invalid) + }) + }) + + suite.Run("get params returns stored params", func() { + suite.Keeper.SetParams(suite.Ctx, types.DefaultParams()) + + storedParams, found := suite.Keeper.GetParams(suite.Ctx) + suite.True(found) + suite.Equal(types.DefaultParams(), storedParams) + }) + + suite.Run("set overwrite previous value", func() { + suite.Keeper.SetParams(suite.Ctx, types.DefaultParams()) + + params := types.NewParams(time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC)) + suite.Keeper.SetParams(suite.Ctx, params) + + storedParams, found := suite.Keeper.GetParams(suite.Ctx) + suite.True(found) + suite.NotEqual(params, types.DefaultParams()) + suite.Equal(params, storedParams) + }) +} diff --git a/x/community/module.go b/x/community/module.go index 2861e9f4d3..2b1bfbecbe 100644 --- a/x/community/module.go +++ b/x/community/module.go @@ -40,13 +40,19 @@ func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { } // DefaultGenesis default genesis state -func (AppModuleBasic) DefaultGenesis(_ codec.JSONCodec) json.RawMessage { - return []byte("{}") +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + gs := types.DefaultGenesisState() + return cdc.MustMarshalJSON(&gs) } // ValidateGenesis module validate genesis -func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, _ json.RawMessage) error { - return nil +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + err := cdc.UnmarshalJSON(bz, &gs) + if err != nil { + return err + } + return gs.Validate() } // RegisterInterfaces implements InterfaceModule.RegisterInterfaces @@ -122,14 +128,18 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { } // InitGenesis module init-genesis -func (am AppModule) InitGenesis(ctx sdk.Context, _ codec.JSONCodec, _ json.RawMessage) []abci.ValidatorUpdate { - InitGenesis(ctx, am.keeper, am.accountKeeper) +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, am.accountKeeper, genState) return []abci.ValidatorUpdate{} } // ExportGenesis module export genesis -func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMessage { - return am.DefaultGenesis(cdc) +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(&gs) } // BeginBlock module begin-block