diff --git a/modules/apps/27-interchain-accounts/controller/ibc_module_test.go b/modules/apps/27-interchain-accounts/controller/ibc_module_test.go index ca1b0db6b06..226352fcc72 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_module_test.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_module_test.go @@ -35,6 +35,8 @@ var ( Version: icatypes.Version, ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxTypes: icatypes.TxTypeSDKMultiMsg, })) ) diff --git a/modules/apps/27-interchain-accounts/controller/keeper/account.go b/modules/apps/27-interchain-accounts/controller/keeper/account.go index aacbe751c6b..ca920a7930d 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/account.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/account.go @@ -36,7 +36,15 @@ func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner s } // NOTE: An empty string is provided for accAddress, to be fulfilled upon OnChanOpenTry handshake step - metadata := icatypes.NewMetadata(icatypes.Version, connectionID, connectionEnd.GetCounterparty().GetConnectionID(), "") + metadata := icatypes.NewMetadata( + icatypes.Version, + connectionID, + connectionEnd.GetCounterparty().GetConnectionID(), + "", + icatypes.EncodingProtobuf, + icatypes.TxTypeSDKMultiMsg, + ) + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) if err != nil { return err 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 b08a6913aaf..2f76209f6c9 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/handshake_test.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/handshake_test.go @@ -60,6 +60,32 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { }, false, }, + { + "unsupported encoding format", + func() { + metadata.Encoding = "invalid-encoding-format" + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + channel.Version = string(versionBytes) + path.EndpointA.SetChannel(*channel) + }, + false, + }, + { + "unsupported transaction type", + func() { + metadata.TxTypes = "invalid-tx-types" + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + channel.Version = string(versionBytes) + path.EndpointA.SetChannel(*channel) + }, + false, + }, { "connection not found", func() { @@ -144,7 +170,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenInit() { path.EndpointA.ChannelConfig.PortID = portID // default values - metadata = icatypes.NewMetadata(icatypes.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, "") + metadata = icatypes.NewMetadata(icatypes.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, "", icatypes.EncodingProtobuf, icatypes.TxTypeSDKMultiMsg) versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) suite.Require().NoError(err) @@ -211,6 +237,30 @@ func (suite *KeeperTestSuite) TestOnChanOpenAck() { }, false, }, + { + "unsupported encoding format", + func() { + metadata.Encoding = "invalid-encoding-format" + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + path.EndpointA.Counterparty.ChannelConfig.Version = string(versionBytes) + }, + false, + }, + { + "unsupported transaction type", + func() { + metadata.TxTypes = "invalid-tx-types" + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + path.EndpointA.Counterparty.ChannelConfig.Version = string(versionBytes) + }, + false, + }, { "invalid account address", func() { @@ -275,7 +325,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenAck() { err = path.EndpointB.ChanOpenTry() suite.Require().NoError(err) - metadata = icatypes.NewMetadata(icatypes.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, TestAccAddress.String()) + metadata = icatypes.NewMetadata(icatypes.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, TestAccAddress.String(), icatypes.EncodingProtobuf, icatypes.TxTypeSDKMultiMsg) versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) suite.Require().NoError(err) diff --git a/modules/apps/27-interchain-accounts/controller/keeper/keeper_test.go b/modules/apps/27-interchain-accounts/controller/keeper/keeper_test.go index eff4ce5fa96..07e887a289c 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/keeper_test.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/keeper_test.go @@ -30,6 +30,8 @@ var ( Version: icatypes.Version, ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxTypes: icatypes.TxTypeSDKMultiMsg, })) ) 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 ddf90c6d46c..dc0acf77172 100644 --- a/modules/apps/27-interchain-accounts/host/ibc_module_test.go +++ b/modules/apps/27-interchain-accounts/host/ibc_module_test.go @@ -37,6 +37,8 @@ var ( Version: icatypes.Version, ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxTypes: icatypes.TxTypeSDKMultiMsg, })) ) 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 6f3dc0d25e1..e847a745eae 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/handshake_test.go +++ b/modules/apps/27-interchain-accounts/host/keeper/handshake_test.go @@ -66,6 +66,30 @@ func (suite *KeeperTestSuite) TestOnChanOpenTry() { }, false, }, + { + "unsupported encoding format", + func() { + metadata.Encoding = "invalid-encoding-format" + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + path.EndpointA.ChannelConfig.Version = string(versionBytes) + }, + false, + }, + { + "unsupported transaction type", + func() { + metadata.TxTypes = "invalid-tx-types" + + versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) + suite.Require().NoError(err) + + path.EndpointA.ChannelConfig.Version = string(versionBytes) + }, + false, + }, { "invalid controller connection ID", func() { @@ -141,7 +165,7 @@ func (suite *KeeperTestSuite) TestOnChanOpenTry() { path.EndpointB.ChannelID = channeltypes.FormatChannelIdentifier(channelSequence) // default values - metadata = icatypes.NewMetadata(icatypes.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, "") + metadata = icatypes.NewMetadata(icatypes.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, "", icatypes.EncodingProtobuf, icatypes.TxTypeSDKMultiMsg) versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) suite.Require().NoError(err) diff --git a/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go b/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go index 2b38f6b5e84..47e488c5b92 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go +++ b/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go @@ -30,6 +30,8 @@ var ( Version: icatypes.Version, ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxTypes: icatypes.TxTypeSDKMultiMsg, })) ) diff --git a/modules/apps/27-interchain-accounts/types/metadata.go b/modules/apps/27-interchain-accounts/types/metadata.go index acc1dcb940b..d0dc50c7258 100644 --- a/modules/apps/27-interchain-accounts/types/metadata.go +++ b/modules/apps/27-interchain-accounts/types/metadata.go @@ -7,18 +7,36 @@ import ( connectiontypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" ) +const ( + // EncodingProtobuf defines the protocol buffers proto3 encoding format + EncodingProtobuf = "proto3" + + // TxTypeSDKMultiMsg defines the multi message transaction type supported by the Cosmos SDK + TxTypeSDKMultiMsg = "sdk_multi_msg" +) + // NewMetadata creates and returns a new ICS27 Metadata instance -func NewMetadata(version, controllerConnectionID, hostConnectionID, accAddress string) Metadata { +func NewMetadata(version, controllerConnectionID, hostConnectionID, accAddress, encoding, txTypes string) Metadata { return Metadata{ Version: version, ControllerConnectionId: controllerConnectionID, HostConnectionId: hostConnectionID, Address: accAddress, + Encoding: encoding, + TxTypes: txTypes, } } // ValidateControllerMetadata performs validation of the provided ICS27 controller metadata parameters func ValidateControllerMetadata(ctx sdk.Context, channelKeeper ChannelKeeper, connectionHops []string, metadata Metadata) error { + if !isSupportedEncoding(metadata.Encoding) { + return sdkerrors.Wrapf(ErrInvalidCodec, "unsupported encoding format %s", metadata.Encoding) + } + + if !isSupportedTxTypes(metadata.TxTypes) { + return sdkerrors.Wrapf(ErrUnknownDataType, "unsupported transaction type %s", metadata.TxTypes) + } + connection, err := channelKeeper.GetConnection(ctx, connectionHops[0]) if err != nil { return err @@ -43,6 +61,14 @@ func ValidateControllerMetadata(ctx sdk.Context, channelKeeper ChannelKeeper, co // ValidateHostMetadata performs validation of the provided ICS27 host metadata parameters func ValidateHostMetadata(ctx sdk.Context, channelKeeper ChannelKeeper, connectionHops []string, metadata Metadata) error { + if !isSupportedEncoding(metadata.Encoding) { + return sdkerrors.Wrapf(ErrInvalidCodec, "unsupported encoding format %s", metadata.Encoding) + } + + if !isSupportedTxTypes(metadata.TxTypes) { + return sdkerrors.Wrapf(ErrUnknownDataType, "unsupported transaction type %s", metadata.TxTypes) + } + connection, err := channelKeeper.GetConnection(ctx, connectionHops[0]) if err != nil { return err @@ -65,6 +91,38 @@ func ValidateHostMetadata(ctx sdk.Context, channelKeeper ChannelKeeper, connecti return nil } +// isSupportedEncoding returns true if the provided encoding is supported, otherwise false +func isSupportedEncoding(encoding string) bool { + for _, enc := range getSupportedEncoding() { + if enc == encoding { + return true + } + } + + return false +} + +// getSupportedEncoding returns a string slice of supported encoding formats +func getSupportedEncoding() []string { + return []string{EncodingProtobuf} +} + +// isSupportedTxTypes returns true if the provided transaction types are supported, otherwise false +func isSupportedTxTypes(txTypes string) bool { + for _, txType := range getSupportedTxTypes() { + if txType == txTypes { + return true + } + } + + return false +} + +// getSupportedTxTypes returns a string slice of supported transaction types +func getSupportedTxTypes() []string { + return []string{TxTypeSDKMultiMsg} +} + // validateConnectionParams compares the given the controller and host connection IDs to those set in the provided ICS27 Metadata func validateConnectionParams(metadata Metadata, controllerConnectionID, hostConnectionID string) error { if metadata.ControllerConnectionId != controllerConnectionID { diff --git a/modules/apps/27-interchain-accounts/types/metadata_test.go b/modules/apps/27-interchain-accounts/types/metadata_test.go index 2e569549647..fa499c0ad77 100644 --- a/modules/apps/27-interchain-accounts/types/metadata_test.go +++ b/modules/apps/27-interchain-accounts/types/metadata_test.go @@ -27,10 +27,40 @@ func (suite *TypesTestSuite) TestValidateControllerMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, Address: "", + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, true, }, + { + "unsupported encoding format", + func() { + metadata = types.Metadata{ + Version: types.Version, + ControllerConnectionId: ibctesting.FirstConnectionID, + HostConnectionId: ibctesting.FirstConnectionID, + Address: TestOwnerAddress, + Encoding: "invalid-encoding-format", + TxTypes: types.TxTypeSDKMultiMsg, + } + }, + false, + }, + { + "unsupported transaction type", + func() { + metadata = types.Metadata{ + Version: types.Version, + ControllerConnectionId: ibctesting.FirstConnectionID, + HostConnectionId: ibctesting.FirstConnectionID, + Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: "invalid-tx-type", + } + }, + false, + }, { "invalid controller connection", func() { @@ -39,6 +69,8 @@ func (suite *TypesTestSuite) TestValidateControllerMetadata() { ControllerConnectionId: "connection-10", HostConnectionId: ibctesting.FirstConnectionID, Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -51,6 +83,8 @@ func (suite *TypesTestSuite) TestValidateControllerMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: "connection-10", Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -63,6 +97,8 @@ func (suite *TypesTestSuite) TestValidateControllerMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, Address: " ", + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -75,6 +111,8 @@ func (suite *TypesTestSuite) TestValidateControllerMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -89,7 +127,7 @@ func (suite *TypesTestSuite) TestValidateControllerMetadata() { path := ibctesting.NewPath(suite.chainA, suite.chainB) suite.coordinator.SetupConnections(path) - metadata = types.NewMetadata(types.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, TestOwnerAddress) + metadata = types.NewMetadata(types.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, TestOwnerAddress, types.EncodingProtobuf, types.TxTypeSDKMultiMsg) tc.malleate() // malleate mutates test data @@ -131,10 +169,40 @@ func (suite *TypesTestSuite) TestValidateHostMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, Address: "", + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, true, }, + { + "unsupported encoding format", + func() { + metadata = types.Metadata{ + Version: types.Version, + ControllerConnectionId: ibctesting.FirstConnectionID, + HostConnectionId: ibctesting.FirstConnectionID, + Address: TestOwnerAddress, + Encoding: "invalid-encoding-format", + TxTypes: types.TxTypeSDKMultiMsg, + } + }, + false, + }, + { + "unsupported transaction type", + func() { + metadata = types.Metadata{ + Version: types.Version, + ControllerConnectionId: ibctesting.FirstConnectionID, + HostConnectionId: ibctesting.FirstConnectionID, + Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: "invalid-tx-type", + } + }, + false, + }, { "invalid controller connection", func() { @@ -143,6 +211,8 @@ func (suite *TypesTestSuite) TestValidateHostMetadata() { ControllerConnectionId: "connection-10", HostConnectionId: ibctesting.FirstConnectionID, Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -155,6 +225,8 @@ func (suite *TypesTestSuite) TestValidateHostMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: "connection-10", Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -167,6 +239,8 @@ func (suite *TypesTestSuite) TestValidateHostMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, Address: " ", + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -179,6 +253,8 @@ func (suite *TypesTestSuite) TestValidateHostMetadata() { ControllerConnectionId: ibctesting.FirstConnectionID, HostConnectionId: ibctesting.FirstConnectionID, Address: TestOwnerAddress, + Encoding: types.EncodingProtobuf, + TxTypes: types.TxTypeSDKMultiMsg, } }, false, @@ -193,7 +269,7 @@ func (suite *TypesTestSuite) TestValidateHostMetadata() { path := ibctesting.NewPath(suite.chainA, suite.chainB) suite.coordinator.SetupConnections(path) - metadata = types.NewMetadata(types.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, TestOwnerAddress) + metadata = types.NewMetadata(types.Version, ibctesting.FirstConnectionID, ibctesting.FirstConnectionID, TestOwnerAddress, types.EncodingProtobuf, types.TxTypeSDKMultiMsg) tc.malleate() // malleate mutates test data