From 432ba30bed4f493bba536d613f891b8d2c04b5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Fri, 2 Oct 2020 00:28:15 +0200 Subject: [PATCH] Flexible Connection Handshake Selection (#7427) * update connopeninit Update ConnOpenInit to reflect changes in https://github.com/cosmos/ics/pull/482. An additional version field is added to the connection handshake and connection open init message to take in an optional field. If this field is empty, then the default versions are used for connection handshake version negotiation. * add version compatibility check in open init * implement partial changes to conn open try * partial implementation of conn open ack changes * fix tests * add handshake tests * make proto * fix conflicts * fix lint * fix lint * increase code cov Co-authored-by: Federico Kunze --- proto/ibc/core/connection/v1/connection.proto | 41 +- x/ibc/03-connection/client/cli/tx.go | 63 ++- x/ibc/03-connection/handler.go | 6 +- x/ibc/03-connection/keeper/handshake.go | 72 +++- x/ibc/03-connection/keeper/handshake_test.go | 184 ++++++++- x/ibc/03-connection/types/connection.go | 6 +- x/ibc/03-connection/types/connection.pb.go | 364 ++++++++++++------ x/ibc/03-connection/types/errors.go | 1 + x/ibc/03-connection/types/msgs.go | 48 ++- x/ibc/03-connection/types/msgs_test.go | 148 +++---- x/ibc/03-connection/types/version.go | 8 +- x/ibc/03-connection/types/version_test.go | 17 +- x/ibc/testing/chain.go | 11 +- 13 files changed, 657 insertions(+), 312 deletions(-) diff --git a/proto/ibc/core/connection/v1/connection.proto b/proto/ibc/core/connection/v1/connection.proto index 3750f87eeded..726ca65f76e5 100644 --- a/proto/ibc/core/connection/v1/connection.proto +++ b/proto/ibc/core/connection/v1/connection.proto @@ -17,7 +17,8 @@ message MsgConnectionOpenInit { string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""]; Counterparty counterparty = 3 [(gogoproto.nullable) = false]; - string signer = 4; + string version = 4; + string signer = 5; } // MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a @@ -28,21 +29,22 @@ message MsgConnectionOpenTry { string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""]; - Counterparty counterparty = 4 [(gogoproto.nullable) = false]; - repeated string counterparty_versions = 5 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""]; - ibc.core.client.v1.Height proof_height = 6 + string proved_id = 3 [(gogoproto.moretags) = "yaml:\"proved_id\""]; + google.protobuf.Any client_state = 4 [(gogoproto.moretags) = "yaml:\"client_state\""]; + Counterparty counterparty = 5 [(gogoproto.nullable) = false]; + repeated string counterparty_versions = 6 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""]; + ibc.core.client.v1.Height proof_height = 7 [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; // proof of the initialization the connection on Chain A: `UNITIALIZED -> // INIT` - bytes proof_init = 7 [(gogoproto.moretags) = "yaml:\"proof_init\""]; + bytes proof_init = 8 [(gogoproto.moretags) = "yaml:\"proof_init\""]; // proof of client state included in message - bytes proof_client = 8 [(gogoproto.moretags) = "yaml:\"proof_client\""]; + bytes proof_client = 9 [(gogoproto.moretags) = "yaml:\"proof_client\""]; // proof of client consensus state - bytes proof_consensus = 9 [(gogoproto.moretags) = "yaml:\"proof_consensus\""]; - ibc.core.client.v1.Height consensus_height = 10 + bytes proof_consensus = 10 [(gogoproto.moretags) = "yaml:\"proof_consensus\""]; + ibc.core.client.v1.Height consensus_height = 11 [(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false]; - string signer = 11; + string signer = 12; } // MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to @@ -51,21 +53,22 @@ message MsgConnectionOpenAck { option (gogoproto.equal) = false; option (gogoproto.goproto_getters) = false; - string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - string version = 2; - google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""]; - ibc.core.client.v1.Height proof_height = 4 + string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""]; + string counterparty_connection_id = 2 [(gogoproto.moretags) = "yaml:\"counterparty_connection_id\""]; + string version = 3; + google.protobuf.Any client_state = 4 [(gogoproto.moretags) = "yaml:\"client_state\""]; + ibc.core.client.v1.Height proof_height = 5 [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; // proof of the initialization the connection on Chain B: `UNITIALIZED -> // TRYOPEN` - bytes proof_try = 5 [(gogoproto.moretags) = "yaml:\"proof_try\""]; + bytes proof_try = 6 [(gogoproto.moretags) = "yaml:\"proof_try\""]; // proof of client state included in message - bytes proof_client = 6 [(gogoproto.moretags) = "yaml:\"proof_client\""]; + bytes proof_client = 7 [(gogoproto.moretags) = "yaml:\"proof_client\""]; // proof of client consensus state - bytes proof_consensus = 7 [(gogoproto.moretags) = "yaml:\"proof_consensus\""]; - ibc.core.client.v1.Height consensus_height = 8 + bytes proof_consensus = 8 [(gogoproto.moretags) = "yaml:\"proof_consensus\""]; + ibc.core.client.v1.Height consensus_height = 9 [(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false]; - string signer = 9; + string signer = 10; } // MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index dba20ac1a4d4..da08a9717d14 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -16,15 +16,23 @@ import ( host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) +const ( + flagVersionIdentifier = "version-identifier" + flagVersionFeatures = "version-features" + flagProvedID = "proved-id" +) + // NewConnectionOpenInitCmd defines the command to initialize a connection on // chain A with a given counterparty chain B func NewConnectionOpenInitCmd() *cobra.Command { cmd := &cobra.Command{ Use: "open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]", Short: "Initialize connection on chain A", - Long: "Initialize a connection on chain A with a given counterparty chain B", + Long: `Initialize a connection on chain A with a given counterparty chain B. + - 'version-identifier' flag can be a single pre-selected version identifier to be used in the handshake. + - 'version-features' flag can be a list of features separated by commas to accompany the version identifier.`, Example: fmt.Sprintf( - "%s tx %s %s open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]", + "%s tx %s %s open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] --version-identifier=\"1.0\" --version-features=\"ORDER_UNORDERED\"", version.AppName, host.ModuleName, types.SubModuleName, ), Args: cobra.ExactArgs(5), @@ -45,9 +53,27 @@ func NewConnectionOpenInitCmd() *cobra.Command { return err } + var encodedVersion string + versionIdentifier, _ := cmd.Flags().GetString(flagVersionIdentifier) + + if versionIdentifier != "" { + var features []string + + versionFeatures, _ := cmd.Flags().GetString(flagVersionFeatures) + if versionFeatures != "" { + features = strings.Split(versionFeatures, ",") + } + + version := types.NewVersion(versionIdentifier, features) + encodedVersion, err = version.Encode() + if err != nil { + return err + } + } + msg := types.NewMsgConnectionOpenInit( connectionID, clientID, counterpartyConnectionID, counterpartyClientID, - counterpartyPrefix, clientCtx.GetFromAddress(), + counterpartyPrefix, encodedVersion, clientCtx.GetFromAddress(), ) if err := msg.ValidateBasic(); err != nil { @@ -58,6 +84,10 @@ func NewConnectionOpenInitCmd() *cobra.Command { }, } + // NOTE: we should use empty default values since the user may not want to select a version + // at this step in the handshake. + cmd.Flags().String(flagVersionIdentifier, "", "version identifier to be used in the connection handshake version negotiation") + cmd.Flags().String(flagVersionFeatures, "", "version features list separated by commas without spaces. The features must function with the version identifier.") flags.AddTxFlagsToCmd(cmd) return cmd @@ -87,6 +117,7 @@ func NewConnectionOpenTryCmd() *cobra.Command { } connectionID := args[0] + provedID, _ := cmd.Flags().GetString(flagProvedID) clientID := args[1] counterpartyConnectionID := args[2] counterpartyClientID := args[3] @@ -129,7 +160,7 @@ func NewConnectionOpenTryCmd() *cobra.Command { } msg := types.NewMsgConnectionOpenTry( - connectionID, clientID, counterpartyConnectionID, counterpartyClientID, + connectionID, provedID, clientID, counterpartyConnectionID, counterpartyClientID, counterpartyClient, counterpartyPrefix, []string{counterpartyVersions}, proofInit, proofClient, proofConsensus, proofHeight, consensusHeight, clientCtx.GetFromAddress(), @@ -143,6 +174,7 @@ func NewConnectionOpenTryCmd() *cobra.Command { }, } + cmd.Flags().String(flagProvedID, "", "identifier set by the counterparty chain") flags.AddTxFlagsToCmd(cmd) return cmd @@ -152,16 +184,16 @@ func NewConnectionOpenTryCmd() *cobra.Command { // connection open attempt from chain B to chain A func NewConnectionOpenAckCmd() *cobra.Command { cmd := &cobra.Command{ - Use: `open-ack [connection-id] [path/to/client_state.json] [consensus-height] [proof-height] + Use: `open-ack [connection-id] [counterparty-connection-id] [path/to/client_state.json] [consensus-height] [proof-height] [path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]`, Short: "relay the acceptance of a connection open attempt", Long: "Relay the acceptance of a connection open attempt from chain B to chain A", Example: fmt.Sprintf( - `%s tx %s %s open-ack [connection-id] [path/to/client_state.json] [consensus-height] [proof-height] + `%s tx %s %s open-ack [connection-id] [counterparty-connection-id] [path/to/client_state.json] [consensus-height] [proof-height] [path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]`, version.AppName, host.ModuleName, types.SubModuleName, ), - Args: cobra.ExactArgs(8), + Args: cobra.ExactArgs(9), RunE: func(cmd *cobra.Command, args []string) error { clientCtx := client.GetClientContextFromCmd(cmd) clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags()) @@ -170,40 +202,41 @@ func NewConnectionOpenAckCmd() *cobra.Command { } connectionID := args[0] + counterpartyConnectionID := args[1] - counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[1]) + counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[2]) if err != nil { return err } - consensusHeight, err := clienttypes.ParseHeight(args[2]) + consensusHeight, err := clienttypes.ParseHeight(args[3]) if err != nil { return err } - proofHeight, err := clienttypes.ParseHeight(args[3]) + proofHeight, err := clienttypes.ParseHeight(args[4]) if err != nil { return err } - proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[4]) + proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[5]) if err != nil { return err } - proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[5]) + proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[6]) if err != nil { return err } - proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[6]) + proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[7]) if err != nil { return err } - version := args[7] + version := args[8] msg := types.NewMsgConnectionOpenAck( - connectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight, + connectionID, counterpartyConnectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight, consensusHeight, version, clientCtx.GetFromAddress(), ) diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index 4ce2932f1b92..f6a00e3be9d5 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -11,7 +11,7 @@ import ( // HandleMsgConnectionOpenInit defines the sdk.Handler for MsgConnectionOpenInit func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenInit) (*sdk.Result, error) { if err := k.ConnOpenInit( - ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, + ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version, ); err != nil { return nil, sdkerrors.Wrap(err, "connection handshake open init failed") } @@ -43,7 +43,7 @@ func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg *types.Msg } if err := k.ConnOpenTry( - ctx, msg.ConnectionId, msg.Counterparty, msg.ClientId, targetClient, + ctx, msg.ConnectionId, msg.ProvedId, msg.Counterparty, msg.ClientId, targetClient, msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus, msg.ProofHeight, msg.ConsensusHeight, ); err != nil { @@ -77,7 +77,7 @@ func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg *types.Msg } if err := k.ConnOpenAck( - ctx, msg.ConnectionId, targetClient, msg.Version, + ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId, msg.ProofTry, msg.ProofClient, msg.ProofConsensus, msg.ProofHeight, msg.ConsensusHeight, ); err != nil { diff --git a/x/ibc/03-connection/keeper/handshake.go b/x/ibc/03-connection/keeper/handshake.go index 12b874d36a15..b52639b3aca4 100644 --- a/x/ibc/03-connection/keeper/handshake.go +++ b/x/ibc/03-connection/keeper/handshake.go @@ -3,7 +3,6 @@ package keeper import ( "bytes" "fmt" - "reflect" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -21,14 +20,24 @@ func (k Keeper) ConnOpenInit( connectionID, // identifier clientID string, counterparty types.Counterparty, // desiredCounterpartyConnectionIdentifier, counterpartyPrefix, counterpartyClientIdentifier + version string, ) error { _, found := k.GetConnection(ctx, connectionID) if found { return types.ErrConnectionExists } + versions := types.GetCompatibleEncodedVersions() + if version != "" { + if !types.IsSupportedVersion(version) { + return sdkerrors.Wrap(types.ErrInvalidVersion, "version is not supported") + } + + versions = []string{version} + } + // connection defines chain A's ConnectionEnd - connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, types.GetCompatibleEncodedVersions()) + connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, versions) k.SetConnection(ctx, connectionID, connection) if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil { @@ -47,7 +56,8 @@ func (k Keeper) ConnOpenInit( // - Identifiers are checked on msg validation func (k Keeper) ConnOpenTry( ctx sdk.Context, - connectionID string, // desiredIdentifier + connectionID, // desiredIdentifier + provedID string, // provedIdentifier counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier clientID string, // clientID of chainA clientState exported.ClientState, // clientState that chainA has for chainB @@ -76,16 +86,41 @@ func (k Keeper) ConnOpenTry( return clienttypes.ErrSelfConsensusStateNotFound } + if provedID != connectionID && provedID != "" { + return sdkerrors.Wrapf( + types.ErrInvalidConnectionIdentifier, + "proved identifier (%s) must equal connection identifier (%s) or be empty", provedID, connectionID, + ) + } + // expectedConnection defines Chain A's ConnectionEnd // NOTE: chain A's counterparty is chain B (i.e where this code is executed) prefix := k.GetCommitmentPrefix() - expectedCounterparty := types.NewCounterparty(clientID, connectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes())) + expectedCounterparty := types.NewCounterparty(clientID, provedID, commitmenttypes.NewMerklePrefix(prefix.Bytes())) expectedConnection := types.NewConnectionEnd(types.INIT, counterparty.ClientId, expectedCounterparty, counterpartyVersions) + // If connection already exists for connectionID, ensure that the existing connection's + // counterparty is chainA and connection is on INIT stage. + // Check that existing connection versions for initialized connection is equal to compatible + // versions for this chain. + previousConnection, found := k.GetConnection(ctx, connectionID) + if found && !(previousConnection.State == types.INIT && + previousConnection.Counterparty.ConnectionId == counterparty.ConnectionId && + bytes.Equal(previousConnection.Counterparty.Prefix.Bytes(), counterparty.Prefix.Bytes()) && + previousConnection.ClientId == clientID && + previousConnection.Counterparty.ClientId == counterparty.ClientId) { + return sdkerrors.Wrap(types.ErrInvalidConnection, "cannot relay connection attempt") + } + + supportedVersions := types.GetCompatibleEncodedVersions() + if len(previousConnection.Versions) != 0 { + supportedVersions = previousConnection.Versions + } + // chain B picks a version from Chain A's available versions that is compatible // with Chain B's supported IBC versions. PickVersion will select the intersection // of the supported versions and the counterparty versions. - version, err := types.PickVersion(counterpartyVersions) + version, err := types.PickVersion(supportedVersions, counterpartyVersions) if err != nil { return err } @@ -113,20 +148,6 @@ func (k Keeper) ConnOpenTry( return err } - // If connection already exists for connectionID, ensure that the existing connection's - // counterparty is chainA and connection is on INIT stage. - // Check that existing connection versions for initialized connection is equal to compatible - // versions for this chain. - previousConnection, found := k.GetConnection(ctx, connectionID) - if found && !(previousConnection.State == types.INIT && - previousConnection.Counterparty.ConnectionId == counterparty.ConnectionId && - bytes.Equal(previousConnection.Counterparty.Prefix.Bytes(), counterparty.Prefix.Bytes()) && - previousConnection.ClientId == clientID && - previousConnection.Counterparty.ClientId == counterparty.ClientId && - reflect.DeepEqual(previousConnection.Versions, types.GetCompatibleEncodedVersions())) { - return sdkerrors.Wrap(types.ErrInvalidConnection, "cannot relay connection attempt") - } - // store connection in chainB state if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil { return sdkerrors.Wrapf(err, "failed to add connection with ID %s to client with ID %s", connectionID, clientID) @@ -145,7 +166,8 @@ func (k Keeper) ConnOpenAck( ctx sdk.Context, connectionID string, clientState exported.ClientState, // client state for chainA on chainB - encodedVersion string, // version that ChainB chose in ConnOpenTry + encodedVersion, // version that ChainB chose in ConnOpenTry + counterpartyConnectionID string, proofTry []byte, // proof that connectionEnd was added to ChainB state in ConnOpenTry proofClient []byte, // proof of client state on chainB for chainA proofConsensus []byte, // proof that chainB has stored ConsensusState of chainA on its client @@ -167,6 +189,13 @@ func (k Keeper) ConnOpenAck( return sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID) } + if counterpartyConnectionID != connection.Counterparty.ConnectionId && connection.Counterparty.ConnectionId != "" { + return sdkerrors.Wrapf( + types.ErrInvalidConnectionIdentifier, + "counterparty connection identifier (%s) must be empty or equal to stored connection ID for counterparty (%s)", counterpartyConnectionID, connection.Counterparty.ConnectionId, + ) + } + // Verify the provided version against the previously set connection state switch { // connection on ChainA must be in INIT or TRYOPEN @@ -209,7 +238,7 @@ func (k Keeper) ConnOpenAck( // Ensure that ChainB stored expected connectionEnd in its state during ConnOpenTry if err := k.VerifyConnectionState( - ctx, connection, proofHeight, proofTry, connection.Counterparty.ConnectionId, + ctx, connection, proofHeight, proofTry, counterpartyConnectionID, expectedConnection, ); err != nil { return err @@ -232,6 +261,7 @@ func (k Keeper) ConnOpenAck( // Update connection state to Open connection.State = types.OPEN connection.Versions = []string{encodedVersion} + connection.Counterparty.ConnectionId = counterpartyConnectionID k.SetConnection(ctx, connectionID, connection) return nil } diff --git a/x/ibc/03-connection/keeper/handshake_test.go b/x/ibc/03-connection/keeper/handshake_test.go index d55f7e299883..db47aad07ece 100644 --- a/x/ibc/03-connection/keeper/handshake_test.go +++ b/x/ibc/03-connection/keeper/handshake_test.go @@ -15,8 +15,10 @@ import ( // chainB which is yet UNINITIALIZED func (suite *KeeperTestSuite) TestConnOpenInit() { var ( - clientA string - clientB string + clientA string + clientB string + version string + emptyConnBID bool ) testCases := []struct { @@ -27,9 +29,21 @@ func (suite *KeeperTestSuite) TestConnOpenInit() { {"success", func() { clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) }, true}, + {"success with empty counterparty identifier", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + emptyConnBID = true + }, true}, + {"success with non empty version", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + version = types.GetCompatibleEncodedVersions()[0] + }, true}, {"connection already exists", func() { clientA, clientB, _, _ = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, ibctesting.Tendermint) }, false}, + {"invalid version", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + version = "bad version" + }, false}, {"couldn't add connection to client", func() { // swap client identifiers to result in client that does not exist clientB, clientA = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) @@ -39,15 +53,20 @@ func (suite *KeeperTestSuite) TestConnOpenInit() { for _, tc := range testCases { tc := tc suite.Run(tc.msg, func() { - suite.SetupTest() // reset + suite.SetupTest() // reset + emptyConnBID = false // must be explicitly changed + version = "" // must be explicitly changed tc.malleate() connA := suite.chainA.GetFirstTestConnection(clientA, clientB) connB := suite.chainB.GetFirstTestConnection(clientB, clientA) + if emptyConnBID { + connB.ID = "" + } counterparty := types.NewCounterparty(clientB, connB.ID, suite.chainB.GetPrefix()) - err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenInit(suite.chainA.GetContext(), connA.ID, clientA, counterparty) + err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenInit(suite.chainA.GetContext(), connA.ID, clientA, counterparty, version) if tc.expPass { suite.Require().NoError(err) @@ -82,13 +101,56 @@ func (suite *KeeperTestSuite) TestConnOpenTry() { // retrieve client state of chainA to pass as counterpartyClient counterpartyClient = suite.chainA.GetClientState(clientA) }, true}, + {"success with empty provedID", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + connA, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) + suite.Require().NoError(err) + + // modify connA to set counterparty connection identifier to empty string + connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) + suite.Require().True(found) + + connection.Counterparty.ConnectionId = "" + + suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) + + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint) + suite.Require().NoError(err) + + err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, ibctesting.Tendermint) + suite.Require().NoError(err) + + // retrieve client state of chainA to pass as counterpartyClient + counterpartyClient = suite.chainA.GetClientState(clientA) + }, true}, + {"success with empty provedID", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + connA, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) + suite.Require().NoError(err) + + // modify connA to set counterparty connection identifier to invalid identifier + connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) + suite.Require().True(found) + + connection.Counterparty.ConnectionId = "badidentifier" + + suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) + + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint) + suite.Require().NoError(err) + + err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, ibctesting.Tendermint) + suite.Require().NoError(err) + + // retrieve client state of chainA to pass as counterpartyClient + counterpartyClient = suite.chainA.GetClientState(clientA) + }, false}, {"invalid counterparty client", func() { clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) suite.Require().NoError(err) - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) + // retrieve client state of chainB to pass as counterpartyClient counterpartyClient = suite.chainA.GetClientState(clientA) // Set an invalid client of chainA on chainB tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState) @@ -238,6 +300,13 @@ func (suite *KeeperTestSuite) TestConnOpenTry() { connB := suite.chainB.GetFirstTestConnection(clientB, clientA) counterparty := types.NewCounterparty(clientA, connA.ID, suite.chainA.GetPrefix()) + // get provedID + var provedID string + connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) + if found { + provedID = connection.Counterparty.ConnectionId + } + connectionKey := host.KeyConnection(connA.ID) proofInit, proofHeight := suite.chainA.QueryProof(connectionKey) @@ -253,7 +322,7 @@ func (suite *KeeperTestSuite) TestConnOpenTry() { proofClient, _ := suite.chainA.QueryProof(clientKey) err := suite.chainB.App.IBCKeeper.ConnectionKeeper.ConnOpenTry( - suite.chainB.GetContext(), connB.ID, counterparty, clientB, counterpartyClient, + suite.chainB.GetContext(), connB.ID, provedID, counterparty, clientB, counterpartyClient, versions, proofInit, proofClient, proofConsensus, proofHeight, consensusHeight, ) @@ -271,11 +340,12 @@ func (suite *KeeperTestSuite) TestConnOpenTry() { // the initialization (TRYINIT) of the connection on Chain B (ID #2). func (suite *KeeperTestSuite) TestConnOpenAck() { var ( - clientA string - clientB string - consensusHeight exported.Height - version string - counterpartyClient exported.ClientState + clientA string + clientB string + counterpartyConnectionID string + consensusHeight exported.Height + version string + counterpartyClient exported.ClientState ) testCases := []struct { @@ -288,11 +358,38 @@ func (suite *KeeperTestSuite) TestConnOpenAck() { connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) suite.Require().NoError(err) + err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) + suite.Require().NoError(err) + // retrieve client state of chainB to pass as counterpartyClient counterpartyClient = suite.chainB.GetClientState(clientB) + }, true}, + {"success with empty counterparty connection ID", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) + suite.Require().NoError(err) err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) suite.Require().NoError(err) + + // modify connA to set counterparty connection identifier to empty string + connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) + suite.Require().True(found) + + connection.Counterparty.ConnectionId = "" + // use some other identifier + counterpartyConnectionID = connB.ID + + suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) + + err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, ibctesting.Tendermint) + suite.Require().NoError(err) + + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint) + suite.Require().NoError(err) + + // retrieve client state of chainB to pass as counterpartyClient + counterpartyClient = suite.chainB.GetClientState(clientB) }, true}, {"success from tryopen", func() { // chainA is in TRYOPEN, chainB is in TRYOPEN @@ -315,6 +412,37 @@ func (suite *KeeperTestSuite) TestConnOpenAck() { // retrieve client state of chainB to pass as counterpartyClient counterpartyClient = suite.chainB.GetClientState(clientB) }, true}, + {"success from tryopen with empty string", func() { + // chainA is in TRYOPEN, chainB is in TRYOPEN + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + connB, connA, err := suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) + suite.Require().NoError(err) + + err = suite.coordinator.ConnOpenTry(suite.chainA, suite.chainB, connA, connB) + suite.Require().NoError(err) + + // set chainB to TRYOPEN + connection := suite.chainB.GetConnection(connB) + connection.State = types.TRYOPEN + + suite.chainB.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainB.GetContext(), connB.ID, connection) + + // set connA to use empty string + connection = suite.chainA.GetConnection(connA) + + // set counterparty connection identifier to empty string + connection.Counterparty.ConnectionId = "" + + suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) + + // update clientB so state change is committed + suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, ibctesting.Tendermint) + + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint) + + // retrieve client state of chainB to pass as counterpartyClient + counterpartyClient = suite.chainB.GetClientState(clientB) + }, true}, {"invalid counterparty client", func() { clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) @@ -353,6 +481,31 @@ func (suite *KeeperTestSuite) TestConnOpenAck() { // retrieve client state of chainB to pass as counterpartyClient counterpartyClient = suite.chainB.GetClientState(clientB) }, false}, + {"invalid counterparty connection ID", func() { + clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) + connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) + suite.Require().NoError(err) + + // retrieve client state of chainB to pass as counterpartyClient + counterpartyClient = suite.chainB.GetClientState(clientB) + + err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) + suite.Require().NoError(err) + + // modify connB to set counterparty connection identifier to wrong identifier + connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) + suite.Require().True(found) + + connection.Counterparty.ConnectionId = "badconnectionid" + + suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) + + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint) + suite.Require().NoError(err) + + err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, ibctesting.Tendermint) + suite.Require().NoError(err) + }, false}, {"connection state is not INIT", func() { // connection state is already OPEN on chainA clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint) @@ -513,12 +666,17 @@ func (suite *KeeperTestSuite) TestConnOpenAck() { suite.SetupTest() // reset version = types.GetCompatibleEncodedVersions()[0] // must be explicitly changed in malleate consensusHeight = clienttypes.ZeroHeight() // must be explicitly changed in malleate + counterpartyConnectionID = "" // must be explicitly changed in malleate tc.malleate() connA := suite.chainA.GetFirstTestConnection(clientA, clientB) connB := suite.chainB.GetFirstTestConnection(clientB, clientA) + if counterpartyConnectionID == "" { + counterpartyConnectionID = connB.ID + } + connectionKey := host.KeyConnection(connB.ID) proofTry, proofHeight := suite.chainB.QueryProof(connectionKey) @@ -535,7 +693,7 @@ func (suite *KeeperTestSuite) TestConnOpenAck() { proofClient, _ := suite.chainB.QueryProof(clientKey) err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenAck( - suite.chainA.GetContext(), connA.ID, counterpartyClient, version, + suite.chainA.GetContext(), connA.ID, counterpartyClient, version, counterpartyConnectionID, proofTry, proofClient, proofConsensus, proofHeight, consensusHeight, ) diff --git a/x/ibc/03-connection/types/connection.go b/x/ibc/03-connection/types/connection.go index 0a79b8cf0d93..efb3bcd3d179 100644 --- a/x/ibc/03-connection/types/connection.go +++ b/x/ibc/03-connection/types/connection.go @@ -85,8 +85,10 @@ func (c Counterparty) GetPrefix() exported.Prefix { // ValidateBasic performs a basic validation check of the identifiers and prefix func (c Counterparty) ValidateBasic() error { - if err := host.ConnectionIdentifierValidator(c.ConnectionId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty connection ID") + if c.ConnectionId != "" { + if err := host.ConnectionIdentifierValidator(c.ConnectionId); err != nil { + return sdkerrors.Wrap(err, "invalid counterparty connection ID") + } } if err := host.ClientIdentifierValidator(c.ClientId); err != nil { return sdkerrors.Wrap(err, "invalid counterparty client ID") diff --git a/x/ibc/03-connection/types/connection.pb.go b/x/ibc/03-connection/types/connection.pb.go index 15b7fe5fde61..ffb3fdccd750 100644 --- a/x/ibc/03-connection/types/connection.pb.go +++ b/x/ibc/03-connection/types/connection.pb.go @@ -70,7 +70,8 @@ type MsgConnectionOpenInit struct { ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` Counterparty Counterparty `protobuf:"bytes,3,opt,name=counterparty,proto3" json:"counterparty"` - Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty"` + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"` } func (m *MsgConnectionOpenInit) Reset() { *m = MsgConnectionOpenInit{} } @@ -111,19 +112,20 @@ var xxx_messageInfo_MsgConnectionOpenInit proto.InternalMessageInfo type MsgConnectionOpenTry struct { ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - ClientState *types.Any `protobuf:"bytes,3,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` - Counterparty Counterparty `protobuf:"bytes,4,opt,name=counterparty,proto3" json:"counterparty"` - CounterpartyVersions []string `protobuf:"bytes,5,rep,name=counterparty_versions,json=counterpartyVersions,proto3" json:"counterparty_versions,omitempty" yaml:"counterparty_versions"` - ProofHeight types1.Height `protobuf:"bytes,6,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` + ProvedId string `protobuf:"bytes,3,opt,name=proved_id,json=provedId,proto3" json:"proved_id,omitempty" yaml:"proved_id"` + ClientState *types.Any `protobuf:"bytes,4,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` + Counterparty Counterparty `protobuf:"bytes,5,opt,name=counterparty,proto3" json:"counterparty"` + CounterpartyVersions []string `protobuf:"bytes,6,rep,name=counterparty_versions,json=counterpartyVersions,proto3" json:"counterparty_versions,omitempty" yaml:"counterparty_versions"` + ProofHeight types1.Height `protobuf:"bytes,7,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` // proof of the initialization the connection on Chain A: `UNITIALIZED -> // INIT` - ProofInit []byte `protobuf:"bytes,7,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"` + ProofInit []byte `protobuf:"bytes,8,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"` // proof of client state included in message - ProofClient []byte `protobuf:"bytes,8,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"` + ProofClient []byte `protobuf:"bytes,9,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"` // proof of client consensus state - ProofConsensus []byte `protobuf:"bytes,9,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"` - ConsensusHeight types1.Height `protobuf:"bytes,10,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height" yaml:"consensus_height"` - Signer string `protobuf:"bytes,11,opt,name=signer,proto3" json:"signer,omitempty"` + ProofConsensus []byte `protobuf:"bytes,10,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"` + ConsensusHeight types1.Height `protobuf:"bytes,11,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height" yaml:"consensus_height"` + Signer string `protobuf:"bytes,12,opt,name=signer,proto3" json:"signer,omitempty"` } func (m *MsgConnectionOpenTry) Reset() { *m = MsgConnectionOpenTry{} } @@ -162,19 +164,20 @@ var xxx_messageInfo_MsgConnectionOpenTry proto.InternalMessageInfo // MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to // acknowledge the change of connection state to TRYOPEN on Chain B. type MsgConnectionOpenAck struct { - ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - ClientState *types.Any `protobuf:"bytes,3,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` - ProofHeight types1.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` + ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` + CounterpartyConnectionId string `protobuf:"bytes,2,opt,name=counterparty_connection_id,json=counterpartyConnectionId,proto3" json:"counterparty_connection_id,omitempty" yaml:"counterparty_connection_id"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + ClientState *types.Any `protobuf:"bytes,4,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` + ProofHeight types1.Height `protobuf:"bytes,5,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` // proof of the initialization the connection on Chain B: `UNITIALIZED -> // TRYOPEN` - ProofTry []byte `protobuf:"bytes,5,opt,name=proof_try,json=proofTry,proto3" json:"proof_try,omitempty" yaml:"proof_try"` + ProofTry []byte `protobuf:"bytes,6,opt,name=proof_try,json=proofTry,proto3" json:"proof_try,omitempty" yaml:"proof_try"` // proof of client state included in message - ProofClient []byte `protobuf:"bytes,6,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"` + ProofClient []byte `protobuf:"bytes,7,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"` // proof of client consensus state - ProofConsensus []byte `protobuf:"bytes,7,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"` - ConsensusHeight types1.Height `protobuf:"bytes,8,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height" yaml:"consensus_height"` - Signer string `protobuf:"bytes,9,opt,name=signer,proto3" json:"signer,omitempty"` + ProofConsensus []byte `protobuf:"bytes,8,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"` + ConsensusHeight types1.Height `protobuf:"bytes,9,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height" yaml:"consensus_height"` + Signer string `protobuf:"bytes,10,opt,name=signer,proto3" json:"signer,omitempty"` } func (m *MsgConnectionOpenAck) Reset() { *m = MsgConnectionOpenAck{} } @@ -557,71 +560,75 @@ func init() { } var fileDescriptor_90572467c054e43a = []byte{ - // 1014 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xcf, 0x6f, 0x1a, 0x47, - 0x14, 0x66, 0x31, 0x3f, 0x1f, 0x10, 0x93, 0x2d, 0xb6, 0xb7, 0xb4, 0x61, 0xd1, 0xb6, 0x52, 0xad, - 0x4a, 0xd9, 0x2d, 0x71, 0x95, 0x83, 0xa5, 0x1e, 0x0c, 0xa1, 0xea, 0xaa, 0x0d, 0x41, 0x6b, 0x5c, - 0xa9, 0xbe, 0x20, 0x58, 0x06, 0x3c, 0xc2, 0xec, 0xa2, 0xdd, 0x05, 0x85, 0xff, 0x20, 0xf2, 0xa5, - 0xbd, 0xf6, 0xe0, 0x2a, 0x52, 0xff, 0x99, 0xa8, 0xa7, 0x1c, 0x2b, 0x55, 0x42, 0x95, 0x7d, 0x69, - 0xaf, 0x5c, 0x7b, 0xa9, 0x66, 0x66, 0x7f, 0x81, 0xb1, 0xa2, 0xc4, 0x44, 0x39, 0x31, 0xdf, 0xbc, - 0xef, 0xcd, 0xcc, 0xfb, 0xe6, 0x9b, 0x99, 0x05, 0xbe, 0xc0, 0x5d, 0x5d, 0xd1, 0x4d, 0x0b, 0x29, - 0xba, 0x69, 0x18, 0x48, 0x77, 0xb0, 0x69, 0x28, 0xd3, 0x4a, 0x08, 0xc9, 0x63, 0xcb, 0x74, 0x4c, - 0x7e, 0x17, 0x77, 0x75, 0x99, 0x10, 0xe5, 0x50, 0x68, 0x5a, 0x29, 0x16, 0x06, 0xe6, 0xc0, 0xa4, - 0x14, 0x85, 0xb4, 0x18, 0xbb, 0xf8, 0xf1, 0xc0, 0x34, 0x07, 0xe7, 0x48, 0xa1, 0xa8, 0x3b, 0xe9, - 0x2b, 0x1d, 0x63, 0xe6, 0x86, 0xc2, 0x33, 0x8e, 0x46, 0xd8, 0x19, 0x21, 0xc3, 0x61, 0x33, 0x7a, - 0xc8, 0x25, 0x8a, 0x01, 0xf1, 0x1c, 0x7b, 0x24, 0xda, 0x62, 0x04, 0xe9, 0x3f, 0x0e, 0x76, 0x9e, - 0xda, 0x83, 0x9a, 0xbf, 0x9e, 0x67, 0x63, 0x64, 0xa8, 0x06, 0x76, 0xf8, 0x0a, 0xa4, 0x19, 0xb3, - 0x8d, 0x7b, 0x02, 0x57, 0xe6, 0xf6, 0xd3, 0xd5, 0xc2, 0x62, 0x2e, 0xe6, 0x67, 0x9d, 0xd1, 0xf9, - 0xa1, 0xe4, 0x87, 0x24, 0x2d, 0xc5, 0xda, 0x6a, 0x8f, 0xff, 0x06, 0x72, 0x41, 0x61, 0x24, 0x2d, - 0x4a, 0xd3, 0x84, 0xc5, 0x5c, 0x2c, 0xb8, 0x69, 0xe1, 0xb0, 0xa4, 0x65, 0x03, 0xac, 0xf6, 0xf8, - 0x06, 0x64, 0x75, 0x73, 0x62, 0x38, 0xc8, 0x1a, 0x77, 0x2c, 0x67, 0x26, 0x6c, 0x95, 0xb9, 0xfd, - 0xcc, 0xa3, 0xcf, 0xe5, 0xf5, 0xaa, 0xc9, 0xb5, 0x10, 0xb7, 0x1a, 0x7b, 0x35, 0x17, 0x23, 0xda, - 0x52, 0x3e, 0xbf, 0x0b, 0x09, 0x1b, 0x0f, 0x0c, 0x64, 0x09, 0x31, 0xb2, 0x0e, 0xcd, 0x45, 0x87, - 0xa9, 0x17, 0x2f, 0xc5, 0xc8, 0x3f, 0x2f, 0xc5, 0x88, 0xf4, 0x5b, 0x02, 0x0a, 0x37, 0xaa, 0x6f, - 0x59, 0xb3, 0x0f, 0x50, 0x7c, 0x13, 0xb2, 0xee, 0xb0, 0xb6, 0xd3, 0x71, 0x90, 0x5b, 0x7c, 0x41, - 0x66, 0x26, 0x90, 0x3d, 0x13, 0xc8, 0x47, 0xc6, 0xac, 0xba, 0xb7, 0x98, 0x8b, 0x1f, 0x2d, 0x2d, - 0x85, 0xe6, 0x48, 0x5a, 0x86, 0xc1, 0x63, 0x82, 0x6e, 0xc8, 0x19, 0xbb, 0xa3, 0x9c, 0x27, 0xb0, - 0x13, 0xc6, 0xed, 0x29, 0xb2, 0x6c, 0x6c, 0x1a, 0xb6, 0x10, 0x2f, 0x6f, 0xed, 0xa7, 0xab, 0xe5, - 0xc5, 0x5c, 0xfc, 0xd4, 0x2b, 0x74, 0x0d, 0x4d, 0xd2, 0x0a, 0xe1, 0xfe, 0x1f, 0xdd, 0x6e, 0xfe, - 0x14, 0xb2, 0x63, 0xcb, 0x34, 0xfb, 0xed, 0x33, 0x84, 0x07, 0x67, 0x8e, 0x90, 0xa0, 0xcb, 0x2c, - 0x86, 0x96, 0xc9, 0xfc, 0x3a, 0xad, 0xc8, 0xdf, 0x51, 0x46, 0xf5, 0x13, 0xb2, 0xb8, 0x40, 0x82, - 0x70, 0xb6, 0xa4, 0x65, 0x28, 0x64, 0x4c, 0xfe, 0x6b, 0x00, 0x16, 0xc5, 0x06, 0x76, 0x84, 0x64, - 0x99, 0xdb, 0xcf, 0x56, 0x77, 0x16, 0x73, 0xf1, 0x7e, 0x38, 0x93, 0xc4, 0x24, 0x2d, 0x4d, 0x01, - 0x75, 0xfe, 0xa1, 0xb7, 0x22, 0x36, 0xb3, 0x90, 0xa2, 0x79, 0x7b, 0xab, 0x33, 0xb2, 0xa8, 0x37, - 0x63, 0x8d, 0x22, 0xbe, 0x06, 0xdb, 0x6e, 0xd4, 0x34, 0x6c, 0x64, 0xd8, 0x13, 0x5b, 0x48, 0xd3, - 0xf4, 0xe2, 0x62, 0x2e, 0xee, 0x2e, 0xa5, 0x7b, 0x04, 0x49, 0xbb, 0xc7, 0x46, 0xf0, 0x3a, 0xf8, - 0x3e, 0xe4, 0xfd, 0xa8, 0x27, 0x0b, 0xbc, 0x51, 0x16, 0xd1, 0x95, 0x65, 0xcf, 0x77, 0xdb, 0xd2, - 0x08, 0x92, 0xb6, 0xed, 0x77, 0xb9, 0xf2, 0x04, 0x07, 0x24, 0x73, 0xcb, 0x01, 0xf9, 0x2b, 0xb6, - 0xe6, 0x80, 0x1c, 0xe9, 0xc3, 0x9b, 0x6e, 0xe7, 0xde, 0xca, 0xed, 0x02, 0x24, 0x5d, 0x5f, 0xb0, - 0x63, 0xa2, 0x79, 0xf0, 0x3d, 0x9c, 0x83, 0x55, 0x83, 0xc5, 0x36, 0x68, 0xb0, 0x0a, 0x30, 0xdf, - 0xb4, 0x1d, 0x6b, 0x26, 0xc4, 0xe9, 0x46, 0x87, 0xee, 0x09, 0x3f, 0x24, 0x69, 0x29, 0xda, 0x26, - 0x57, 0xcb, 0xaa, 0xbb, 0x12, 0x77, 0x73, 0x57, 0x72, 0x23, 0xee, 0x4a, 0xbd, 0x57, 0x77, 0xa5, - 0x6f, 0x71, 0xd7, 0x45, 0x14, 0x84, 0x1b, 0xee, 0xaa, 0x99, 0x46, 0x1f, 0x5b, 0xa3, 0xbb, 0x3a, - 0xcc, 0xdf, 0x99, 0x8e, 0x3e, 0xa4, 0x1e, 0x5b, 0xb3, 0x33, 0x1d, 0x7d, 0xe8, 0xed, 0x0c, 0xf1, - 0xf4, 0xaa, 0x51, 0xb6, 0x36, 0x68, 0x94, 0x37, 0xbf, 0x45, 0xff, 0x72, 0x90, 0x0b, 0x94, 0xa8, - 0x1b, 0xbd, 0x77, 0x79, 0x84, 0x8a, 0x90, 0xf2, 0xaf, 0xe5, 0x28, 0xb9, 0x96, 0x35, 0x1f, 0xf3, - 0x07, 0x10, 0x0f, 0x8e, 0xd4, 0xbd, 0x47, 0x0f, 0x6e, 0x7b, 0x08, 0xe8, 0xa9, 0xd1, 0x18, 0x77, - 0xd3, 0x8f, 0xc8, 0x61, 0x8c, 0xd4, 0x2b, 0xfd, 0x1c, 0x85, 0x82, 0xda, 0x43, 0x86, 0x83, 0xfb, - 0x18, 0xf5, 0x82, 0xaa, 0xf9, 0x07, 0x10, 0xf5, 0x6b, 0xcd, 0x2d, 0xe6, 0x62, 0x9a, 0xd5, 0x4a, - 0x8a, 0x8c, 0xe2, 0x15, 0x45, 0xa2, 0x6f, 0xad, 0xc8, 0xd6, 0x6d, 0x8a, 0xc4, 0xee, 0xa0, 0x48, - 0x7c, 0x23, 0x8a, 0xfc, 0xc1, 0x41, 0x36, 0x4c, 0xfd, 0x00, 0x5f, 0x20, 0x55, 0x48, 0x8c, 0x2d, - 0xd4, 0xc7, 0xcf, 0xd7, 0x7d, 0x78, 0xf9, 0xdf, 0x95, 0xd3, 0x8a, 0xfc, 0x14, 0x59, 0xc3, 0x73, - 0xd4, 0xa4, 0x5c, 0xb7, 0x24, 0x37, 0xd3, 0x2d, 0xe6, 0x33, 0xc8, 0xb0, 0x0b, 0xab, 0xd9, 0x71, - 0xce, 0x6c, 0xbe, 0x00, 0xf1, 0x31, 0x69, 0x08, 0x1c, 0xd5, 0x9f, 0x01, 0xe9, 0x14, 0xb6, 0x83, - 0x8d, 0x67, 0xc4, 0x77, 0xa8, 0xd9, 0x1f, 0x3b, 0x1a, 0x1e, 0xfb, 0x7b, 0x48, 0xba, 0xdf, 0x17, - 0x7c, 0x09, 0x00, 0x7b, 0x4e, 0xb3, 0xd8, 0xa0, 0x5a, 0xa8, 0x87, 0xf8, 0xa3, 0x8f, 0x3a, 0xce, - 0xc4, 0x42, 0xfe, 0x89, 0xf1, 0x30, 0xab, 0xe6, 0xcb, 0x5f, 0x39, 0x88, 0xb3, 0x97, 0xe4, 0x31, - 0x88, 0xc7, 0xad, 0xa3, 0x56, 0xbd, 0x7d, 0xd2, 0x50, 0x1b, 0x6a, 0x4b, 0x3d, 0xfa, 0x41, 0x3d, - 0xad, 0x3f, 0x69, 0x9f, 0x34, 0x8e, 0x9b, 0xf5, 0x9a, 0xfa, 0xad, 0x5a, 0x7f, 0x92, 0x8f, 0x14, - 0xef, 0x5f, 0x5c, 0x96, 0x73, 0x4b, 0x04, 0x5e, 0x00, 0x60, 0x79, 0xa4, 0x33, 0xcf, 0x15, 0x53, - 0x17, 0x97, 0xe5, 0x18, 0x69, 0xf3, 0x25, 0xc8, 0xb1, 0x48, 0x4b, 0xfb, 0xe9, 0x59, 0xb3, 0xde, - 0xc8, 0x47, 0x8b, 0x99, 0x8b, 0xcb, 0x72, 0xd2, 0x85, 0x41, 0x26, 0x0d, 0x6e, 0xb1, 0x4c, 0xd2, - 0x2e, 0xc6, 0x5e, 0xfc, 0x5e, 0x8a, 0x54, 0x9b, 0xaf, 0xae, 0x4a, 0xdc, 0xeb, 0xab, 0x12, 0xf7, - 0xf7, 0x55, 0x89, 0xfb, 0xe5, 0xba, 0x14, 0x79, 0x7d, 0x5d, 0x8a, 0xfc, 0x79, 0x5d, 0x8a, 0x9c, - 0x3e, 0x1e, 0x60, 0xe7, 0x6c, 0xd2, 0x25, 0x5b, 0xa7, 0xe8, 0xa6, 0x3d, 0x32, 0x6d, 0xf7, 0xe7, - 0xa1, 0xdd, 0x1b, 0x2a, 0xcf, 0x15, 0xf2, 0xc7, 0xe0, 0xab, 0x83, 0x87, 0xa1, 0x7f, 0x2c, 0xce, - 0x6c, 0x8c, 0xec, 0x6e, 0x82, 0xbe, 0xb0, 0x07, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xf2, 0x12, - 0xa2, 0xf0, 0xd5, 0x0c, 0x00, 0x00, + // 1076 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0x4f, 0x6f, 0x1a, 0x47, + 0x14, 0x67, 0x97, 0x3f, 0x86, 0x01, 0x27, 0x64, 0x8b, 0xed, 0xed, 0xb6, 0x61, 0xe9, 0xb6, 0x55, + 0xad, 0x4a, 0x59, 0x8a, 0x5d, 0xe5, 0x60, 0xa9, 0x07, 0x43, 0xa8, 0xba, 0x6a, 0x43, 0xd0, 0x1a, + 0x57, 0xaa, 0x2f, 0x08, 0x96, 0x01, 0x8f, 0x30, 0x3b, 0x68, 0x77, 0x41, 0xe1, 0x1b, 0x44, 0xbe, + 0xb4, 0x97, 0x1e, 0x7a, 0xb0, 0x14, 0xa9, 0x5f, 0xa4, 0xc7, 0xa8, 0xa7, 0xf4, 0xd6, 0x13, 0xaa, + 0xec, 0x4b, 0x7b, 0xe5, 0x13, 0x54, 0x33, 0xb3, 0xff, 0xf8, 0xa7, 0x2a, 0x81, 0x2a, 0x27, 0xe6, + 0xcd, 0xfb, 0xbd, 0x99, 0x79, 0xbf, 0xf9, 0xbd, 0x37, 0x0b, 0xf8, 0x0c, 0xb5, 0x8d, 0xa2, 0x81, + 0x2d, 0x58, 0x34, 0xb0, 0x69, 0x42, 0xc3, 0x41, 0xd8, 0x2c, 0x8e, 0x4b, 0x21, 0x4b, 0x1d, 0x5a, + 0xd8, 0xc1, 0xc2, 0x3e, 0x6a, 0x1b, 0x2a, 0x01, 0xaa, 0x21, 0xd7, 0xb8, 0x24, 0xe5, 0x7a, 0xb8, + 0x87, 0x29, 0xa4, 0x48, 0x46, 0x0c, 0x2d, 0xbd, 0xdf, 0xc3, 0xb8, 0x77, 0x05, 0x8b, 0xd4, 0x6a, + 0x8f, 0xba, 0xc5, 0x96, 0x39, 0x71, 0x5d, 0xe1, 0x1d, 0x07, 0x03, 0xe4, 0x0c, 0xa0, 0xe9, 0xb0, + 0x1d, 0x3d, 0xcb, 0x05, 0xca, 0x01, 0xf0, 0x0a, 0x79, 0x20, 0x3a, 0x62, 0x00, 0xe5, 0x67, 0x1e, + 0xec, 0x3d, 0xb5, 0x7b, 0x15, 0xff, 0x3c, 0xcf, 0x86, 0xd0, 0xd4, 0x4c, 0xe4, 0x08, 0x25, 0x90, + 0x62, 0xc8, 0x26, 0xea, 0x88, 0x5c, 0x81, 0x3b, 0x4c, 0x95, 0x73, 0xb3, 0xa9, 0x9c, 0x9d, 0xb4, + 0x06, 0x57, 0x27, 0x8a, 0xef, 0x52, 0xf4, 0x24, 0x1b, 0x6b, 0x1d, 0xe1, 0x2b, 0xb0, 0x1b, 0x24, + 0x46, 0xc2, 0x78, 0x1a, 0x26, 0xce, 0xa6, 0x72, 0xce, 0x0d, 0x0b, 0xbb, 0x15, 0x3d, 0x13, 0xd8, + 0x5a, 0x47, 0xa8, 0x81, 0x8c, 0x81, 0x47, 0xa6, 0x03, 0xad, 0x61, 0xcb, 0x72, 0x26, 0x62, 0xb4, + 0xc0, 0x1d, 0xa6, 0x8f, 0x3e, 0x51, 0x57, 0xb3, 0xa6, 0x56, 0x42, 0xd8, 0x72, 0xec, 0xd5, 0x54, + 0x8e, 0xe8, 0x73, 0xf1, 0x82, 0x08, 0x76, 0xc6, 0xd0, 0xb2, 0x11, 0x36, 0xc5, 0x18, 0x39, 0x88, + 0xee, 0x99, 0xc2, 0x3e, 0x48, 0xd8, 0xa8, 0x67, 0x42, 0x4b, 0x8c, 0x53, 0x87, 0x6b, 0x9d, 0x24, + 0x5f, 0xbc, 0x94, 0x23, 0x7f, 0xbf, 0x94, 0x23, 0xca, 0x1f, 0x09, 0x90, 0x5b, 0xe2, 0xa5, 0x61, + 0x4d, 0xde, 0x01, 0x2d, 0x25, 0x90, 0x1a, 0x5a, 0x78, 0x0c, 0x3b, 0x24, 0x34, 0xba, 0xb8, 0xa3, + 0xef, 0x52, 0xf4, 0x24, 0x1b, 0x6b, 0x1d, 0xa1, 0x0e, 0x32, 0xee, 0x49, 0x6c, 0xa7, 0xe5, 0x40, + 0x9a, 0x7e, 0xfa, 0x28, 0xa7, 0x32, 0x45, 0xa9, 0x9e, 0xa2, 0xd4, 0x53, 0x73, 0x52, 0x3e, 0x98, + 0x4d, 0xe5, 0xf7, 0xe6, 0x4e, 0x4f, 0x63, 0x14, 0x3d, 0xcd, 0xcc, 0x33, 0x62, 0x2d, 0xdd, 0x4d, + 0x7c, 0xc3, 0xbb, 0x39, 0x07, 0x7b, 0x61, 0xbb, 0xe9, 0xde, 0x8c, 0x2d, 0x26, 0x0a, 0xd1, 0xc3, + 0x54, 0xb9, 0x30, 0x9b, 0xca, 0x1f, 0x7a, 0xdc, 0xac, 0x80, 0x29, 0x7a, 0x2e, 0x3c, 0xff, 0xbd, + 0x3b, 0x2d, 0x5c, 0x80, 0xcc, 0xd0, 0xc2, 0xb8, 0xdb, 0xbc, 0x84, 0xa8, 0x77, 0xe9, 0x88, 0x3b, + 0xf4, 0x98, 0x52, 0xe8, 0x98, 0x4c, 0xfc, 0xe3, 0x92, 0xfa, 0x0d, 0x45, 0x94, 0x3f, 0x20, 0x87, + 0x0b, 0x28, 0x08, 0x47, 0x2b, 0x7a, 0x9a, 0x9a, 0x0c, 0x29, 0x7c, 0x09, 0x00, 0xf3, 0x22, 0x13, + 0x39, 0x62, 0xb2, 0xc0, 0x1d, 0x66, 0xca, 0x7b, 0xb3, 0xa9, 0xfc, 0x20, 0x1c, 0x49, 0x7c, 0x8a, + 0x9e, 0xa2, 0x06, 0x2d, 0xa3, 0x13, 0xef, 0x44, 0x6c, 0x67, 0x31, 0x45, 0xe3, 0x0e, 0x16, 0x77, + 0x64, 0x5e, 0x6f, 0xc7, 0x0a, 0xb5, 0x84, 0x0a, 0xb8, 0xef, 0x7a, 0xb1, 0x69, 0x43, 0xd3, 0x1e, + 0xd9, 0x22, 0xa0, 0xe1, 0xd2, 0x6c, 0x2a, 0xef, 0xcf, 0x85, 0x7b, 0x00, 0x45, 0xbf, 0xc7, 0x56, + 0xf0, 0x26, 0x84, 0x2e, 0xc8, 0xfa, 0x5e, 0x8f, 0x96, 0xf4, 0x7f, 0xd2, 0x22, 0xbb, 0xb4, 0x1c, + 0xf8, 0x02, 0x9d, 0x5b, 0x41, 0xd1, 0xef, 0xfb, 0x53, 0x2e, 0x3d, 0x41, 0x4d, 0x65, 0xd6, 0xd4, + 0xd4, 0x6f, 0xf1, 0x15, 0x35, 0x75, 0x6a, 0xf4, 0x97, 0x0b, 0x84, 0x7b, 0xa3, 0x02, 0x31, 0x80, + 0x34, 0x27, 0x92, 0x55, 0xc5, 0xf6, 0xe9, 0x6c, 0x2a, 0x7f, 0xb4, 0x42, 0x50, 0x0b, 0x0b, 0x8b, + 0x61, 0x67, 0x25, 0xbc, 0x49, 0xa8, 0x99, 0x44, 0xe7, 0x9b, 0xc9, 0xf6, 0x8b, 0x6d, 0x51, 0xc5, + 0xf1, 0x2d, 0xaa, 0x98, 0x75, 0x13, 0xdc, 0x6d, 0x3a, 0xd6, 0x44, 0x4c, 0x50, 0x35, 0xcd, 0x77, + 0x13, 0xe6, 0x62, 0xdd, 0x04, 0x77, 0x49, 0xcb, 0x5b, 0x94, 0xf0, 0xce, 0x66, 0x12, 0x4e, 0x6e, + 0x45, 0xc2, 0xa9, 0xff, 0x55, 0xc2, 0x60, 0x8d, 0x84, 0xaf, 0x79, 0x20, 0x2e, 0x49, 0xb8, 0x82, + 0xcd, 0x2e, 0xb2, 0x06, 0x9b, 0xca, 0xd8, 0xbf, 0x99, 0x96, 0xd1, 0xa7, 0xaa, 0x5d, 0x71, 0x33, + 0x2d, 0xa3, 0xef, 0xdd, 0x0c, 0x29, 0x9c, 0x45, 0xa1, 0x44, 0xb7, 0x28, 0x94, 0x80, 0x8c, 0xd8, + 0x1a, 0x32, 0xfe, 0xe1, 0xc0, 0x6e, 0xc0, 0x44, 0xd5, 0xec, 0xbc, 0xcd, 0xe3, 0x28, 0x81, 0xa4, + 0xdf, 0xfb, 0x79, 0xd2, 0xfb, 0x75, 0xdf, 0x16, 0x8e, 0x41, 0x9c, 0x95, 0x14, 0xc9, 0xeb, 0xde, + 0xd1, 0xc3, 0x75, 0xaf, 0x0d, 0xad, 0x1a, 0x9d, 0x61, 0x97, 0x5e, 0xaa, 0xd8, 0x66, 0x2f, 0xd5, + 0x49, 0x8c, 0xe4, 0xab, 0xfc, 0xc8, 0x83, 0x9c, 0xd6, 0x81, 0xa6, 0x83, 0xba, 0x08, 0x76, 0x82, + 0xac, 0x85, 0x87, 0x80, 0xf7, 0x73, 0xdd, 0x9d, 0x4d, 0xe5, 0x14, 0xcb, 0x95, 0x24, 0xc9, 0xa3, + 0x05, 0x46, 0xf8, 0x37, 0x66, 0x24, 0xba, 0x8e, 0x91, 0xd8, 0x06, 0x8c, 0xc4, 0xb7, 0xc2, 0xc8, + 0xef, 0x1c, 0xc8, 0x84, 0xa1, 0xef, 0xe0, 0xcb, 0xa8, 0x0c, 0x12, 0x43, 0x0b, 0x76, 0xd1, 0xf3, + 0x55, 0x9f, 0x8a, 0xfe, 0x97, 0xf0, 0xb8, 0xa4, 0x3e, 0x85, 0x56, 0xff, 0x0a, 0xd6, 0x29, 0xd6, + 0x4d, 0xc9, 0x8d, 0x74, 0x93, 0xf9, 0x18, 0xa4, 0x59, 0xc3, 0xaa, 0xb7, 0x9c, 0x4b, 0x5b, 0xc8, + 0x81, 0xf8, 0x90, 0x0c, 0x44, 0x8e, 0xf2, 0xcf, 0x0c, 0xe5, 0x02, 0xdc, 0x0f, 0x2e, 0x9e, 0x01, + 0xdf, 0x22, 0x67, 0x7f, 0x6d, 0x3e, 0xbc, 0xf6, 0xb7, 0x60, 0xc7, 0xfd, 0x88, 0x11, 0xf2, 0x00, + 0x20, 0x4f, 0x69, 0x16, 0x5b, 0x54, 0x0f, 0xcd, 0x10, 0x7d, 0x74, 0x61, 0xcb, 0x19, 0x59, 0xd0, + 0xaf, 0x18, 0xcf, 0x66, 0xd9, 0x7c, 0xfe, 0x0b, 0x07, 0xe2, 0xec, 0x25, 0x79, 0x0c, 0xe4, 0xb3, + 0xc6, 0x69, 0xa3, 0xda, 0x3c, 0xaf, 0x69, 0x35, 0xad, 0xa1, 0x9d, 0x7e, 0xa7, 0x5d, 0x54, 0x9f, + 0x34, 0xcf, 0x6b, 0x67, 0xf5, 0x6a, 0x45, 0xfb, 0x5a, 0xab, 0x3e, 0xc9, 0x46, 0xa4, 0x07, 0xd7, + 0x37, 0x85, 0xdd, 0x39, 0x80, 0x20, 0x02, 0xc0, 0xe2, 0xc8, 0x64, 0x96, 0x93, 0x92, 0xd7, 0x37, + 0x85, 0x18, 0x19, 0x0b, 0x79, 0xb0, 0xcb, 0x3c, 0x0d, 0xfd, 0x87, 0x67, 0xf5, 0x6a, 0x2d, 0xcb, + 0x4b, 0xe9, 0xeb, 0x9b, 0xc2, 0x8e, 0x6b, 0x06, 0x91, 0xd4, 0x19, 0x65, 0x91, 0x64, 0x2c, 0xc5, + 0x5e, 0xfc, 0x9a, 0x8f, 0x94, 0xeb, 0xaf, 0x6e, 0xf3, 0xdc, 0xeb, 0xdb, 0x3c, 0xf7, 0xd7, 0x6d, + 0x9e, 0xfb, 0xe9, 0x2e, 0x1f, 0x79, 0x7d, 0x97, 0x8f, 0xfc, 0x79, 0x97, 0x8f, 0x5c, 0x3c, 0xee, + 0x21, 0xe7, 0x72, 0xd4, 0x26, 0x57, 0x57, 0x34, 0xb0, 0x3d, 0xc0, 0xb6, 0xfb, 0xf3, 0xc8, 0xee, + 0xf4, 0x8b, 0xcf, 0x8b, 0xe4, 0xaf, 0xcc, 0x17, 0xc7, 0x8f, 0x42, 0xff, 0xb1, 0x9c, 0xc9, 0x10, + 0xda, 0xed, 0x04, 0x7d, 0x61, 0x8f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x23, 0x2c, 0x45, 0x4d, + 0x87, 0x0d, 0x00, 0x00, } func (m *MsgConnectionOpenInit) Marshal() (dAtA []byte, err error) { @@ -649,6 +656,13 @@ func (m *MsgConnectionOpenInit) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Signer) i = encodeVarintConnection(dAtA, i, uint64(len(m.Signer))) i-- + dAtA[i] = 0x2a + } + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarintConnection(dAtA, i, uint64(len(m.Version))) + i-- dAtA[i] = 0x22 } { @@ -703,7 +717,7 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Signer) i = encodeVarintConnection(dAtA, i, uint64(len(m.Signer))) i-- - dAtA[i] = 0x5a + dAtA[i] = 0x62 } { size, err := m.ConsensusHeight.MarshalToSizedBuffer(dAtA[:i]) @@ -714,27 +728,27 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x52 + dAtA[i] = 0x5a if len(m.ProofConsensus) > 0 { i -= len(m.ProofConsensus) copy(dAtA[i:], m.ProofConsensus) i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofConsensus))) i-- - dAtA[i] = 0x4a + dAtA[i] = 0x52 } if len(m.ProofClient) > 0 { i -= len(m.ProofClient) copy(dAtA[i:], m.ProofClient) i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofClient))) i-- - dAtA[i] = 0x42 + dAtA[i] = 0x4a } if len(m.ProofInit) > 0 { i -= len(m.ProofInit) copy(dAtA[i:], m.ProofInit) i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofInit))) i-- - dAtA[i] = 0x3a + dAtA[i] = 0x42 } { size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) @@ -745,14 +759,14 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a if len(m.CounterpartyVersions) > 0 { for iNdEx := len(m.CounterpartyVersions) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.CounterpartyVersions[iNdEx]) copy(dAtA[i:], m.CounterpartyVersions[iNdEx]) i = encodeVarintConnection(dAtA, i, uint64(len(m.CounterpartyVersions[iNdEx]))) i-- - dAtA[i] = 0x2a + dAtA[i] = 0x32 } } { @@ -764,7 +778,7 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x22 + dAtA[i] = 0x2a if m.ClientState != nil { { size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) @@ -775,6 +789,13 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x22 + } + if len(m.ProvedId) > 0 { + i -= len(m.ProvedId) + copy(dAtA[i:], m.ProvedId) + i = encodeVarintConnection(dAtA, i, uint64(len(m.ProvedId))) + i-- dAtA[i] = 0x1a } if len(m.ConnectionId) > 0 { @@ -819,7 +840,7 @@ func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Signer) i = encodeVarintConnection(dAtA, i, uint64(len(m.Signer))) i-- - dAtA[i] = 0x4a + dAtA[i] = 0x52 } { size, err := m.ConsensusHeight.MarshalToSizedBuffer(dAtA[:i]) @@ -830,27 +851,27 @@ func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x42 + dAtA[i] = 0x4a if len(m.ProofConsensus) > 0 { i -= len(m.ProofConsensus) copy(dAtA[i:], m.ProofConsensus) i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofConsensus))) i-- - dAtA[i] = 0x3a + dAtA[i] = 0x42 } if len(m.ProofClient) > 0 { i -= len(m.ProofClient) copy(dAtA[i:], m.ProofClient) i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofClient))) i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a } if len(m.ProofTry) > 0 { i -= len(m.ProofTry) copy(dAtA[i:], m.ProofTry) i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofTry))) i-- - dAtA[i] = 0x2a + dAtA[i] = 0x32 } { size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) @@ -861,7 +882,7 @@ func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x22 + dAtA[i] = 0x2a if m.ClientState != nil { { size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) @@ -872,13 +893,20 @@ func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintConnection(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x22 } if len(m.Version) > 0 { i -= len(m.Version) copy(dAtA[i:], m.Version) i = encodeVarintConnection(dAtA, i, uint64(len(m.Version))) i-- + dAtA[i] = 0x1a + } + if len(m.CounterpartyConnectionId) > 0 { + i -= len(m.CounterpartyConnectionId) + copy(dAtA[i:], m.CounterpartyConnectionId) + i = encodeVarintConnection(dAtA, i, uint64(len(m.CounterpartyConnectionId))) + i-- dAtA[i] = 0x12 } if len(m.ConnectionId) > 0 { @@ -1244,6 +1272,10 @@ func (m *MsgConnectionOpenInit) Size() (n int) { } l = m.Counterparty.Size() n += 1 + l + sovConnection(uint64(l)) + l = len(m.Version) + if l > 0 { + n += 1 + l + sovConnection(uint64(l)) + } l = len(m.Signer) if l > 0 { n += 1 + l + sovConnection(uint64(l)) @@ -1265,6 +1297,10 @@ func (m *MsgConnectionOpenTry) Size() (n int) { if l > 0 { n += 1 + l + sovConnection(uint64(l)) } + l = len(m.ProvedId) + if l > 0 { + n += 1 + l + sovConnection(uint64(l)) + } if m.ClientState != nil { l = m.ClientState.Size() n += 1 + l + sovConnection(uint64(l)) @@ -1310,6 +1346,10 @@ func (m *MsgConnectionOpenAck) Size() (n int) { if l > 0 { n += 1 + l + sovConnection(uint64(l)) } + l = len(m.CounterpartyConnectionId) + if l > 0 { + n += 1 + l + sovConnection(uint64(l)) + } l = len(m.Version) if l > 0 { n += 1 + l + sovConnection(uint64(l)) @@ -1621,6 +1661,38 @@ func (m *MsgConnectionOpenInit) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConnection + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConnection + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthConnection + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) } @@ -1770,6 +1842,38 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { m.ConnectionId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProvedId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConnection + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConnection + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthConnection + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProvedId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ClientState", wireType) } @@ -1805,7 +1909,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 4: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", wireType) } @@ -1838,7 +1942,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyVersions", wireType) } @@ -1870,7 +1974,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { } m.CounterpartyVersions = append(m.CounterpartyVersions, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType) } @@ -1903,7 +2007,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 7: + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofInit", wireType) } @@ -1937,7 +2041,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { m.ProofInit = []byte{} } iNdEx = postIndex - case 8: + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofClient", wireType) } @@ -1971,7 +2075,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { m.ProofClient = []byte{} } iNdEx = postIndex - case 9: + case 10: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofConsensus", wireType) } @@ -2005,7 +2109,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { m.ProofConsensus = []byte{} } iNdEx = postIndex - case 10: + case 11: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHeight", wireType) } @@ -2038,7 +2142,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 11: + case 12: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) } @@ -2156,6 +2260,38 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { m.ConnectionId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyConnectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConnection + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConnection + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthConnection + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CounterpartyConnectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) } @@ -2187,7 +2323,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { } m.Version = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ClientState", wireType) } @@ -2223,7 +2359,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 4: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType) } @@ -2256,7 +2392,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofTry", wireType) } @@ -2290,7 +2426,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { m.ProofTry = []byte{} } iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofClient", wireType) } @@ -2324,7 +2460,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { m.ProofClient = []byte{} } iNdEx = postIndex - case 7: + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ProofConsensus", wireType) } @@ -2358,7 +2494,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { m.ProofConsensus = []byte{} } iNdEx = postIndex - case 8: + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHeight", wireType) } @@ -2391,7 +2527,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 9: + case 10: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) } diff --git a/x/ibc/03-connection/types/errors.go b/x/ibc/03-connection/types/errors.go index 41ff557637a6..107a0e087c17 100644 --- a/x/ibc/03-connection/types/errors.go +++ b/x/ibc/03-connection/types/errors.go @@ -15,4 +15,5 @@ var ( ErrInvalidConnection = sdkerrors.Register(SubModuleName, 8, "invalid connection") ErrInvalidVersion = sdkerrors.Register(SubModuleName, 9, "invalid connection version") ErrVersionNegotiationFailed = sdkerrors.Register(SubModuleName, 10, "connection version negotiation failed") + ErrInvalidConnectionIdentifier = sdkerrors.Register(SubModuleName, 11, "invalid connection identifier") ) diff --git a/x/ibc/03-connection/types/msgs.go b/x/ibc/03-connection/types/msgs.go index 8f70559dbc35..8956be25d486 100644 --- a/x/ibc/03-connection/types/msgs.go +++ b/x/ibc/03-connection/types/msgs.go @@ -17,13 +17,14 @@ var _ sdk.Msg = &MsgConnectionOpenInit{} func NewMsgConnectionOpenInit( connectionID, clientID, counterpartyConnectionID, counterpartyClientID string, counterpartyPrefix commitmenttypes.MerklePrefix, - signer sdk.AccAddress, + version string, signer sdk.AccAddress, ) *MsgConnectionOpenInit { counterparty := NewCounterparty(counterpartyClientID, counterpartyConnectionID, counterpartyPrefix) return &MsgConnectionOpenInit{ ConnectionId: connectionID, ClientId: clientID, Counterparty: counterparty, + Version: version, Signer: signer.String(), } } @@ -38,7 +39,7 @@ func (msg MsgConnectionOpenInit) Type() string { return "connection_open_init" } -// ValidateBasic implements sdk.Msg +// ValidateBasic implements sdk.Msg. func (msg MsgConnectionOpenInit) ValidateBasic() error { if err := host.ConnectionIdentifierValidator(msg.ConnectionId); err != nil { return sdkerrors.Wrap(err, "invalid connection ID") @@ -46,6 +47,11 @@ func (msg MsgConnectionOpenInit) ValidateBasic() error { if err := host.ClientIdentifierValidator(msg.ClientId); err != nil { return sdkerrors.Wrap(err, "invalid client ID") } + if msg.Version != "" { + if err := ValidateVersion(msg.Version); err != nil { + return sdkerrors.Wrap(err, "basic validation of the provided version failed") + } + } if msg.Signer == "" { return sdkerrors.ErrInvalidAddress } @@ -71,7 +77,7 @@ var _ sdk.Msg = &MsgConnectionOpenTry{} // NewMsgConnectionOpenTry creates a new MsgConnectionOpenTry instance //nolint:interfacer func NewMsgConnectionOpenTry( - connectionID, clientID, counterpartyConnectionID, + connectionID, provedID, clientID, counterpartyConnectionID, counterpartyClientID string, counterpartyClient exported.ClientState, counterpartyPrefix commitmenttypes.MerklePrefix, counterpartyVersions []string, proofInit, proofClient, proofConsensus []byte, @@ -81,6 +87,7 @@ func NewMsgConnectionOpenTry( csAny, _ := clienttypes.PackClientState(counterpartyClient) return &MsgConnectionOpenTry{ ConnectionId: connectionID, + ProvedId: provedID, ClientId: clientID, ClientState: csAny, Counterparty: counterparty, @@ -109,6 +116,9 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error { if err := host.ConnectionIdentifierValidator(msg.ConnectionId); err != nil { return sdkerrors.Wrap(err, "invalid connection ID") } + if msg.ProvedId != "" && msg.ProvedId != msg.ConnectionId { + return sdkerrors.Wrap(ErrInvalidConnectionIdentifier, "proved identifier must be empty or equal to connection identifier") + } if err := host.ClientIdentifierValidator(msg.ClientId); err != nil { return sdkerrors.Wrap(err, "invalid client ID") } @@ -181,34 +191,29 @@ var _ sdk.Msg = &MsgConnectionOpenAck{} // NewMsgConnectionOpenAck creates a new MsgConnectionOpenAck instance //nolint:interfacer func NewMsgConnectionOpenAck( - connectionID string, counterpartyClient exported.ClientState, + connectionID, counterpartyConnectionID string, counterpartyClient exported.ClientState, proofTry, proofClient, proofConsensus []byte, proofHeight, consensusHeight clienttypes.Height, version string, signer sdk.AccAddress, ) *MsgConnectionOpenAck { csAny, _ := clienttypes.PackClientState(counterpartyClient) return &MsgConnectionOpenAck{ - ConnectionId: connectionID, - ClientState: csAny, - ProofTry: proofTry, - ProofClient: proofClient, - ProofConsensus: proofConsensus, - ProofHeight: proofHeight, - ConsensusHeight: consensusHeight, - Version: version, - Signer: signer.String(), + ConnectionId: connectionID, + CounterpartyConnectionId: counterpartyConnectionID, + ClientState: csAny, + ProofTry: proofTry, + ProofClient: proofClient, + ProofConsensus: proofConsensus, + ProofHeight: proofHeight, + ConsensusHeight: consensusHeight, + Version: version, + Signer: signer.String(), } } // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces func (msg MsgConnectionOpenAck) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var clientState exported.ClientState - err := unpacker.UnpackAny(msg.ClientState, &clientState) - if err != nil { - return err - } - - return nil + return unpacker.UnpackAny(msg.ClientState, new(exported.ClientState)) } // Route implements sdk.Msg @@ -226,6 +231,9 @@ func (msg MsgConnectionOpenAck) ValidateBasic() error { if err := host.ConnectionIdentifierValidator(msg.ConnectionId); err != nil { return sdkerrors.Wrap(err, "invalid connection ID") } + if err := host.ConnectionIdentifierValidator(msg.CounterpartyConnectionId); err != nil { + return sdkerrors.Wrap(err, "invalid counterparty connection ID") + } if err := ValidateVersion(msg.Version); err != nil { return err } diff --git a/x/ibc/03-connection/types/msgs_test.go b/x/ibc/03-connection/types/msgs_test.go index 00cd17e23fbf..e1bed97aa907 100644 --- a/x/ibc/03-connection/types/msgs_test.go +++ b/x/ibc/03-connection/types/msgs_test.go @@ -67,37 +67,31 @@ func TestMsgTestSuite(t *testing.T) { func (suite *MsgTestSuite) TestNewMsgConnectionOpenInit() { prefix := commitmenttypes.NewMerklePrefix([]byte("storePrefixKey")) signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") - - testMsgs := []*types.MsgConnectionOpenInit{ - types.NewMsgConnectionOpenInit("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", prefix, signer), - types.NewMsgConnectionOpenInit("ibcconntest", "test/iris", "connectiontotest", "clienttotest", prefix, signer), - types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "test/conn1", "clienttotest", prefix, signer), - types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "test/conn1", prefix, signer), - types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", emptyPrefix, signer), - types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", prefix, nil), - types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", prefix, signer), - } + // empty versions are considered valid, the default compatible versions + // will be used in protocol. + version := "" var testCases = []struct { + name string msg *types.MsgConnectionOpenInit expPass bool - errMsg string }{ - {testMsgs[0], false, "invalid connection ID"}, - {testMsgs[1], false, "invalid client ID"}, - {testMsgs[2], false, "invalid counterparty client ID"}, - {testMsgs[3], false, "invalid counterparty connection ID"}, - {testMsgs[4], false, "empty counterparty prefix"}, - {testMsgs[5], false, "empty singer"}, - {testMsgs[6], true, "success"}, + {"invalid connection ID", types.NewMsgConnectionOpenInit("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", prefix, version, signer), false}, + {"invalid client ID", types.NewMsgConnectionOpenInit("ibcconntest", "test/iris", "connectiontotest", "clienttotest", prefix, version, signer), false}, + {"invalid counterparty client ID", types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "test/conn1", "clienttotest", prefix, version, signer), false}, + {"invalid counterparty connection ID", types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "test/conn1", prefix, version, signer), false}, + {"empty counterparty prefix", types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", emptyPrefix, version, signer), false}, + {"supplied version fails basic validation", types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", prefix, "bad version", signer), false}, + {"empty singer", types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", prefix, version, nil), false}, + {"success", types.NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", prefix, version, signer), true}, } - for i, tc := range testCases { + for _, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - suite.Require().NoError(err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, tc.name) } else { - suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, tc.name) } } } @@ -121,57 +115,39 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() { invalidClient := ibctmtypes.NewClientState( chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), &ibctesting.UpgradePath, false, false, ) - - testMsgs := []*types.MsgConnectionOpenTry{ - types.NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "test/iris", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "ibc/test", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "test/conn1", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", nil, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - {"ibcconntest", "clienttotesta", invalidAny, counterparty, []string{ibctesting.ConnectionVersion}, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, emptyPrefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, nil), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{"(invalid version)"}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), - } + provedID := "" var testCases = []struct { + name string msg *types.MsgConnectionOpenTry expPass bool - errMsg string }{ - {testMsgs[0], false, "invalid connection ID"}, - {testMsgs[1], false, "invalid client ID"}, - {testMsgs[2], false, "invalid counterparty connection ID"}, - {testMsgs[3], false, "invalid counterparty client ID"}, - {testMsgs[4], false, "invalid nil counterparty client"}, - {testMsgs[5], false, "invalid client unpacking"}, - {testMsgs[6], false, "counterparty failed Validate"}, - {testMsgs[7], false, "empty counterparty prefix"}, - {testMsgs[8], false, "empty counterpartyVersions"}, - {testMsgs[9], false, "empty proofInit"}, - {testMsgs[10], false, "empty proofClient"}, - {testMsgs[11], false, "empty proofConsensus"}, - {testMsgs[12], false, "invalid proofHeight"}, - {testMsgs[13], false, "invalid consensusHeight"}, - {testMsgs[14], false, "empty singer"}, - {testMsgs[15], true, "success"}, - {testMsgs[16], false, "invalid version"}, + {"invalid connection ID", types.NewMsgConnectionOpenTry("test/conn1", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"invalid connection ID", types.NewMsgConnectionOpenTry("ibcconntest", "test/conn1", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"invalid client ID", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "test/iris", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"invalid counterparty connection ID", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "ibc/test", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"invalid counterparty client ID", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "test/conn1", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"invalid nil counterparty client", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", nil, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"invalid client unpacking", &types.MsgConnectionOpenTry{"ibcconntest", provedID, "clienttotesta", invalidAny, counterparty, []string{ibctesting.ConnectionVersion}, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, false}, + {"counterparty failed Validate", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"empty counterparty prefix", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, emptyPrefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"empty counterpartyVersions", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"empty proofInit", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"empty proofClient", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, signer), false}, + {"empty proofConsensus", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, signer), false}, + {"invalid proofHeight", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, signer), false}, + {"invalid consensusHeight", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), signer), false}, + {"empty singer", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, nil), false}, + {"success", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), true}, + {"invalid version", types.NewMsgConnectionOpenTry("ibcconntest", provedID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{"(invalid version)"}, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, } - for i, tc := range testCases { + for _, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) + suite.Require().NoError(err, tc.name) } else { - suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, tc.name) } } } @@ -192,46 +168,34 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() { invalidClient := ibctmtypes.NewClientState( chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), &ibctesting.UpgradePath, false, false, ) + connectionID := "ibcconntest" - testMsgs := []*types.MsgConnectionOpenAck{ - types.NewMsgConnectionOpenAck("test/conn1", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", nil, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - {"ibcconntest", ibctesting.ConnectionVersion, invalidAny, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, - types.NewMsgConnectionOpenAck("ibcconntest", invalidClient, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), ibctesting.ConnectionVersion, signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, "", signer), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, nil), - types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), - } var testCases = []struct { + name string msg *types.MsgConnectionOpenAck expPass bool - errMsg string }{ - {testMsgs[0], false, "invalid connection ID"}, - {testMsgs[1], false, "invalid nil counterparty client"}, - {testMsgs[2], false, "invalid unpacking counterparty client"}, - {testMsgs[3], false, "counterparty client failed Validate"}, - {testMsgs[4], false, "empty proofTry"}, - {testMsgs[5], false, "empty proofClient"}, - {testMsgs[6], false, "empty proofConsensus"}, - {testMsgs[7], false, "invalid proofHeight"}, - {testMsgs[8], false, "invalid consensusHeight"}, - {testMsgs[9], false, "invalid version"}, - {testMsgs[10], false, "empty signer"}, - {testMsgs[11], true, "success"}, + {"invalid connection ID", types.NewMsgConnectionOpenAck("test/conn1", connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"invalid counterparty connection ID", types.NewMsgConnectionOpenAck(connectionID, "test/conn1", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"invalid nil counterparty client", types.NewMsgConnectionOpenAck(connectionID, connectionID, nil, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"invalid unpacking counterparty client", &types.MsgConnectionOpenAck{connectionID, connectionID, ibctesting.ConnectionVersion, invalidAny, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, false}, + {"counterparty client failed Validate", types.NewMsgConnectionOpenAck(connectionID, connectionID, invalidClient, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"empty proofTry", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"empty proofClient", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"empty proofConsensus", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"invalid proofHeight", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"invalid consensusHeight", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), ibctesting.ConnectionVersion, signer), false}, + {"invalid version", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, "", signer), false}, + {"empty signer", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, nil), false}, + {"success", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), true}, } - for i, tc := range testCases { + for _, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) + suite.Require().NoError(err, tc.name) } else { - suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, tc.name) } } } diff --git a/x/ibc/03-connection/types/version.go b/x/ibc/03-connection/types/version.go index e6c13cec015f..7134719485d9 100644 --- a/x/ibc/03-connection/types/version.go +++ b/x/ibc/03-connection/types/version.go @@ -180,12 +180,16 @@ func FindSupportedVersion(version Version, supportedVersions []Version) (Version // // CONTRACT: PickVersion must only provide a version that is in the // intersection of the supported versions and the counterparty versions. -func PickVersion(encodedCounterpartyVersions []string) (string, error) { +func PickVersion(encodedSupportedVersions, encodedCounterpartyVersions []string) (string, error) { + supportedVersions, err := DecodeVersions(encodedSupportedVersions) + if err != nil { + return "", sdkerrors.Wrapf(err, "failed to unmarshal supported versions (%s) when attempting to pick compatible version", encodedSupportedVersions) + } + counterpartyVersions, err := DecodeVersions(encodedCounterpartyVersions) if err != nil { return "", sdkerrors.Wrapf(err, "failed to unmarshal counterparty versions (%s) when attempting to pick compatible version", encodedCounterpartyVersions) } - supportedVersions := GetCompatibleVersions() for _, supportedVersion := range supportedVersions { // check if the source version is supported by the counterparty diff --git a/x/ibc/03-connection/types/version_test.go b/x/ibc/03-connection/types/version_test.go index a8e5aeeed341..ed15354fbe0c 100644 --- a/x/ibc/03-connection/types/version_test.go +++ b/x/ibc/03-connection/types/version_test.go @@ -120,22 +120,27 @@ func TestFindSupportedVersion(t *testing.T) { func TestPickVersion(t *testing.T) { testCases := []struct { name string + supportedVersions []types.Version counterpartyVersions []types.Version expVer types.Version expPass bool }{ - {"valid default ibc version", types.GetCompatibleVersions(), types.DefaultIBCVersion, true}, - {"valid version in counterparty versions", []types.Version{types.NewVersion("version1", nil), types.NewVersion("2.0.0", []string{"ORDER_UNORDERED-ZK"}), types.DefaultIBCVersion}, types.DefaultIBCVersion, true}, - {"valid identifier match but empty feature set not allowed", []types.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"DAG", "ORDERED-ZK", "UNORDERED-zk]"})}, types.NewVersion(types.DefaultIBCVersionIdentifier, nil), false}, - {"empty counterparty versions", []types.Version{}, types.Version{}, false}, - {"non-matching counterparty versions", []types.Version{types.NewVersion("2.0.0", nil)}, types.Version{}, false}, + {"valid default ibc version", types.GetCompatibleVersions(), types.GetCompatibleVersions(), types.DefaultIBCVersion, true}, + {"valid version in counterparty versions", types.GetCompatibleVersions(), []types.Version{types.NewVersion("version1", nil), types.NewVersion("2.0.0", []string{"ORDER_UNORDERED-ZK"}), types.DefaultIBCVersion}, types.DefaultIBCVersion, true}, + {"valid identifier match but empty feature set not allowed", types.GetCompatibleVersions(), []types.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"DAG", "ORDERED-ZK", "UNORDERED-zk]"})}, types.NewVersion(types.DefaultIBCVersionIdentifier, nil), false}, + {"empty counterparty versions", types.GetCompatibleVersions(), []types.Version{}, types.Version{}, false}, + {"non-matching counterparty versions", types.GetCompatibleVersions(), []types.Version{types.NewVersion("2.0.0", nil)}, types.Version{}, false}, + {"non-matching counterparty versions (uses ordered channels only) contained in supported versions (uses unordered channels only)", []types.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_UNORDERED"})}, []types.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED"})}, types.Version{}, false}, } for i, tc := range testCases { + encodedSupportedVersions, err := types.EncodeVersions(tc.supportedVersions) + require.NoError(t, err) + encodedCounterpartyVersions, err := types.EncodeVersions(tc.counterpartyVersions) require.NoError(t, err) - encodedVersion, err := types.PickVersion(encodedCounterpartyVersions) + encodedVersion, err := types.PickVersion(encodedSupportedVersions, encodedCounterpartyVersions) if tc.expPass { require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) diff --git a/x/ibc/testing/chain.go b/x/ibc/testing/chain.go index 31181c7ee15b..326f39137dbe 100644 --- a/x/ibc/testing/chain.go +++ b/x/ibc/testing/chain.go @@ -50,8 +50,9 @@ const ( UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3 MaxClockDrift time.Duration = time.Second * 10 - DefaultChannelVersion = ibctransfertypes.Version - InvalidID = "IDisInvalid" + DefaultChannelVersion = ibctransfertypes.Version + DefaultOpenInitVersion = "" + InvalidID = "IDisInvalid" ConnectionIDPrefix = "conn" ChannelIDPrefix = "chan" @@ -572,7 +573,7 @@ func (chain *TestChain) ConnectionOpenInit( msg := connectiontypes.NewMsgConnectionOpenInit( connection.ID, connection.ClientID, counterpartyConnection.ID, connection.CounterpartyClientID, - counterparty.GetPrefix(), + counterparty.GetPrefix(), DefaultOpenInitVersion, chain.SenderAccount.GetAddress(), ) return chain.sendMsgs(msg) @@ -591,7 +592,7 @@ func (chain *TestChain) ConnectionOpenTry( proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID) msg := connectiontypes.NewMsgConnectionOpenTry( - connection.ID, connection.ClientID, + connection.ID, connection.ID, connection.ClientID, counterpartyConnection.ID, counterpartyConnection.ClientID, counterpartyClient, counterparty.GetPrefix(), []string{ConnectionVersion}, proofInit, proofClient, proofConsensus, @@ -614,7 +615,7 @@ func (chain *TestChain) ConnectionOpenAck( proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID) msg := connectiontypes.NewMsgConnectionOpenAck( - connection.ID, counterpartyClient, + connection.ID, counterpartyConnection.ID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight, consensusHeight, ConnectionVersion,