Skip to content

Commit 432ba30

Browse files
Flexible Connection Handshake Selection (#7427)
* update connopeninit Update ConnOpenInit to reflect changes in cosmos/ibc#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 <[email protected]>
1 parent 53f8aec commit 432ba30

File tree

13 files changed

+657
-312
lines changed

13 files changed

+657
-312
lines changed

proto/ibc/core/connection/v1/connection.proto

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ message MsgConnectionOpenInit {
1717
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
1818
string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""];
1919
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
20-
string signer = 4;
20+
string version = 4;
21+
string signer = 5;
2122
}
2223

2324
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a
@@ -28,21 +29,22 @@ message MsgConnectionOpenTry {
2829

2930
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
3031
string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""];
31-
google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""];
32-
Counterparty counterparty = 4 [(gogoproto.nullable) = false];
33-
repeated string counterparty_versions = 5 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
34-
ibc.core.client.v1.Height proof_height = 6
32+
string proved_id = 3 [(gogoproto.moretags) = "yaml:\"proved_id\""];
33+
google.protobuf.Any client_state = 4 [(gogoproto.moretags) = "yaml:\"client_state\""];
34+
Counterparty counterparty = 5 [(gogoproto.nullable) = false];
35+
repeated string counterparty_versions = 6 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
36+
ibc.core.client.v1.Height proof_height = 7
3537
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
3638
// proof of the initialization the connection on Chain A: `UNITIALIZED ->
3739
// INIT`
38-
bytes proof_init = 7 [(gogoproto.moretags) = "yaml:\"proof_init\""];
40+
bytes proof_init = 8 [(gogoproto.moretags) = "yaml:\"proof_init\""];
3941
// proof of client state included in message
40-
bytes proof_client = 8 [(gogoproto.moretags) = "yaml:\"proof_client\""];
42+
bytes proof_client = 9 [(gogoproto.moretags) = "yaml:\"proof_client\""];
4143
// proof of client consensus state
42-
bytes proof_consensus = 9 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
43-
ibc.core.client.v1.Height consensus_height = 10
44+
bytes proof_consensus = 10 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
45+
ibc.core.client.v1.Height consensus_height = 11
4446
[(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false];
45-
string signer = 11;
47+
string signer = 12;
4648
}
4749

4850
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to
@@ -51,21 +53,22 @@ message MsgConnectionOpenAck {
5153
option (gogoproto.equal) = false;
5254
option (gogoproto.goproto_getters) = false;
5355

54-
string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
55-
string version = 2;
56-
google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""];
57-
ibc.core.client.v1.Height proof_height = 4
56+
string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
57+
string counterparty_connection_id = 2 [(gogoproto.moretags) = "yaml:\"counterparty_connection_id\""];
58+
string version = 3;
59+
google.protobuf.Any client_state = 4 [(gogoproto.moretags) = "yaml:\"client_state\""];
60+
ibc.core.client.v1.Height proof_height = 5
5861
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
5962
// proof of the initialization the connection on Chain B: `UNITIALIZED ->
6063
// TRYOPEN`
61-
bytes proof_try = 5 [(gogoproto.moretags) = "yaml:\"proof_try\""];
64+
bytes proof_try = 6 [(gogoproto.moretags) = "yaml:\"proof_try\""];
6265
// proof of client state included in message
63-
bytes proof_client = 6 [(gogoproto.moretags) = "yaml:\"proof_client\""];
66+
bytes proof_client = 7 [(gogoproto.moretags) = "yaml:\"proof_client\""];
6467
// proof of client consensus state
65-
bytes proof_consensus = 7 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
66-
ibc.core.client.v1.Height consensus_height = 8
68+
bytes proof_consensus = 8 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
69+
ibc.core.client.v1.Height consensus_height = 9
6770
[(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false];
68-
string signer = 9;
71+
string signer = 10;
6972
}
7073

7174
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to

x/ibc/03-connection/client/cli/tx.go

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@ import (
1616
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
1717
)
1818

