Skip to content

Commit df918d2

Browse files
aleem1314srdtrk
andauthored
feat(ica/host)!: migrate ica/host to params to be self managed (#3520)
* feat: add proto msg * feat: add msg-server implementation * wip: add migrations * fix failing tests * cleanup * cleanup * Update modules/apps/27-interchain-accounts/host/migrations/v8/migrations.go * fix(transfer): 'p.AllowMessages' missing '&' in 'NewParamSetPair' * fix(transfer): 'p.HostEnabled' missing '&' in 'NewParamSetPair' * refactor(ica/host): reduce code duplication by removing 'IsHostEnabled' and 'GetAllowMessages' functions * refactor(ica/host): moved getter and setters to 'keeper.go' * refactor(ica/host): moved getter and setters to 'keeper.go' * fix(ica/host): handling the SetParam errors now * imp(ica/host): added failure cases to TestValidateParams * feat(ica/host): added codec for msg * fix(ica/host): added host's RegisterInterfaces to module.go * fix(changelog): removed manual addition * imp(ica/host): made GetParams more economical * fix(fee/test): handled ica's 'SetParams' error during testing * imp(ica/host): using ibcerrors instead of relying on sdk's govtypes * style(ica/host): removed '*' from Migrator's keeper * revert(ica/host): reverts to the previous commit as this is more consistent with what is done in module.go * fix(simapp): added ParamKeyTable to the icahost subspace in app.go for migration * feat(ica/host/test): added migrator_test.go * style(ica/host/test): ran gofumpt * feat(ica/host): passing legacySubspace to keeper instead * fix(ica/host): removed unneeded reference to hss from 'NewAppModule' function * fix(simapp): reduced modifications to simapp to 1 * fix(ica/host/test): updated tests * style(ica/host): ran gofumpt * docs(ica/host): fixed a typo * style(ica/host): added a space for import separation * style(ica/host): renamed 'migrator.go' to 'migrations.go' * refactor(ica/host): removed unneeded validate function * style(ica/host): storing ParamsKey using a string * fix(ica/host): registered the msg_server in ica's module.go * style(ica/host): removed unneeded fmt variable assignment * imp(ica/host/test): added more test cases, and refactored the test * style(ica/host/test): ran gofumpt * imp(ica/host): 'GetParams' panics now if it can't find the params * imp(core): added 'ErrInvalidAuthority' * imp(ica/host): uses 'ErrInvalidAuthority' * fix(ica/test): fixed test for the ica module * imp(ica/host/test): added a new test case * imp(ica/host/test): added params test to genesis * style(ica/host): ran gofumpt * imp(ica/host/test): added unset param test to keeper * docs(ica/host): added tracker issue for removing params_legacy.go * style(ica/host): improved test case naming * fix(ica/host/test): fixed a minor inaccuracy with the test in the hopes of increasing codecov * style(ica/host): updated err message * imp(ica/transfer, core/errors): removed ErrInvalidAuthority * style(ica/host): updated nil check to be more consistent * style(transfer): renamed errors to errorsmod to avoid shadowing * imp(ica/host/test): made test shorter * imp(ica/host/test): removed unneeded comment * style(ica/host/test): removed test case field names * refactor(ica/host, fee/test): refactored Validate out of SetParams * style(ica/host): ran gofumpt * imp(ica/types): switched back to 'bz == nil' * style(ica/host/test): looks better * style(ica/host): changed panic message * imp(ica/host): removed redundant Validate from msg server, handled in ValidateBasic * style(ica/host): added code comment * fix(ica/host): increase consensus version * style(ica/host/test): moved success case to top * style(ica/host/test): improve test styling * docs(migration): added changes in app.go * imp(ica/host): improved the error message --------- Co-authored-by: srdtrk <59252793+srdtrk@users.noreply.github.com> Co-authored-by: srdtrk <srdtrk@hotmail.com>
1 parent ba62612 commit df918d2

24 files changed

+1157
-111
lines changed

docs/migrations/v7-to-v8.md

+15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ There are four sections based on the four potential user groups of this document
1616

1717
TODO: https://github.com/cosmos/ibc-go/pull/3505 (extra parameter added to transfer's `GenesisState`)
1818

19+
- You should pass the `authority` to the icahost keeper. ([#3520](https://github.com/cosmos/ibc-go/pull/3520)) See [diff](https://github.com/cosmos/ibc-go/pull/3520/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08a).
20+
21+
```diff
22+
// app.go
23+
24+
// ICA Host keeper
25+
app.ICAHostKeeper = icahostkeeper.NewKeeper(
26+
appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName),
27+
app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack
28+
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
29+
app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(),
30+
+ authtypes.NewModuleAddress(govtypes.ModuleName).String(),
31+
)
32+
```
33+
1934
## IBC Apps
2035

2136
TODO: https://github.com/cosmos/ibc-go/pull/3303

modules/apps/27-interchain-accounts/host/ibc_module.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (im IBCModule) OnChanOpenTry(
5252
counterparty channeltypes.Counterparty,
5353
counterpartyVersion string,
5454
) (string, error) {
55-
if !im.keeper.IsHostEnabled(ctx) {
55+
if !im.keeper.GetParams(ctx).HostEnabled {
5656
return "", types.ErrHostSubModuleDisabled
5757
}
5858

@@ -76,7 +76,7 @@ func (im IBCModule) OnChanOpenConfirm(
7676
portID,
7777
channelID string,
7878
) error {
79-
if !im.keeper.IsHostEnabled(ctx) {
79+
if !im.keeper.GetParams(ctx).HostEnabled {
8080
return types.ErrHostSubModuleDisabled
8181
}
8282

@@ -109,7 +109,7 @@ func (im IBCModule) OnRecvPacket(
109109
_ sdk.AccAddress,
110110
) ibcexported.Acknowledgement {
111111
logger := im.keeper.Logger(ctx)
112-
if !im.keeper.IsHostEnabled(ctx) {
112+
if !im.keeper.GetParams(ctx).HostEnabled {
113113
logger.Info("host submodule is disabled")
114114
return channeltypes.NewErrorAcknowledgement(types.ErrHostSubModuleDisabled)
115115
}

modules/apps/27-interchain-accounts/host/keeper/genesis.go

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, state genesistypes.HostGenesisS
2727
keeper.SetInterchainAccountAddress(ctx, acc.ConnectionId, acc.PortId, acc.AccountAddress)
2828
}
2929

30+
if err := state.Params.Validate(); err != nil {
31+
panic(fmt.Sprintf("could not set ica host params at genesis: %v", err))
32+
}
3033
keeper.SetParams(ctx, state.Params)
3134
}
3235

modules/apps/27-interchain-accounts/host/keeper/genesis_test.go

+61-1
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,71 @@ func (suite *KeeperTestSuite) TestInitGenesis() {
4141
suite.Require().True(found)
4242
suite.Require().Equal(interchainAccAddr.String(), accountAdrr)
4343

44-
expParams := types.NewParams(false, nil)
44+
expParams := genesisState.GetParams()
4545
params := suite.chainA.GetSimApp().ICAHostKeeper.GetParams(suite.chainA.GetContext())
4646
suite.Require().Equal(expParams, params)
4747
}
4848

49+
func (suite *KeeperTestSuite) TestGenesisParams() {
50+
testCases := []struct {
51+
name string
52+
input types.Params
53+
expPass bool
54+
}{
55+
{"success: set default params", types.DefaultParams(), true},
56+
{"success: non-default params", types.NewParams(!types.DefaultHostEnabled, []string{"/cosmos.staking.v1beta1.MsgDelegate"}), true},
57+
{"success: set empty byte for allow messages", types.NewParams(true, nil), true},
58+
{"failure: set empty string for allow messages", types.NewParams(true, []string{""}), false},
59+
{"failure: set space string for allow messages", types.NewParams(true, []string{" "}), false},
60+
}
61+
62+
for _, tc := range testCases {
63+
tc := tc
64+
65+
suite.Run(tc.name, func() {
66+
suite.SetupTest() // reset
67+
interchainAccAddr := icatypes.GenerateAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, TestPortID)
68+
genesisState := genesistypes.HostGenesisState{
69+
ActiveChannels: []genesistypes.ActiveChannel{
70+
{
71+
ConnectionId: ibctesting.FirstConnectionID,
72+
PortId: TestPortID,
73+
ChannelId: ibctesting.FirstChannelID,
74+
},
75+
},
76+
InterchainAccounts: []genesistypes.RegisteredInterchainAccount{
77+
{
78+
ConnectionId: ibctesting.FirstConnectionID,
79+
PortId: TestPortID,
80+
AccountAddress: interchainAccAddr.String(),
81+
},
82+
},
83+
Port: icatypes.HostPortID,
84+
Params: tc.input,
85+
}
86+
if tc.expPass {
87+
keeper.InitGenesis(suite.chainA.GetContext(), suite.chainA.GetSimApp().ICAHostKeeper, genesisState)
88+
89+
channelID, found := suite.chainA.GetSimApp().ICAHostKeeper.GetActiveChannelID(suite.chainA.GetContext(), ibctesting.FirstConnectionID, TestPortID)
90+
suite.Require().True(found)
91+
suite.Require().Equal(ibctesting.FirstChannelID, channelID)
92+
93+
accountAdrr, found := suite.chainA.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainA.GetContext(), ibctesting.FirstConnectionID, TestPortID)
94+
suite.Require().True(found)
95+
suite.Require().Equal(interchainAccAddr.String(), accountAdrr)
96+
97+
expParams := tc.input
98+
params := suite.chainA.GetSimApp().ICAHostKeeper.GetParams(suite.chainA.GetContext())
99+
suite.Require().Equal(expParams, params)
100+
} else {
101+
suite.Require().Panics(func() {
102+
keeper.InitGenesis(suite.chainA.GetContext(), suite.chainA.GetSimApp().ICAHostKeeper, genesisState)
103+
})
104+
}
105+
})
106+
}
107+
}
108+
49109
func (suite *KeeperTestSuite) TestExportGenesis() {
50110
suite.SetupTest()
51111

modules/apps/27-interchain-accounts/host/keeper/keeper.go

+46-15
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import (
2222

2323
// Keeper defines the IBC interchain accounts host keeper
2424
type Keeper struct {
25-
storeKey storetypes.StoreKey
26-
cdc codec.BinaryCodec
27-
paramSpace paramtypes.Subspace
25+
storeKey storetypes.StoreKey
26+
cdc codec.BinaryCodec
27+
legacySubspace paramtypes.Subspace
2828

2929
ics4Wrapper porttypes.ICS4Wrapper
3030
channelKeeper icatypes.ChannelKeeper
@@ -34,34 +34,40 @@ type Keeper struct {
3434
scopedKeeper exported.ScopedKeeper
3535

3636
msgRouter icatypes.MessageRouter
37+
38+
// the address capable of executing a MsgUpdateParams message. Typically, this
39+
// should be the x/gov module account.
40+
authority string
3741
}
3842

3943
// NewKeeper creates a new interchain accounts host Keeper instance
4044
func NewKeeper(
41-
cdc codec.BinaryCodec, key storetypes.StoreKey, paramSpace paramtypes.Subspace,
45+
cdc codec.BinaryCodec, key storetypes.StoreKey, legacySubspace paramtypes.Subspace,
4246
ics4Wrapper porttypes.ICS4Wrapper, channelKeeper icatypes.ChannelKeeper, portKeeper icatypes.PortKeeper,
4347
accountKeeper icatypes.AccountKeeper, scopedKeeper exported.ScopedKeeper, msgRouter icatypes.MessageRouter,
48+
authority string,
4449
) Keeper {
4550
// ensure ibc interchain accounts module account is set
4651
if addr := accountKeeper.GetModuleAddress(icatypes.ModuleName); addr == nil {
4752
panic("the Interchain Accounts module account has not been set")
4853
}
4954

5055
// set KeyTable if it has not already been set
51-
if !paramSpace.HasKeyTable() {
52-
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
56+
if !legacySubspace.HasKeyTable() {
57+
legacySubspace = legacySubspace.WithKeyTable(types.ParamKeyTable())
5358
}
5459

5560
return Keeper{
56-
storeKey: key,
57-
cdc: cdc,
58-
paramSpace: paramSpace,
59-
ics4Wrapper: ics4Wrapper,
60-
channelKeeper: channelKeeper,
61-
portKeeper: portKeeper,
62-
accountKeeper: accountKeeper,
63-
scopedKeeper: scopedKeeper,
64-
msgRouter: msgRouter,
61+
storeKey: key,
62+
cdc: cdc,
63+
legacySubspace: legacySubspace,
64+
ics4Wrapper: ics4Wrapper,
65+
channelKeeper: channelKeeper,
66+
portKeeper: portKeeper,
67+
accountKeeper: accountKeeper,
68+
scopedKeeper: scopedKeeper,
69+
msgRouter: msgRouter,
70+
authority: authority,
6571
}
6672
}
6773

@@ -199,3 +205,28 @@ func (k Keeper) SetInterchainAccountAddress(ctx sdk.Context, connectionID, portI
199205
store := ctx.KVStore(k.storeKey)
200206
store.Set(icatypes.KeyOwnerAccount(portID, connectionID), []byte(address))
201207
}
208+
209+
// GetAuthority returns the 27-interchain-accounts host submodule's authority.
210+
func (k Keeper) GetAuthority() string {
211+
return k.authority
212+
}
213+
214+
// GetParams returns the total set of the host submodule parameters.
215+
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
216+
store := ctx.KVStore(k.storeKey)
217+
bz := store.Get([]byte(types.ParamsKey))
218+
if bz == nil { // only panic on unset params and not on empty params
219+
panic("ica/host params are not set in store")
220+
}
221+
222+
var params types.Params
223+
k.cdc.MustUnmarshal(bz, &params)
224+
return params
225+
}
226+
227+
// SetParams sets the total set of the host submodule parameters.
228+
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
229+
store := ctx.KVStore(k.storeKey)
230+
bz := k.cdc.MustMarshal(&params)
231+
store.Set([]byte(types.ParamsKey), bz)
232+
}

modules/apps/27-interchain-accounts/host/keeper/keeper_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/stretchr/testify/suite"
77

88
genesistypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/genesis/types"
9+
"github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types"
910
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
1011
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
1112
ibctesting "github.com/cosmos/ibc-go/v7/testing"
@@ -218,3 +219,52 @@ func (suite *KeeperTestSuite) TestSetInterchainAccountAddress() {
218219
suite.Require().True(found)
219220
suite.Require().Equal(expectedAccAddr, retrievedAddr)
220221
}
222+
223+
func (suite *KeeperTestSuite) TestParams() {
224+
expParams := types.DefaultParams()
225+
226+
params := suite.chainA.GetSimApp().ICAHostKeeper.GetParams(suite.chainA.GetContext())
227+
suite.Require().Equal(expParams, params)
228+
229+
testCases := []struct {
230+
name string
231+
input types.Params
232+
expPass bool
233+
}{
234+
{"success: set default params", types.DefaultParams(), true},
235+
{"success: non-default params", types.NewParams(!types.DefaultHostEnabled, []string{"/cosmos.staking.v1beta1.MsgDelegate"}), true},
236+
{"success: set empty byte for allow messages", types.NewParams(true, nil), true},
237+
{"failure: set empty string for allow messages", types.NewParams(true, []string{""}), false},
238+
{"failure: set space string for allow messages", types.NewParams(true, []string{" "}), false},
239+
}
240+
241+
for _, tc := range testCases {
242+
tc := tc
243+
244+
suite.Run(tc.name, func() {
245+
suite.SetupTest() // reset
246+
ctx := suite.chainA.GetContext()
247+
err := tc.input.Validate()
248+
suite.chainA.GetSimApp().ICAHostKeeper.SetParams(ctx, tc.input)
249+
if tc.expPass {
250+
suite.Require().NoError(err)
251+
expected := tc.input
252+
p := suite.chainA.GetSimApp().ICAHostKeeper.GetParams(ctx)
253+
suite.Require().Equal(expected, p)
254+
} else {
255+
suite.Require().Error(err)
256+
}
257+
})
258+
}
259+
}
260+
261+
func (suite *KeeperTestSuite) TestUnsetParams() {
262+
suite.SetupTest()
263+
ctx := suite.chainA.GetContext()
264+
store := suite.chainA.GetContext().KVStore(suite.chainA.GetSimApp().GetKey(types.SubModuleName))
265+
store.Delete([]byte(types.ParamsKey))
266+
267+
suite.Require().Panics(func() {
268+
suite.chainA.GetSimApp().ICAHostKeeper.GetParams(ctx)
269+
})
270+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package keeper
2+
3+
import (
4+
sdk "github.com/cosmos/cosmos-sdk/types"
5+
"github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types"
6+
)
7+
8+
// Migrator is a struct for handling in-place state migrations.
9+
type Migrator struct {
10+
keeper *Keeper
11+
}
12+
13+
// NewMigrator returns Migrator instance for the state migration.
14+
func NewMigrator(k *Keeper) Migrator {
15+
return Migrator{
16+
keeper: k,
17+
}
18+
}
19+
20+
// MigrateParams migrates the host submodule's parameters from the x/params to self store.
21+
func (m Migrator) MigrateParams(ctx sdk.Context) error {
22+
var params types.Params
23+
m.keeper.legacySubspace.GetParamSet(ctx, &params)
24+
25+
if err := params.Validate(); err != nil {
26+
return err
27+
}
28+
m.keeper.SetParams(ctx, params)
29+
30+
return nil
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package keeper_test
2+
3+
import (
4+
"fmt"
5+
6+
icahostkeeper "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/keeper"
7+
icahosttypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types"
8+
)
9+
10+
func (suite *KeeperTestSuite) TestMigratorMigrateParams() {
11+
testCases := []struct {
12+
msg string
13+
malleate func()
14+
expectedParams icahosttypes.Params
15+
}{
16+
{
17+
"success: default params",
18+
func() {
19+
params := icahosttypes.DefaultParams()
20+
subspace := suite.chainA.GetSimApp().GetSubspace(icahosttypes.SubModuleName) // get subspace
21+
subspace.SetParamSet(suite.chainA.GetContext(), &params) // set params
22+
},
23+
icahosttypes.DefaultParams(),
24+
},
25+
}
26+
27+
for _, tc := range testCases {
28+
suite.Run(fmt.Sprintf("case %s", tc.msg), func() {
29+
suite.SetupTest() // reset
30+
31+
tc.malleate() // explicitly set params
32+
33+
migrator := icahostkeeper.NewMigrator(&suite.chainA.GetSimApp().ICAHostKeeper)
34+
err := migrator.MigrateParams(suite.chainA.GetContext())
35+
suite.Require().NoError(err)
36+
37+
params := suite.chainA.GetSimApp().ICAHostKeeper.GetParams(suite.chainA.GetContext())
38+
suite.Require().Equal(tc.expectedParams, params)
39+
})
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package keeper
2+
3+
import (
4+
"context"
5+
6+
errorsmod "cosmossdk.io/errors"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
9+
"github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types"
10+
ibcerrors "github.com/cosmos/ibc-go/v7/modules/core/errors"
11+
)
12+
13+
var _ types.MsgServer = (*msgServer)(nil)
14+
15+
type msgServer struct {
16+
*Keeper
17+
}
18+
19+
// NewMsgServerImpl returns an implementation of the ICS27 host MsgServer interface
20+
// for the provided Keeper.
21+
func NewMsgServerImpl(keeper *Keeper) types.MsgServer {
22+
return &msgServer{Keeper: keeper}
23+
}
24+
25+
// UpdateParams updates the host submodule's params.
26+
func (m msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
27+
if m.authority != msg.Authority {
28+
return nil, errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "expected %s, got %s", m.authority, msg.Authority)
29+
}
30+
31+
ctx := sdk.UnwrapSDKContext(goCtx)
32+
m.SetParams(ctx, msg.Params)
33+
34+
return &types.MsgUpdateParamsResponse{}, nil
35+
}

0 commit comments

Comments
 (0)