Skip to content

Commit

Permalink
feat(client): migrate client params
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitrisJim committed May 24, 2023
1 parent df918d2 commit 731a0af
Show file tree
Hide file tree
Showing 19 changed files with 763 additions and 90 deletions.
18 changes: 18 additions & 0 deletions modules/core/02-client/exported/exported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package exported

import (
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)

type (
ParamSet = paramtypes.ParamSet

// Subspace defines an interface that implements the legacy x/params Subspace
// type.
//
// NOTE: This is used solely for migration of x/params managed parameters.
Subspace interface {
GetParamSet(ctx sdk.Context, ps ParamSet)
}
)
3 changes: 3 additions & 0 deletions modules/core/02-client/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (
// InitGenesis initializes the ibc client submodule's state from a provided genesis
// state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) {
if err := gs.Params.Validate(); err != nil {
panic(fmt.Sprintf("invalid ibc client genesis state parameters: %v", err))
}
k.SetParams(ctx, gs.Params)

// Set all client metadata first. This will allow client keeper to overwrite client and consensus state keys
Expand Down
34 changes: 21 additions & 13 deletions modules/core/02-client/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,29 @@ import (
// Keeper represents a type that grants read and write permissions to any client
// state information
type Keeper struct {
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
paramSpace paramtypes.Subspace
stakingKeeper types.StakingKeeper
upgradeKeeper types.UpgradeKeeper
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
legacySubspace paramtypes.Subspace
stakingKeeper types.StakingKeeper
upgradeKeeper types.UpgradeKeeper

authority string
}

// NewKeeper creates a new NewKeeper instance
func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, paramSpace paramtypes.Subspace, sk types.StakingKeeper, uk types.UpgradeKeeper) Keeper {
func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, legacySubspace paramtypes.Subspace, sk types.StakingKeeper, uk types.UpgradeKeeper, authority string) Keeper {
// set KeyTable if it has not already been set
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
if !legacySubspace.HasKeyTable() {
legacySubspace = legacySubspace.WithKeyTable(types.ParamKeyTable())
}

return Keeper{
storeKey: key,
cdc: cdc,
paramSpace: paramSpace,
stakingKeeper: sk,
upgradeKeeper: uk,
storeKey: key,
cdc: cdc,
legacySubspace: legacySubspace,
stakingKeeper: sk,
upgradeKeeper: uk,
authority: authority,
}
}

Expand Down Expand Up @@ -413,3 +416,8 @@ func (k Keeper) GetClientStatus(ctx sdk.Context, clientState exported.ClientStat
}
return clientState.Status(ctx, k.ClientStore(ctx, clientID), k.cdc)
}

// GetAuthority returns the client module's authority.
func (k Keeper) GetAuthority() string {
return k.authority
}
15 changes: 15 additions & 0 deletions modules/core/02-client/keeper/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

v7 "github.com/cosmos/ibc-go/v7/modules/core/02-client/migrations/v7"
"github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
)

// Migrator is a struct for handling in-place store migrations.
Expand Down Expand Up @@ -31,3 +32,17 @@ func (m Migrator) Migrate2to3(ctx sdk.Context) error {
func (m Migrator) Migrate3to4(ctx sdk.Context) error {
return v7.MigrateLocalhostClient(ctx, m.keeper)
}

// MigrateParams migrates from consensus version 4 to 5.
// This migration takes the parameters that are currently stored and managed by x/params
// and stores them directly in the ibc module's state.
func (m Migrator) MigrateParams(ctx sdk.Context) error {
var params types.Params
m.keeper.legacySubspace.GetParamSet(ctx, &params)

if err := params.Validate(); err != nil {
return err
}
m.keeper.SetParams(ctx, params)
return nil
}
43 changes: 43 additions & 0 deletions modules/core/02-client/keeper/migrations_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package keeper_test

import (
"github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper"
"github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
)

// TestMigrateParams tests the migration for the client params
func (suite *KeeperTestSuite) TestMigrateParams() {
testCases := []struct {
name string
malleate func()
expectedParams types.Params
}{
{
"success: default params",
func() {
params := types.DefaultParams()
subspace := suite.chainA.GetSimApp().GetSubspace(ibcexported.ModuleName)
subspace.SetParamSet(suite.chainA.GetContext(), &params)
},
types.DefaultParams(),
},
}

for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest() // reset

tc.malleate()

ctx := suite.chainA.GetContext()
migrator := keeper.NewMigrator(suite.chainA.GetSimApp().IBCKeeper.ClientKeeper)
err := migrator.MigrateParams(ctx)
suite.Require().NoError(err)

params := suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.GetParams(ctx)
suite.Require().Equal(tc.expectedParams, params)
})
}
}
21 changes: 15 additions & 6 deletions modules/core/02-client/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@ import (
"github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
)

// GetAllowedClients retrieves the allowed clients from the paramstore
// GetAllowedClients retrieves the allowed clients from the params stored.
func (k Keeper) GetAllowedClients(ctx sdk.Context) []string {
var res []string
k.paramSpace.Get(ctx, types.KeyAllowedClients, &res)
return res
p := k.GetParams(ctx)
return p.AllowedClients
}

// GetParams returns the total set of ibc-client parameters.
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
return types.NewParams(k.GetAllowedClients(ctx)...)
store := ctx.KVStore(k.storeKey)
bz := store.Get([]byte(types.ParamsKey))
if bz == nil {
panic("ibc client params are not set in store")
}

var p types.Params
k.cdc.MustUnmarshal(bz, &p)
return p
}

// SetParams sets the total set of ibc-client parameters.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSpace.SetParamSet(ctx, &params)
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&params)
store.Set([]byte(types.ParamsKey), bz)
}
52 changes: 47 additions & 5 deletions modules/core/02-client/keeper/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,58 @@ package keeper_test