19+
const (
20+
flagVersionIdentifier = "version-identifier"
21+
flagVersionFeatures = "version-features"
22+
flagProvedID = "proved-id"
23+
)
24+
1925
// NewConnectionOpenInitCmd defines the command to initialize a connection on
2026
// chain A with a given counterparty chain B
2127
func NewConnectionOpenInitCmd() *cobra.Command {
2228
cmd := &cobra.Command{
2329
Use: "open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]",
2430
Short: "Initialize connection on chain A",
25-
Long: "Initialize a connection on chain A with a given counterparty chain B",
31+
Long: `Initialize a connection on chain A with a given counterparty chain B.
32+
- 'version-identifier' flag can be a single pre-selected version identifier to be used in the handshake.
33+
- 'version-features' flag can be a list of features separated by commas to accompany the version identifier.`,
2634
Example: fmt.Sprintf(
27-
"%s tx %s %s open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]",
35+
"%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\"",
2836
version.AppName, host.ModuleName, types.SubModuleName,
2937
),
3038
Args: cobra.ExactArgs(5),
@@ -45,9 +53,27 @@ func NewConnectionOpenInitCmd() *cobra.Command {
4553
return err
4654
}
4755

56+
var encodedVersion string
57+
versionIdentifier, _ := cmd.Flags().GetString(flagVersionIdentifier)
58+
59+
if versionIdentifier != "" {
60+
var features []string
61+
62+
versionFeatures, _ := cmd.Flags().GetString(flagVersionFeatures)
63+
if versionFeatures != "" {
64+
features = strings.Split(versionFeatures, ",")
65+
}
66+
67+
version := types.NewVersion(versionIdentifier, features)
68+
encodedVersion, err = version.Encode()
69+
if err != nil {
70+
return err
71+
}
72+
}
73+
4874
msg := types.NewMsgConnectionOpenInit(
4975
connectionID, clientID, counterpartyConnectionID, counterpartyClientID,
50-
counterpartyPrefix, clientCtx.GetFromAddress(),
76+
counterpartyPrefix, encodedVersion, clientCtx.GetFromAddress(),
5177
)
5278

5379
if err := msg.ValidateBasic(); err != nil {
@@ -58,6 +84,10 @@ func NewConnectionOpenInitCmd() *cobra.Command {
5884
},
5985
}
6086

87+
// NOTE: we should use empty default values since the user may not want to select a version
88+
// at this step in the handshake.
89+
cmd.Flags().String(flagVersionIdentifier, "", "version identifier to be used in the connection handshake version negotiation")
90+
cmd.Flags().String(flagVersionFeatures, "", "version features list separated by commas without spaces. The features must function with the version identifier.")
6191
flags.AddTxFlagsToCmd(cmd)
6292

6393
return cmd
@@ -87,6 +117,7 @@ func NewConnectionOpenTryCmd() *cobra.Command {
87117
}
88118

89119
connectionID := args[0]
120+
provedID, _ := cmd.Flags().GetString(flagProvedID)
90121
clientID := args[1]
91122
counterpartyConnectionID := args[2]
92123
counterpartyClientID := args[3]
@@ -129,7 +160,7 @@ func NewConnectionOpenTryCmd() *cobra.Command {
129160
}
130161

131162
msg := types.NewMsgConnectionOpenTry(
132-
connectionID, clientID, counterpartyConnectionID, counterpartyClientID,
163+
connectionID, provedID, clientID, counterpartyConnectionID, counterpartyClientID,
133164
counterpartyClient, counterpartyPrefix, []string{counterpartyVersions},
134165
proofInit, proofClient, proofConsensus, proofHeight,
135166
consensusHeight, clientCtx.GetFromAddress(),
@@ -143,6 +174,7 @@ func NewConnectionOpenTryCmd() *cobra.Command {
143174
},
144175
}
145176

177+
cmd.Flags().String(flagProvedID, "", "identifier set by the counterparty chain")
146178
flags.AddTxFlagsToCmd(cmd)
147179

148180
return cmd
@@ -152,16 +184,16 @@ func NewConnectionOpenTryCmd() *cobra.Command {
152184
// connection open attempt from chain B to chain A
153185
func NewConnectionOpenAckCmd() *cobra.Command {
154186
cmd := &cobra.Command{
155-
Use: `open-ack [connection-id] [path/to/client_state.json] [consensus-height] [proof-height]
187+
Use: `open-ack [connection-id] [counterparty-connection-id] [path/to/client_state.json] [consensus-height] [proof-height]
156188
[path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]`,
157189
Short: "relay the acceptance of a connection open attempt",
158190
Long: "Relay the acceptance of a connection open attempt from chain B to chain A",
159191
Example: fmt.Sprintf(
160-
`%s tx %s %s open-ack [connection-id] [path/to/client_state.json] [consensus-height] [proof-height]
192+
`%s tx %s %s open-ack [connection-id] [counterparty-connection-id] [path/to/client_state.json] [consensus-height] [proof-height]
161193
[path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]`,
162194
version.AppName, host.ModuleName, types.SubModuleName,
163195
),
164-
Args: cobra.ExactArgs(8),
196+
Args: cobra.ExactArgs(9),
165197
RunE: func(cmd *cobra.Command, args []string) error {
166198
clientCtx := client.GetClientContextFromCmd(cmd)
167199
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
@@ -170,40 +202,41 @@ func NewConnectionOpenAckCmd() *cobra.Command {
170202
}
171203

172204
connectionID := args[0]
205+
counterpartyConnectionID := args[1]
173206

174-
counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[1])
207+
counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[2])
175208
if err != nil {
176209
return err
177210
}
178211

179-
consensusHeight, err := clienttypes.ParseHeight(args[2])
212+
consensusHeight, err := clienttypes.ParseHeight(args[3])
180213
if err != nil {
181214
return err
182215
}
183-
proofHeight, err := clienttypes.ParseHeight(args[3])
216+
proofHeight, err := clienttypes.ParseHeight(args[4])
184217
if err != nil {
185218
return err
186219
}
187220

188-
proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[4])
221+
proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[5])
189222
if err != nil {
190223
return err
191224
}
192225

193-
proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[5])
226+
proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[6])
194227
if err != nil {
195228
return err
196229
}
197230

