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

fix: ica handshake reopening channel - use GetAppVersion in favour of channel.Version #2302

Merged
merged 9 commits into from Sep 21, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -67,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (transfer) [\#2034](https://github.com/cosmos/ibc-go/pull/2034) Transfer Keeper now expects a keeper which fulfills the expected `ScopedKeeper` interface for the capability keeper.
* (05-port) [\#2025](https://github.com/cosmos/ibc-go/pull/2025) Port Keeper now expects a keeper which fulfills the expected `ScopedKeeper` interface for the capability keeper.
* (04-channel) [\#2024](https://github.com/cosmos/ibc-go/pull/2024) Channel Keeper now expects a keeper which fulfills the expected `ScopedKeeper` interface for the capability keeper.
* (apps/27-interchain-accounts)[\#2302](https://github.com/cosmos/ibc-go/pull/2302) Handle unwrapping of channel version in interchain accounts channel reopening handshake flow. The `host` submodule `Keeper` now requires an `ICS4Wrapper` similarly to the `controller` submodule.

### State Machine Breaking

Expand Down
Expand Up @@ -70,7 +70,12 @@ func (k Keeper) OnChanOpenInit(
return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s is already OPEN", activeChannelID, portID)
}

if !icatypes.IsPreviousMetadataEqual(channel.Version, metadata) {
appVersion, found := k.GetAppVersion(ctx, portID, activeChannelID)
if !found {
panic(fmt.Sprintf("active channel mapping set for %s, but channel does not exist in channel store", activeChannelID))
Copy link
Contributor

Choose a reason for hiding this comment

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

looks like this panic introduces multiple conventions in the function (error return + panic) does it make more sense to return an error instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to panic?

Copy link
Member Author

Choose a reason for hiding this comment

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

As mentioned earlier in person I just followed essentially the same used above here - as in some places in ibc-go code we just panic because it's unreachable code.

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe we could add a comment indicating as such? The message we panic with seems like it would be a regular error that we could run into.

Copy link
Contributor

Choose a reason for hiding this comment

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

a nit: channel does not exist in channel store is kind of confusing if the error is GetAppVersion returning not found -- maybe something like channel version does not exist?

}

if !icatypes.IsPreviousMetadataEqual(appVersion, metadata) {
return "", sdkerrors.Wrap(icatypes.ErrInvalidVersion, "previous active channel metadata does not match provided version")
}
}
Expand Down
15 changes: 14 additions & 1 deletion modules/apps/27-interchain-accounts/host/ibc_module_test.go
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/host/types"
icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"
feetypes "github.com/cosmos/ibc-go/v5/modules/apps/29-fee/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
Expand Down Expand Up @@ -77,7 +78,7 @@ func RegisterInterchainAccount(endpoint *ibctesting.Endpoint, owner string) erro

channelSequence := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextChannelSequence(endpoint.Chain.GetContext())

if err := endpoint.Chain.GetSimApp().ICAControllerKeeper.RegisterInterchainAccount(endpoint.Chain.GetContext(), endpoint.ConnectionID, owner, TestVersion); err != nil {
if err := endpoint.Chain.GetSimApp().ICAControllerKeeper.RegisterInterchainAccount(endpoint.Chain.GetContext(), endpoint.ConnectionID, owner, endpoint.ChannelConfig.Version); err != nil {
return err
}

Expand Down Expand Up @@ -618,6 +619,18 @@ func (suite *InterchainAccountsTestSuite) fundICAWallet(ctx sdk.Context, portID
// A new channel will be opened for the controller portID. The interchain account address should remain unchanged.
func (suite *InterchainAccountsTestSuite) TestControlAccountAfterChannelClose() {
path := NewICAPath(suite.chainA, suite.chainB)

// use a fee enabled version to cover unwrapping channel version code paths
feeMetadata := feetypes.Metadata{
FeeVersion: feetypes.Version,
AppVersion: TestVersion,
}

feeICAVersion := string(feetypes.ModuleCdc.MustMarshalJSON(&feeMetadata))

path.EndpointA.ChannelConfig.Version = feeICAVersion
path.EndpointB.ChannelConfig.Version = feeICAVersion

suite.coordinator.SetupConnections(path)

err := SetupICAPath(path, TestOwnerAddress)
Expand Down
Expand Up @@ -59,7 +59,12 @@ func (k Keeper) OnChanOpenTry(
return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s is already OPEN", activeChannelID, portID)
}

if !icatypes.IsPreviousMetadataEqual(channel.Version, metadata) {
appVersion, found := k.GetAppVersion(ctx, portID, activeChannelID)
if !found {
panic(fmt.Sprintf("active channel mapping set for %s, but channel does not exist in channel store", activeChannelID))
}

if !icatypes.IsPreviousMetadataEqual(appVersion, metadata) {
return "", sdkerrors.Wrap(icatypes.ErrInvalidVersion, "previous active channel metadata does not match provided version")
}
}
Expand Down
9 changes: 8 additions & 1 deletion modules/apps/27-interchain-accounts/host/keeper/keeper.go
Expand Up @@ -24,6 +24,7 @@ type Keeper struct {
cdc codec.BinaryCodec
paramSpace paramtypes.Subspace

ics4Wrapper icatypes.ICS4Wrapper
channelKeeper icatypes.ChannelKeeper
portKeeper icatypes.PortKeeper
accountKeeper icatypes.AccountKeeper
Expand All @@ -36,7 +37,7 @@ type Keeper struct {
// NewKeeper creates a new interchain accounts host Keeper instance
func NewKeeper(
cdc codec.BinaryCodec, key storetypes.StoreKey, paramSpace paramtypes.Subspace,
channelKeeper icatypes.ChannelKeeper, portKeeper icatypes.PortKeeper,
ics4Wrapper icatypes.ICS4Wrapper, channelKeeper icatypes.ChannelKeeper, portKeeper icatypes.PortKeeper,
accountKeeper icatypes.AccountKeeper, scopedKeeper icatypes.ScopedKeeper, msgRouter icatypes.MessageRouter,
) Keeper {
// ensure ibc interchain accounts module account is set
Expand All @@ -53,6 +54,7 @@ func NewKeeper(
storeKey: key,
cdc: cdc,
paramSpace: paramSpace,
ics4Wrapper: ics4Wrapper,
channelKeeper: channelKeeper,
portKeeper: portKeeper,
accountKeeper: accountKeeper,
Expand Down Expand Up @@ -90,6 +92,11 @@ func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability
return k.scopedKeeper.ClaimCapability(ctx, cap, name)
}

// GetAppVersion calls the ICS4Wrapper GetAppVersion function.
func (k Keeper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) {
return k.ics4Wrapper.GetAppVersion(ctx, portID, channelID)
}

// GetActiveChannelID retrieves the active channelID from the store keyed by the provided connectionID and portID
func (k Keeper) GetActiveChannelID(ctx sdk.Context, connectionID, portID string) (string, bool) {
store := ctx.KVStore(k.storeKey)
Expand Down
1 change: 1 addition & 0 deletions testing/simapp/app.go
Expand Up @@ -406,6 +406,7 @@ func NewSimApp(
// ICA Host keeper
app.ICAHostKeeper = icahostkeeper.NewKeeper(
appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName),
app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(),
)
Expand Down