diff --git a/CHANGELOG.md b/CHANGELOG.md index f9a87dbc934..df41c312f38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features +* (apps/27-interchain-accounts) [\#5633](https://github.com/cosmos/ibc-go/pull/5633) Allow new ICA channels to use unordered ordering. + ### Bug Fixes ## [v7.4.0](https://github.com/cosmos/ibc-go/releases/tag/v7.4.0) - 2024-04-05 diff --git a/docs/apps/interchain-accounts/active-channels.md b/docs/apps/interchain-accounts/active-channels.md index 61ab551582c..45033136fdc 100644 --- a/docs/apps/interchain-accounts/active-channels.md +++ b/docs/apps/interchain-accounts/active-channels.md @@ -4,7 +4,13 @@ order: 9 # Understanding Active Channels -The Interchain Accounts module uses [ORDERED channels](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#ordering) to maintain the order of transactions when sending packets from a controller to a host chain. A limitation when using ORDERED channels is that when a packet times out the channel will be closed. +The Interchain Accounts module uses either [ORDERED or UNORDERED](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#ordering) channels. + +When using `ORDERED` channels, the order of transactions when sending packets from a controller to a host chain is maintained. + +When using `UNORDERED` channels, there is no guarantee that the order of transactions when sending packets from the controller to the host chain is maintained. + +> A limitation when using ORDERED channels is that when a packet times out the channel will be closed. In the case of a channel closing, a controller chain needs to be able to regain access to the interchain account registered on this channel. `Active Channels` enable this functionality. diff --git a/docs/apps/interchain-accounts/client.md b/docs/apps/interchain-accounts/client.md index 09b2af7e8e0..48e24068282 100644 --- a/docs/apps/interchain-accounts/client.md +++ b/docs/apps/interchain-accounts/client.md @@ -34,6 +34,25 @@ The `tx` commands allow users to interact with the controller submodule. simd tx interchain-accounts controller --help ``` +#### `register` + +The `register` command allows users to register an interchain account on a host chain on the provided connection. + +```shell +simd tx interchain-accounts controller register [connection-id] [flags] +``` + +During registration a new channel is set up between controller and host. There are two flags available that influence the channel that is created: + +- `--version` to specify the (JSON-formatted) version string of the channel. For example: `{\"version\":\"ics27-1\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\",\"controller_connection_id\":\"connection-0\",\"host_connection_id\":\"connection-0\"}`. Passing a custom version string is useful if you want to specify, for example, the encoding format of the interchain accounts packet data (either `proto3` or `proto3json`). If not specified the controller submodule will generate a default version string. +- `--ordering` to specify the ordering of the channel. Available options are `order_ordered` (default if not specified) and `order_unordered`. + +Example: + +```shell +simd tx interchain-accounts controller register connection-0 --ordering order_unordered --from cosmos1.. +``` + #### `send-tx` The `send-tx` command allows users to send a transaction on the provided connection to be executed using an interchain account on the host chain. diff --git a/docs/apps/interchain-accounts/messages.md b/docs/apps/interchain-accounts/messages.md index 1052f2b5081..f1f735de2e2 100644 --- a/docs/apps/interchain-accounts/messages.md +++ b/docs/apps/interchain-accounts/messages.md @@ -13,6 +13,7 @@ type MsgRegisterInterchainAccount struct { Owner string ConnectionID string Version string + Ordering channeltypes.Order } ``` diff --git a/docs/apps/interchain-accounts/overview.md b/docs/apps/interchain-accounts/overview.md index 97133f15e94..c33073db544 100644 --- a/docs/apps/interchain-accounts/overview.md +++ b/docs/apps/interchain-accounts/overview.md @@ -30,4 +30,13 @@ SDK modules on a chain are assumed to be trustworthy. For example, there are no The implementation of ICS-27 in ibc-go uses this assumption in its security considerations. -The implementation assumes other IBC application modules will not bind to ports within the ICS-27 namespace. +The implementation assumes other IBC application modules will not bind to ports within the ICS-27 namespace. + +## Channel Closure + +The provided interchain account host and controller implementations do not support `ChanCloseInit`. However, they do support `ChanCloseConfirm`. +This means that the host and controller modules cannot close channels, but they will confirm channel closures initiated by other implementations of ICS-27. + +In the event of a channel closing (due to a packet timeout in an ordered channel, for example), the interchain account associated with that channel can become accessible again if a new channel is created with a (JSON-formatted) version string that encodes the exact same `Metadata` information of the previous channel. The channel can be reopened using either [`MsgRegisterInterchainAccount`](./05-messages.md#msgregisterinterchainaccount) or `MsgChannelOpenInit`. If `MsgRegisterInterchainAccount` is used, then it is possible to leave the `version` field of the message empty, since it will be filled in by the controller submodule. If `MsgChannelOpenInit` is used, then the `version` field must be provided with the correct JSON-encoded `Metadata` string. See section [Understanding Active Channels](./09-active-channels.md#understanding-active-channels) for more information. + +When reopening a channel with the default controller submodule, the ordering of the channel cannot be changed. In order to change the ordering of the channel, the channel has to go through a [channel upgrade handshake](../../01-ibc/06-channel-upgrades.md) or reopen the channel with a custom controller implementation. diff --git a/modules/apps/27-interchain-accounts/controller/client/cli/tx.go b/modules/apps/27-interchain-accounts/controller/client/cli/tx.go index 44094f7b152..eb0af19693b 100644 --- a/modules/apps/27-interchain-accounts/controller/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/controller/client/cli/tx.go @@ -13,11 +13,15 @@ import ( "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" ) const ( // The controller chain channel version - flagVersion = "version" + flagVersion = "version" + // The channel ordering + flagOrdering = "ordering" flagRelativePacketTimeout = "relative-packet-timeout" ) @@ -28,8 +32,8 @@ func newRegisterInterchainAccountCmd() *cobra.Command { Long: strings.TrimSpace(`Register an account on the counterparty chain via the connection id from the source chain. Connection identifier should be for the source chain and the interchain account will be created on the counterparty chain. Callers are expected to -provide the appropriate application version string via {version} flag. Generates a new -port identifier using the provided owner string, binds to the port identifier and claims +provide the appropriate application version string via {version} flag and the desired ordering +via the {ordering} flag. Generates a new port identifier using the provided owner string, binds to the port identifier and claims the associated capability.`), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -45,13 +49,19 @@ the associated capability.`), return err } - msg := types.NewMsgRegisterInterchainAccount(connectionID, owner, version) + ordering, err := parseOrdering(cmd) + if err != nil { + return err + } + + msg := types.NewMsgRegisterInterchainAccountWithOrdering(connectionID, owner, version, ordering) return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } cmd.Flags().String(flagVersion, "", "Controller chain channel version") + cmd.Flags().String(flagOrdering, channeltypes.ORDERED.String(), fmt.Sprintf("Channel ordering, can be one of: %s", strings.Join(connectiontypes.SupportedOrderings, ", "))) flags.AddTxFlagsToCmd(cmd) return cmd @@ -107,3 +117,18 @@ appropriate relative timeoutTimestamp must be provided with flag {relative-packe return cmd } + +// parseOrdering gets the channel ordering from the flags. +func parseOrdering(cmd *cobra.Command) (channeltypes.Order, error) { + orderString, err := cmd.Flags().GetString(flagOrdering) + if err != nil { + return channeltypes.NONE, err + } + + order, found := channeltypes.Order_value[strings.ToUpper(orderString)] + if !found { + return channeltypes.NONE, fmt.Errorf("invalid channel ordering: %s", orderString) + } + + return channeltypes.Order(order), nil +} diff --git a/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go b/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go index ef4089ed5b3..9eea42e851e 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go @@ -160,11 +160,6 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenInit() { suite.chainA.GetSimApp().ICAControllerKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(false)) }, false, }, - { - "ICA OnChanOpenInit fails - UNORDERED channel", func() { - channel.Ordering = channeltypes.UNORDERED - }, false, - }, { "ICA auth module callback fails", func() { suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenInit = func(ctx sdk.Context, order channeltypes.Order, connectionHops []string, diff --git a/modules/apps/27-interchain-accounts/controller/keeper/account.go b/modules/apps/27-interchain-accounts/controller/keeper/account.go index c1418595508..2abe1505527 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/account.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/account.go @@ -39,7 +39,7 @@ func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner, k.SetMiddlewareEnabled(ctx, portID, connectionID) - _, err = k.registerInterchainAccount(ctx, connectionID, portID, version) + _, err = k.registerInterchainAccount(ctx, connectionID, portID, version, channeltypes.ORDERED) if err != nil { return err } @@ -49,7 +49,7 @@ func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner, // registerInterchainAccount registers an interchain account, returning the channel id of the MsgChannelOpenInitResponse // and an error if one occurred. -func (k Keeper) registerInterchainAccount(ctx sdk.Context, connectionID, portID, version string) (string, error) { +func (k Keeper) registerInterchainAccount(ctx sdk.Context, connectionID, portID, version string, ordering channeltypes.Order) (string, error) { // if there is an active channel for this portID / connectionID return an error activeChannelID, found := k.GetOpenActiveChannel(ctx, connectionID, portID) if found { @@ -66,7 +66,7 @@ func (k Keeper) registerInterchainAccount(ctx sdk.Context, connectionID, portID, } } - msg := channeltypes.NewMsgChannelOpenInit(portID, version, channeltypes.ORDERED, []string{connectionID}, icatypes.HostPortID, authtypes.NewModuleAddress(icatypes.ModuleName).String()) + msg := channeltypes.NewMsgChannelOpenInit(portID, version, ordering, []string{connectionID}, icatypes.HostPortID, authtypes.NewModuleAddress(icatypes.ModuleName).String()) handler := k.msgRouter.Handler(msg) res, err := handler(ctx, msg) if err != nil { diff --git a/modules/apps/27-interchain-accounts/controller/keeper/handshake.go b/modules/apps/27-interchain-accounts/controller/keeper/handshake.go index 51644e4050e..fa0da1166d2 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/handshake.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/handshake.go @@ -13,8 +13,7 @@ import ( ) // OnChanOpenInit performs basic validation of channel initialization. -// The channel order must be ORDERED, the counterparty port identifier -// must be the host chain representation as defined in the types package, +// The counterparty port identifier must be the host chain representation as defined in the types package, // the channel version must be equal to the version in the types package, // there must not be an active channel for the specfied port identifier, // and the interchain accounts module must be able to claim the channel @@ -29,10 +28,6 @@ func (k Keeper) OnChanOpenInit( counterparty channeltypes.Counterparty, version string, ) (string, error) { - if order != channeltypes.ORDERED { - return "", sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s", channeltypes.ORDERED, order) - } - if !strings.HasPrefix(portID, icatypes.ControllerPortPrefix) { return "", sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "expected %s{owner-account-address}, got %s", icatypes.ControllerPortPrefix, portID) } @@ -66,8 +61,12 @@ func (k Keeper) OnChanOpenInit( panic(fmt.Sprintf("active channel mapping set for %s but channel does not exist in channel store", activeChannelID)) } - if channel.State == channeltypes.OPEN { - return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s is already OPEN", activeChannelID, portID) + if channel.State != channeltypes.CLOSED { + return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s must be %s", activeChannelID, portID, channeltypes.CLOSED) + } + + if channel.Ordering != order { + return "", sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "order cannot change when reopening a channel expected %s, got %s", channel.Ordering, order) } appVersion, found := k.GetAppVersion(ctx, portID, activeChannelID) diff --git a/modules/apps/27-interchain-accounts/controller/keeper/handshake_test.go b/modules/apps/27-interchain-accounts/controller/keeper/handshake_test.go index 79df5aadad6..75add555418 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/handshake_test.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/handshake_test.go @@ -4,6 +4,7 @@ import ( capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v7/modules/core/24-host" ibctesting "github.com/cosmos/ibc-go/v7/testing" @@ -20,12 +21,12 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { testCases := []struct { name string malleate func() - expPass bool + expError error }{ { "success", func() {}, - true, + nil, }, { "success: previous active channel closed", @@ -43,14 +44,14 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { path.EndpointA.SetChannel(channel) }, - true, + nil, }, { "success: empty channel version returns default metadata JSON string", func() { channel.Version = "" }, - true, + nil, }, { "success: channel reopening", @@ -67,7 +68,25 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { path.EndpointA.ChannelID = "" path.EndpointB.ChannelID = "" }, - true, + nil, + }, + { + "failure: different ordering from previous channel", + func() { + suite.chainA.GetSimApp().ICAControllerKeeper.SetActiveChannelID(suite.chainA.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) + + counterparty := channeltypes.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) + channel := channeltypes.Channel{ + State: channeltypes.CLOSED, + Ordering: channeltypes.UNORDERED, + Counterparty: counterparty, + ConnectionHops: []string{path.EndpointA.ConnectionID}, + Version: TestVersion, + } + + path.EndpointA.SetChannel(channel) + }, + channeltypes.ErrInvalidChannelOrdering, }, { "invalid metadata - previous metadata is different", @@ -91,21 +110,14 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { } path.EndpointA.SetChannel(closedChannel) }, - false, - }, - { - "invalid order - UNORDERED", - func() { - channel.Ordering = channeltypes.UNORDERED - }, - false, + icatypes.ErrInvalidVersion, }, { "invalid port ID", func() { path.EndpointA.ChannelConfig.PortID = "invalid-port-id" //nolint:goconst }, - false, + icatypes.ErrInvalidControllerPort, }, { "invalid counterparty port ID", @@ -113,7 +125,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { path.EndpointA.SetChannel(*channel) channel.Counterparty.PortId = "invalid-port-id" }, - false, + icatypes.ErrInvalidHostPort, }, { "invalid metadata bytestring", @@ -121,7 +133,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { path.EndpointA.SetChannel(*channel) channel.Version = "invalid-metadata-bytestring" }, - false, + icatypes.ErrUnknownDataType, }, { "unsupported encoding format", @@ -134,7 +146,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.Version = string(versionBytes) path.EndpointA.SetChannel(*channel) }, - false, + icatypes.ErrInvalidCodec, }, { "unsupported transaction type", @@ -147,7 +159,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.Version = string(versionBytes) path.EndpointA.SetChannel(*channel) }, - false, + icatypes.ErrUnknownDataType, }, { "connection not found", @@ -155,7 +167,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.ConnectionHops = []string{"invalid-connnection-id"} path.EndpointA.SetChannel(*channel) }, - false, + connectiontypes.ErrConnectionNotFound, }, { "connection not found with default empty channel version", @@ -163,7 +175,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.ConnectionHops = []string{"connection-10"} channel.Version = "" }, - false, + connectiontypes.ErrConnectionNotFound, }, { "invalid controller connection ID", @@ -176,7 +188,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.Version = string(versionBytes) path.EndpointA.SetChannel(*channel) }, - false, + connectiontypes.ErrInvalidConnection, }, { "invalid host connection ID", @@ -189,7 +201,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.Version = string(versionBytes) path.EndpointA.SetChannel(*channel) }, - false, + connectiontypes.ErrInvalidConnection, }, { "invalid version", @@ -202,10 +214,10 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { channel.Version = string(versionBytes) path.EndpointA.SetChannel(*channel) }, - false, + icatypes.ErrInvalidVersion, }, { - "channel is already active", + "channel is already active (OPEN state)", func() { suite.chainA.GetSimApp().ICAControllerKeeper.SetActiveChannelID(suite.chainA.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) @@ -219,7 +231,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { } suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, channel) }, - false, + icatypes.ErrActiveChannelAlreadySet, }, } @@ -263,11 +275,13 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, chanCap, channel.Counterparty, channel.Version, ) - if tc.expPass { + expPass := tc.expError == nil + if expPass { suite.Require().NoError(err) suite.Require().Equal(string(versionBytes), version) } else { suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expError) } }) } diff --git a/modules/apps/27-interchain-accounts/controller/keeper/msg_server.go b/modules/apps/27-interchain-accounts/controller/keeper/msg_server.go index fe0535c7022..f118fbd75a3 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/msg_server.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/msg_server.go @@ -37,7 +37,7 @@ func (s msgServer) RegisterInterchainAccount(goCtx context.Context, msg *types.M s.SetMiddlewareDisabled(ctx, portID, msg.ConnectionId) - channelID, err := s.registerInterchainAccount(ctx, msg.ConnectionId, portID, msg.Version) + channelID, err := s.registerInterchainAccount(ctx, msg.ConnectionId, portID, msg.Version, msg.Ordering) if err != nil { s.Logger(ctx).Error("error registering interchain account", "error", err.Error()) return nil, err diff --git a/modules/apps/27-interchain-accounts/controller/types/msgs.go b/modules/apps/27-interchain-accounts/controller/types/msgs.go index e01a3798203..400e48bf5d0 100644 --- a/modules/apps/27-interchain-accounts/controller/types/msgs.go +++ b/modules/apps/27-interchain-accounts/controller/types/msgs.go @@ -7,17 +7,31 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v7/modules/core/24-host" ) var _ sdk.Msg = &MsgRegisterInterchainAccount{} -// NewMsgRegisterInterchainAccount creates a new instance of MsgRegisterInterchainAccount +// NewMsgRegisterInterchainAccountWithOrdering creates a new instance of MsgRegisterInterchainAccount. +func NewMsgRegisterInterchainAccountWithOrdering(connectionID, owner, version string, ordering channeltypes.Order) *MsgRegisterInterchainAccount { + return &MsgRegisterInterchainAccount{ + ConnectionId: connectionID, + Owner: owner, + Version: version, + Ordering: ordering, + } +} + +// NewMsgRegisterInterchainAccount creates a new instance of MsgRegisterInterchainAccount. +// It uses channeltypes.ORDERED as the default ordering. Breakage in v9.0.0 will allow the ordering to be provided +// directly. Use NewMsgRegisterInterchainAccountWithOrder to provide the ordering in previous versions. func NewMsgRegisterInterchainAccount(connectionID, owner, version string) *MsgRegisterInterchainAccount { return &MsgRegisterInterchainAccount{ ConnectionId: connectionID, Owner: owner, Version: version, + Ordering: channeltypes.ORDERED, } } diff --git a/modules/apps/27-interchain-accounts/controller/types/tx.pb.go b/modules/apps/27-interchain-accounts/controller/types/tx.pb.go index b15979a713e..d800fcd0616 100644 --- a/modules/apps/27-interchain-accounts/controller/types/tx.pb.go +++ b/modules/apps/27-interchain-accounts/controller/types/tx.pb.go @@ -9,7 +9,8 @@ import ( _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" - types "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + types1 "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + types "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -31,9 +32,10 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // MsgRegisterInterchainAccount defines the payload for Msg/RegisterAccount type MsgRegisterInterchainAccount struct { - Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` - ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Ordering types.Order `protobuf:"varint,4,opt,name=ordering,proto3,enum=ibc.core.channel.v1.Order" json:"ordering,omitempty"` } func (m *MsgRegisterInterchainAccount) Reset() { *m = MsgRegisterInterchainAccount{} } @@ -124,9 +126,9 @@ func (m *MsgRegisterInterchainAccountResponse) GetPortId() string { // MsgSendTx defines the payload for Msg/SendTx type MsgSendTx struct { - Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` - ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - PacketData types.InterchainAccountPacketData `protobuf:"bytes,3,opt,name=packet_data,json=packetData,proto3" json:"packet_data" yaml:"packet_data"` + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` + PacketData types1.InterchainAccountPacketData `protobuf:"bytes,3,opt,name=packet_data,json=packetData,proto3" json:"packet_data" yaml:"packet_data"` // Relative timeout timestamp provided will be added to the current block time during transaction execution. // The timeout timestamp must be non-zero. RelativeTimeout uint64 `protobuf:"varint,4,opt,name=relative_timeout,json=relativeTimeout,proto3" json:"relative_timeout,omitempty" yaml:"relative_timeout"` @@ -222,43 +224,46 @@ func init() { } var fileDescriptor_7def041328c84a30 = []byte{ - // 570 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x94, 0xbf, 0x6f, 0xd3, 0x40, - 0x14, 0xc7, 0xed, 0x34, 0xa4, 0xcd, 0x95, 0x5f, 0xb5, 0x82, 0x30, 0x06, 0xd9, 0x95, 0xc5, 0x50, - 0x09, 0xc5, 0xa7, 0x84, 0x4a, 0x95, 0x8a, 0x3a, 0x10, 0x15, 0xa4, 0x0c, 0x91, 0x22, 0xd3, 0x01, - 0xb1, 0x44, 0x97, 0xf3, 0xc9, 0x39, 0x70, 0xee, 0x8c, 0xef, 0x62, 0xda, 0x91, 0x0d, 0x16, 0xc4, - 0xc6, 0xda, 0xbf, 0x82, 0x7f, 0x81, 0x8e, 0x1d, 0x99, 0xac, 0x2a, 0x59, 0x98, 0xf3, 0x17, 0x20, - 0xdb, 0x89, 0x53, 0xa0, 0x54, 0xe5, 0x47, 0x37, 0xbf, 0x7b, 0xf7, 0x79, 0xef, 0x7b, 0xef, 0x3d, - 0x3f, 0xf0, 0x88, 0xf6, 0x31, 0x44, 0x61, 0x18, 0x50, 0x8c, 0x24, 0xe5, 0x4c, 0x40, 0xca, 0x24, - 0x89, 0xf0, 0x00, 0x51, 0xd6, 0x43, 0x18, 0xf3, 0x11, 0x93, 0x02, 0x62, 0xce, 0x64, 0xc4, 0x83, - 0x80, 0x44, 0x30, 0x6e, 0x40, 0xb9, 0xef, 0x84, 0x11, 0x97, 0x5c, 0x6b, 0xd2, 0x3e, 0x76, 0x4e, - 0xc3, 0xce, 0x19, 0xb0, 0xb3, 0x80, 0x9d, 0xb8, 0x61, 0xd4, 0x7c, 0xee, 0xf3, 0x0c, 0x87, 0xe9, - 0x57, 0x1e, 0xc9, 0xd8, 0xbc, 0x90, 0x8c, 0xb8, 0x01, 0x43, 0x84, 0x5f, 0x11, 0x99, 0x53, 0xf6, - 0x27, 0x15, 0xdc, 0xeb, 0x08, 0xdf, 0x25, 0x3e, 0x15, 0x92, 0x44, 0xed, 0x02, 0x79, 0x9c, 0x13, - 0x5a, 0x0d, 0x5c, 0xe1, 0x6f, 0x18, 0x89, 0x74, 0x75, 0x5d, 0xdd, 0xa8, 0xba, 0xb9, 0xa1, 0xed, - 0x80, 0x6b, 0x98, 0x33, 0x46, 0x70, 0x9a, 0xa9, 0x47, 0x3d, 0xbd, 0x94, 0x7a, 0x5b, 0xfa, 0x34, - 0xb1, 0x6a, 0x07, 0x68, 0x18, 0x6c, 0xdb, 0x3f, 0xb8, 0x6d, 0xf7, 0xea, 0xc2, 0x6e, 0x7b, 0x9a, - 0x0e, 0x96, 0x63, 0x12, 0x09, 0xca, 0x99, 0xbe, 0x94, 0x85, 0x9d, 0x9b, 0xdb, 0x2b, 0xef, 0x0e, - 0x2d, 0xe5, 0xdb, 0xa1, 0xa5, 0xd8, 0xef, 0x55, 0x70, 0xff, 0x3c, 0x65, 0x2e, 0x11, 0x21, 0x67, - 0x82, 0x68, 0x9b, 0x00, 0xe0, 0x01, 0x62, 0x8c, 0x04, 0xa9, 0x90, 0x4c, 0x66, 0xeb, 0xd6, 0x34, - 0xb1, 0xd6, 0x66, 0x42, 0x0a, 0x9f, 0xed, 0x56, 0x67, 0x46, 0xdb, 0xd3, 0x1e, 0x80, 0xe5, 0x90, - 0x47, 0x72, 0xa1, 0x5d, 0x9b, 0x26, 0xd6, 0xf5, 0x1c, 0x99, 0x39, 0x6c, 0xb7, 0x92, 0x7e, 0xb5, - 0x3d, 0xfb, 0x73, 0x09, 0x54, 0x3b, 0xc2, 0x7f, 0x46, 0x98, 0xb7, 0xb7, 0x7f, 0x39, 0x25, 0x79, - 0xab, 0x82, 0xd5, 0xbc, 0x33, 0x3d, 0x0f, 0x49, 0x94, 0xd5, 0x65, 0xb5, 0xb9, 0xeb, 0x5c, 0x68, - 0x3e, 0xe2, 0x86, 0xf3, 0x4b, 0x7d, 0xba, 0x59, 0xb0, 0x5d, 0x24, 0x51, 0xcb, 0x38, 0x4a, 0x2c, - 0x65, 0x9a, 0x58, 0xda, 0xec, 0x79, 0x8b, 0x34, 0xb6, 0x0b, 0xc2, 0xe2, 0x9e, 0xf6, 0x14, 0xdc, - 0x8c, 0x48, 0x80, 0x24, 0x8d, 0x49, 0x4f, 0xd2, 0x21, 0xe1, 0x23, 0xa9, 0x97, 0xd7, 0xd5, 0x8d, - 0x72, 0xeb, 0xee, 0x34, 0xb1, 0x6e, 0xe7, 0xf4, 0xcf, 0x37, 0x6c, 0xf7, 0xc6, 0xfc, 0x68, 0x2f, - 0x3f, 0x39, 0xd5, 0x44, 0x08, 0xd6, 0x8a, 0xba, 0x15, 0x0d, 0x33, 0xc0, 0x8a, 0x20, 0xaf, 0x47, - 0x84, 0x61, 0x92, 0x95, 0xb0, 0xec, 0x16, 0x76, 0xf3, 0xa4, 0x04, 0x96, 0x3a, 0xc2, 0xd7, 0xbe, - 0xa8, 0xe0, 0xce, 0xef, 0x87, 0xb2, 0xeb, 0xfc, 0xf9, 0x6f, 0xe3, 0x9c, 0x37, 0x4c, 0xc6, 0xf3, - 0xff, 0x1d, 0xb1, 0x78, 0xed, 0x07, 0x15, 0x54, 0x66, 0x83, 0xb3, 0xf3, 0x97, 0x49, 0x72, 0xdc, - 0x78, 0xf2, 0x4f, 0xf8, 0x5c, 0x50, 0xeb, 0xe5, 0xd1, 0xd8, 0x54, 0x8f, 0xc7, 0xa6, 0x7a, 0x32, - 0x36, 0xd5, 0x8f, 0x13, 0x53, 0x39, 0x9e, 0x98, 0xca, 0xd7, 0x89, 0xa9, 0xbc, 0xe8, 0xfa, 0x54, - 0x0e, 0x46, 0x7d, 0x07, 0xf3, 0x21, 0xc4, 0x5c, 0x0c, 0xb9, 0x80, 0xb4, 0x8f, 0xeb, 0x3e, 0x87, - 0xf1, 0x16, 0x1c, 0x72, 0x6f, 0x14, 0x10, 0x91, 0xae, 0x18, 0x01, 0x9b, 0x5b, 0xf5, 0x45, 0xea, - 0xfa, 0x59, 0x4b, 0x4e, 0x1e, 0x84, 0x44, 0xf4, 0x2b, 0xd9, 0x96, 0x79, 0xf8, 0x3d, 0x00, 0x00, - 0xff, 0xff, 0xf0, 0x81, 0x7c, 0xb2, 0x24, 0x05, 0x00, 0x00, + // 613 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcd, 0x6e, 0xd4, 0x3c, + 0x14, 0x4d, 0xda, 0x7e, 0xfd, 0x71, 0x3f, 0x0a, 0x8d, 0x8a, 0x08, 0x01, 0x25, 0x25, 0x62, 0x51, + 0x09, 0xd5, 0xd6, 0x0c, 0x15, 0x95, 0x8a, 0xba, 0x60, 0x54, 0x90, 0x66, 0x51, 0x51, 0x85, 0x2e, + 0x10, 0x9b, 0x91, 0xc7, 0xb1, 0x52, 0x43, 0xc6, 0x0e, 0xb6, 0x27, 0xb4, 0x4b, 0x76, 0xb0, 0x41, + 0x3c, 0x42, 0x9f, 0x82, 0x57, 0xa0, 0x3b, 0xba, 0x64, 0x15, 0x55, 0xed, 0x86, 0xf5, 0x3c, 0x01, + 0xca, 0xcf, 0x64, 0x0a, 0x94, 0xaa, 0xfc, 0xed, 0x7c, 0x73, 0xef, 0x39, 0xbe, 0xe7, 0xdc, 0x1b, + 0x83, 0xfb, 0xac, 0x4b, 0x10, 0x4e, 0x92, 0x98, 0x11, 0xac, 0x99, 0xe0, 0x0a, 0x31, 0xae, 0xa9, + 0x24, 0x3b, 0x98, 0xf1, 0x0e, 0x26, 0x44, 0xf4, 0xb9, 0x56, 0x88, 0x08, 0xae, 0xa5, 0x88, 0x63, + 0x2a, 0x51, 0xda, 0x40, 0x7a, 0x17, 0x26, 0x52, 0x68, 0x61, 0x35, 0x59, 0x97, 0xc0, 0xd3, 0x60, + 0x78, 0x06, 0x18, 0x8e, 0xc0, 0x30, 0x6d, 0x38, 0x0b, 0x91, 0x88, 0x44, 0x01, 0x47, 0xf9, 0xa9, + 0x64, 0x72, 0x56, 0x2e, 0xd4, 0x46, 0xda, 0x40, 0x09, 0x26, 0x2f, 0xa8, 0xae, 0x50, 0xb7, 0x72, + 0x14, 0x11, 0x92, 0x22, 0xb2, 0x83, 0x39, 0xa7, 0x71, 0x5e, 0x51, 0x1d, 0xcb, 0x12, 0xff, 0x93, + 0x09, 0x6e, 0x6e, 0xaa, 0x28, 0xa0, 0x11, 0x53, 0x9a, 0xca, 0x76, 0xcd, 0xfa, 0xa0, 0x24, 0xb5, + 0x16, 0xc0, 0x7f, 0xe2, 0x15, 0xa7, 0xd2, 0x36, 0x17, 0xcd, 0xa5, 0x99, 0xa0, 0x0c, 0xac, 0x75, + 0x70, 0x89, 0x08, 0xce, 0x29, 0xc9, 0x9b, 0xe9, 0xb0, 0xd0, 0x1e, 0xcb, 0xb3, 0x2d, 0x7b, 0x90, + 0x79, 0x0b, 0x7b, 0xb8, 0x17, 0xaf, 0xf9, 0xdf, 0xa4, 0xfd, 0xe0, 0xff, 0x51, 0xdc, 0x0e, 0x2d, + 0x1b, 0x4c, 0xa5, 0x54, 0x2a, 0x26, 0xb8, 0x3d, 0x5e, 0xd0, 0x0e, 0x43, 0xeb, 0x1e, 0x98, 0x16, + 0x32, 0xa4, 0x92, 0xf1, 0xc8, 0x9e, 0x58, 0x34, 0x97, 0xe6, 0x9a, 0x0e, 0xcc, 0x5d, 0xcc, 0x55, + 0xc0, 0x61, 0xeb, 0x69, 0x03, 0x3e, 0xce, 0x8b, 0x82, 0xba, 0x76, 0x6d, 0xfa, 0xcd, 0xbe, 0x67, + 0x7c, 0xd9, 0xf7, 0x0c, 0xff, 0xad, 0x09, 0x6e, 0x9f, 0xa7, 0x28, 0xa0, 0x2a, 0x11, 0x5c, 0x51, + 0x6b, 0x05, 0x80, 0x8a, 0x30, 0x17, 0x50, 0xc8, 0x6b, 0x5d, 0x1d, 0x64, 0xde, 0x7c, 0x25, 0xa0, + 0xce, 0xf9, 0xc1, 0x4c, 0x15, 0xb4, 0x43, 0xeb, 0x0e, 0x98, 0x4a, 0x84, 0xd4, 0x23, 0xcd, 0xd6, + 0x20, 0xf3, 0xe6, 0x4a, 0x48, 0x95, 0xf0, 0x83, 0xc9, 0xfc, 0xd4, 0x0e, 0xfd, 0x0f, 0x63, 0x60, + 0x66, 0x53, 0x45, 0x4f, 0x28, 0x0f, 0xb7, 0x77, 0xff, 0x8d, 0x95, 0xaf, 0x4d, 0x30, 0x5b, 0x0e, + 0xbd, 0x13, 0x62, 0x8d, 0x0b, 0x3f, 0x67, 0x9b, 0x1b, 0xf0, 0x42, 0xab, 0x97, 0x36, 0xe0, 0x0f, + 0xfe, 0x6c, 0x15, 0x64, 0x1b, 0x58, 0xe3, 0x96, 0x73, 0x90, 0x79, 0xc6, 0x20, 0xf3, 0xac, 0x4a, + 0xde, 0xe8, 0x1a, 0x3f, 0x00, 0x49, 0x5d, 0x67, 0x3d, 0x02, 0x57, 0x24, 0x8d, 0xb1, 0x66, 0x29, + 0xed, 0x68, 0xd6, 0xa3, 0xa2, 0xaf, 0x8b, 0xe1, 0x4d, 0xb4, 0x6e, 0x0c, 0x32, 0xef, 0x5a, 0x89, + 0xfe, 0xbe, 0xc2, 0x0f, 0x2e, 0x0f, 0x3f, 0x6d, 0x97, 0x5f, 0x4e, 0x0d, 0x11, 0x81, 0xf9, 0xda, + 0xb7, 0x7a, 0x60, 0x0e, 0x98, 0x56, 0xf4, 0x65, 0x9f, 0x72, 0x42, 0x0b, 0x0b, 0x27, 0x82, 0x3a, + 0x6e, 0x1e, 0x8d, 0x81, 0xf1, 0x4d, 0x15, 0x59, 0x1f, 0x4d, 0x70, 0xfd, 0xe7, 0xcb, 0xbc, 0x05, + 0x7f, 0xfd, 0x8f, 0x84, 0xe7, 0x2d, 0x93, 0xf3, 0xf4, 0x6f, 0x33, 0xd6, 0x6a, 0xdf, 0x99, 0x60, + 0xb2, 0x5a, 0x9c, 0xf5, 0xdf, 0xbc, 0xa4, 0x84, 0x3b, 0x0f, 0xff, 0x08, 0x3e, 0x6c, 0xa8, 0xf5, + 0xfc, 0xe0, 0xd8, 0x35, 0x0f, 0x8f, 0x5d, 0xf3, 0xe8, 0xd8, 0x35, 0xdf, 0x9f, 0xb8, 0xc6, 0xe1, + 0x89, 0x6b, 0x7c, 0x3e, 0x71, 0x8d, 0x67, 0x5b, 0x11, 0xd3, 0x3b, 0xfd, 0x2e, 0x24, 0xa2, 0x87, + 0x88, 0x50, 0x3d, 0xa1, 0x10, 0xeb, 0x92, 0xe5, 0x48, 0xa0, 0x74, 0x15, 0xf5, 0x44, 0xd8, 0x8f, + 0xa9, 0xca, 0x5f, 0x2f, 0x85, 0x9a, 0xab, 0xcb, 0xa3, 0xab, 0x97, 0xcf, 0x7a, 0x3f, 0xf5, 0x5e, + 0x42, 0x55, 0x77, 0xb2, 0x78, 0x9d, 0xee, 0x7e, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x86, 0xb9, + 0xeb, 0x7f, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -401,6 +406,11 @@ func (m *MsgRegisterInterchainAccount) MarshalToSizedBuffer(dAtA []byte) (int, e _ = i var l int _ = l + if m.Ordering != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Ordering)) + i-- + dAtA[i] = 0x20 + } if len(m.Version) > 0 { i -= len(m.Version) copy(dAtA[i:], m.Version) @@ -571,6 +581,9 @@ func (m *MsgRegisterInterchainAccount) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + if m.Ordering != 0 { + n += 1 + sovTx(uint64(m.Ordering)) + } return n } @@ -756,6 +769,25 @@ func (m *MsgRegisterInterchainAccount) Unmarshal(dAtA []byte) error { } m.Version = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Ordering", wireType) + } + m.Ordering = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Ordering |= types.Order(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/modules/apps/27-interchain-accounts/host/ibc_module_test.go b/modules/apps/27-interchain-accounts/host/ibc_module_test.go index c0c8c0b3561..346144ead6e 100644 --- a/modules/apps/27-interchain-accounts/host/ibc_module_test.go +++ b/modules/apps/27-interchain-accounts/host/ibc_module_test.go @@ -140,7 +140,12 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenTry() { expPass bool }{ { - "success", func() {}, true, + "success w/ ORDERED channel", func() {}, true, + }, + { + "success w/ UNORDERED channel", func() { + channel.Ordering = channeltypes.UNORDERED + }, true, }, { "account address generation is block dependent", func() { @@ -169,11 +174,6 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenTry() { } }, true, }, - { - "ICA callback fails - invalid channel order", func() { - channel.Ordering = channeltypes.UNORDERED - }, false, - }, } for _, tc := range testCases { diff --git a/modules/apps/27-interchain-accounts/host/keeper/handshake.go b/modules/apps/27-interchain-accounts/host/keeper/handshake.go index 9f31c787ff3..7e567ce449e 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/handshake.go +++ b/modules/apps/27-interchain-accounts/host/keeper/handshake.go @@ -3,6 +3,7 @@ package keeper import ( "fmt" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" @@ -26,10 +27,6 @@ func (k Keeper) OnChanOpenTry( counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { - if order != channeltypes.ORDERED { - return "", sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s", channeltypes.ORDERED, order) - } - if portID != icatypes.HostPortID { return "", sdkerrors.Wrapf(icatypes.ErrInvalidHostPort, "expected %s, got %s", icatypes.HostPortID, portID) } @@ -50,18 +47,13 @@ func (k Keeper) OnChanOpenTry( panic(fmt.Sprintf("active channel mapping set for %s but channel does not exist in channel store", activeChannelID)) } - if channel.State == channeltypes.OPEN { - return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s is already OPEN", activeChannelID, portID) - } - - 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 channel.State != channeltypes.CLOSED { + return "", errorsmod.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s must be %s", activeChannelID, portID, channeltypes.CLOSED) } - if !icatypes.IsPreviousMetadataEqual(appVersion, metadata) { - return "", sdkerrors.Wrap(icatypes.ErrInvalidVersion, "previous active channel metadata does not match provided version") - } + // if a channel is being reopened, we allow the controller to propose new fields + // which are not exactly the same as the previous. The provided address will + // be overwritten with the correct one before the metadata is returned. } // On the host chain the capability may only be claimed during the OnChanOpenTry diff --git a/modules/apps/27-interchain-accounts/host/keeper/handshake_test.go b/modules/apps/27-interchain-accounts/host/keeper/handshake_test.go index 8158008c1e9..e26e9530092 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/handshake_test.go +++ b/modules/apps/27-interchain-accounts/host/keeper/handshake_test.go @@ -88,6 +88,25 @@ func (suite *KeeperTestSuite) TestOnChanOpenTry() { suite.Require().False(found) }, true, }, + { + "success - previous metadata is different", + func() { + // set the active channelID in state + suite.chainB.GetSimApp().ICAHostKeeper.SetActiveChannelID(suite.chainB.GetContext(), path.EndpointB.ConnectionID, path.EndpointA.ChannelConfig.PortID, path.EndpointB.ChannelID) + + // set the previous encoding to be proto3json. + // the new encoding is set to be protobuf in the test below. + metadata.Encoding = icatypes.EncodingProto3JSON + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + channel.State = channeltypes.CLOSED + channel.Version = string(versionBytes) + + path.EndpointB.SetChannel(*channel) + }, true, + }, { "reopening account fails - no existing account", func() { @@ -136,34 +155,6 @@ func (suite *KeeperTestSuite) TestOnChanOpenTry() { }, false, }, - { - "invalid metadata - previous metadata is different", - func() { - // create a new channel and set it in state - ch := channeltypes.NewChannel(channeltypes.CLOSED, channeltypes.ORDERED, channeltypes.NewCounterparty(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID), []string{path.EndpointA.ConnectionID}, TestVersion) - suite.chainB.GetSimApp().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, ch) - - // set the active channelID in state - suite.chainB.GetSimApp().ICAHostKeeper.SetActiveChannelID(suite.chainB.GetContext(), path.EndpointB.ConnectionID, path.EndpointA.ChannelConfig.PortID, path.EndpointB.ChannelID) - - // attempt to downgrade version by reinitializing channel with version 1, but setting channel to version 2 - metadata.Version = "ics27-2" - - versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) - suite.Require().NoError(err) - - channel.Version = string(versionBytes) - - path.EndpointB.SetChannel(*channel) - }, false, - }, - { - "invalid order - UNORDERED", - func() { - channel.Ordering = channeltypes.UNORDERED - }, - false, - }, { "invalid port ID", func() { @@ -256,7 +247,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenTry() { false, }, { - "active channel already set", + "active channel already set (OPEN state)", func() { // create a new channel and set it in state ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, channeltypes.NewCounterparty(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID), []string{path.EndpointA.ConnectionID}, ibctesting.DefaultChannelVersion) diff --git a/modules/core/03-connection/types/version.go b/modules/core/03-connection/types/version.go index a9a9f3df699..827ced76ba9 100644 --- a/modules/core/03-connection/types/version.go +++ b/modules/core/03-connection/types/version.go @@ -13,11 +13,15 @@ var ( // in connection version negotiation. The current version supports only // ORDERED and UNORDERED channels and requires at least one channel type // to be agreed upon. - DefaultIBCVersion = NewVersion(DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED", "ORDER_UNORDERED"}) + DefaultIBCVersion = NewVersion(DefaultIBCVersionIdentifier, SupportedOrderings) // DefaultIBCVersionIdentifier is the IBC v1.0.0 protocol version identifier DefaultIBCVersionIdentifier = "1" + // SupportedOrderings is the list of orderings supported by IBC. The current + // version supports only ORDERED and UNORDERED channels. + SupportedOrderings = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} + // AllowNilFeatureSet is a helper map to indicate if a specified version // identifier is allowed to have a nil feature set. Any versions supported, // but not included in the map default to not supporting nil feature sets. diff --git a/proto/ibc/applications/interchain_accounts/controller/v1/tx.proto b/proto/ibc/applications/interchain_accounts/controller/v1/tx.proto index 284ffe70576..874ab457b65 100644 --- a/proto/ibc/applications/interchain_accounts/controller/v1/tx.proto +++ b/proto/ibc/applications/interchain_accounts/controller/v1/tx.proto @@ -6,6 +6,7 @@ option go_package = "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-acco import "gogoproto/gogo.proto"; import "ibc/applications/interchain_accounts/v1/packet.proto"; +import "ibc/core/channel/v1/channel.proto"; // Msg defines the 27-interchain-accounts/controller Msg service. service Msg { @@ -20,9 +21,10 @@ message MsgRegisterInterchainAccount { option (gogoproto.equal) = false; option (gogoproto.goproto_getters) = false; - string owner = 1; - string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - string version = 3; + string owner = 1; + string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""]; + string version = 3; + ibc.core.channel.v1.Order ordering = 4; } // MsgRegisterInterchainAccountResponse defines the response for Msg/RegisterAccount