198-
proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[6])
231+
proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[7])
199232
if err != nil {
200233
return err
201234
}
202235

203-
version := args[7]
236+
version := args[8]
204237

205238
msg := types.NewMsgConnectionOpenAck(
206-
connectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight,
239+
connectionID, counterpartyConnectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight,
207240
consensusHeight, version, clientCtx.GetFromAddress(),
208241
)
209242

x/ibc/03-connection/handler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
// HandleMsgConnectionOpenInit defines the sdk.Handler for MsgConnectionOpenInit
1212
func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenInit) (*sdk.Result, error) {
1313
if err := k.ConnOpenInit(
14-
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty,
14+
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version,
1515
); err != nil {
1616
return nil, sdkerrors.Wrap(err, "connection handshake open init failed")
1717
}
@@ -43,7 +43,7 @@ func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg *types.Msg
4343
}
4444

4545
if err := k.ConnOpenTry(
46-
ctx, msg.ConnectionId, msg.Counterparty, msg.ClientId, targetClient,
46+
ctx, msg.ConnectionId, msg.ProvedId, msg.Counterparty, msg.ClientId, targetClient,
4747
msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
4848
msg.ProofHeight, msg.ConsensusHeight,
4949
); err != nil {
@@ -77,7 +77,7 @@ func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg *types.Msg
7777
}
7878

7979
if err := k.ConnOpenAck(
80-
ctx, msg.ConnectionId, targetClient, msg.Version,
80+
ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId,
8181
msg.ProofTry, msg.ProofClient, msg.ProofConsensus,
8282
msg.ProofHeight, msg.ConsensusHeight,
8383
); err != nil {

0 commit comments

Comments
 (0)