import (
"github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
)

func (suite *KeeperTestSuite) TestParams() {
// TestDefaultSetParams tests the default params set are what is expected
func (suite *KeeperTestSuite) TestDefaultSetParams() {
expParams := types.DefaultParams()

params := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetParams(suite.chainA.GetContext())
suite.Require().Equal(expParams, params)
}

// TestParams tests that Param setting and retrieval works properly
func (suite *KeeperTestSuite) TestParams() {
testCases := []struct {
name string
input types.Params
expPass bool
}{
{"success: set default params", types.DefaultParams(), true},
{"success: empty allowedClients", types.NewParams(), true},
{"success: subset of allowedClients", types.NewParams(ibcexported.Tendermint, ibcexported.Localhost), true},
{"failure: contains a single empty string value as allowedClient", types.NewParams(ibcexported.Localhost, ""), false},
}

for _, tc := range testCases {
tc := tc

suite.Run(tc.name, func() {
suite.SetupTest() // reset
ctx := suite.chainA.GetContext()
err := tc.input.Validate()
suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.SetParams(ctx, tc.input)
if tc.expPass {
suite.Require().NoError(err)
expected := tc.input
p := suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.GetParams(ctx)
suite.Require().Equal(expected, p)
} else {
suite.Require().Error(err)
}
})
}
}

// TestUnsetParams tests that trying to get params that are not set panics.
func (suite *KeeperTestSuite) TestUnsetParams() {
suite.SetupTest()
ctx := suite.chainA.GetContext()
store := ctx.KVStore(suite.chainA.GetSimApp().GetKey(ibcexported.StoreKey))
store.Delete([]byte(types.ParamsKey))

expParams.AllowedClients = []string{}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetParams(suite.chainA.GetContext(), expParams)
_ = suite.chainA.App.GetIBCKeeper().ClientKeeper.GetParams(suite.chainA.GetContext())
suite.Require().Empty(expParams.AllowedClients)
suite.Require().Panics(func() {
suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.GetParams(ctx)
})
}
1 change: 1 addition & 0 deletions modules/core/02-client/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
&MsgUpdateClient{},
&MsgUpgradeClient{},
&MsgSubmitMisbehaviour{},
&MsgUpdateClientParams{},
)

msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
Expand Down
3 changes: 3 additions & 0 deletions modules/core/02-client/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const (
// KeyNextClientSequence is the key used to store the next client sequence in
// the keeper.
KeyNextClientSequence = "nextClientSequence"

// ParamsKey is the store key for the IBC client parameters
ParamsKey = "clientParams"
)

// FormatClientIdentifier returns the client identifier with the sequence appended.
Expand Down
26 changes: 26 additions & 0 deletions modules/core/02-client/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var (
_ sdk.Msg = (*MsgUpdateClient)(nil)
_ sdk.Msg = (*MsgSubmitMisbehaviour)(nil)
_ sdk.Msg = (*MsgUpgradeClient)(nil)
_ sdk.Msg = (*MsgUpdateClientParams)(nil)

_ codectypes.UnpackInterfacesMessage = (*MsgCreateClient)(nil)
_ codectypes.UnpackInterfacesMessage = (*MsgUpdateClient)(nil)
Expand Down Expand Up @@ -264,3 +265,28 @@ func (msg MsgSubmitMisbehaviour) UnpackInterfaces(unpacker codectypes.AnyUnpacke
var misbehaviour exported.ClientMessage
return unpacker.UnpackAny(msg.Misbehaviour, &misbehaviour)
}

// NewMsgUpdateClientParams creates a new instance of MsgUpdateClientParams.
func NewMsgUpdateClientParams(authority string, params Params) *MsgUpdateClientParams {
return &MsgUpdateClientParams{
Authority: authority,
Params: params,
}
}

// GetSigners returns the expected signers for a MsgUpdateClientParams message.
func (msg *MsgUpdateClientParams) GetSigners() []sdk.AccAddress {
accAddr, err := sdk.AccAddressFromBech32(msg.Authority)
if err != nil {
panic(err)
}
return []sdk.AccAddress{accAddr}
}

// ValidateBasic performs basic checks on a MsgUpdateClientParams.
func (msg *MsgUpdateClientParams) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
}
return msg.Params.Validate()
}
40 changes: 40 additions & 0 deletions modules/core/02-client/types/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,43 @@ func (suite *TypesTestSuite) TestMsgSubmitMisbehaviour_ValidateBasic() {
}
}
}

// TestMsgUpdateClientParams_ValidateBasic tests ValidateBasic for MsgUpdateClientParams
func (suite *TypesTestSuite) TestMsgUpdateClientParams_ValidateBasic() {
authority := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetAuthority()
testCases := []struct {
name string
msg *types.MsgUpdateClientParams
expPass bool
}{
{
"success: valid authority and params",
types.NewMsgUpdateClientParams(authority, types.DefaultParams()),
true,
},
{
"success: valid authority empty params",
types.NewMsgUpdateClientParams(authority, types.Params{}),
true,
},
{
"failure: invalid authority address",
types.NewMsgUpdateClientParams("invalid", types.DefaultParams()),
false,
},
{
"failure: invalid allowed client",
types.NewMsgUpdateClientParams(authority, types.NewParams("")),
false,
},
}

for _, tc := range testCases {
err := tc.msg.ValidateBasic()
if tc.expPass {
suite.Require().NoError(err, "valid case %s failed", tc.name)
} else {
suite.Require().Error(err, "invalid case %s passed", tc.name)
}
}
}
Loading

0 comments on commit 731a0af

Please sign in to comment.