Skip to content

Commit

Permalink
ibc: Connection Version changed from string to proto definition (cosm…
Browse files Browse the repository at this point in the history
…os#7644)

* ibc: Version to proto Any

* change version string to struct

* various version fixes

* fix build

* reorder code

* update spec

* rename to ProtoVersionsToExported and ExportedVersionsToProto

Co-authored-by: Colin Axner <[email protected]>
Co-authored-by: colin axnér <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Oct 28, 2020
1 parent 7792ccf commit 426d195
Show file tree
Hide file tree
Showing 28 changed files with 490 additions and 508 deletions.
4 changes: 2 additions & 2 deletions proto/ibc/core/connection/v1/connection.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ message ConnectionEnd {
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
// IBC version which can be utilised to determine encodings or protocols for
// channels or packets utilising this connection
repeated string versions = 2;
repeated Version versions = 2;
// current state of the connection end.
State state = 3;
// counterparty chain associated with this connection.
Expand All @@ -35,7 +35,7 @@ message IdentifiedConnection {
string client_id = 2 [(gogoproto.moretags) = "yaml:\"client_id\""];
// IBC version which can be utilised to determine encodings or protocols for
// channels or packets utilising this connection
repeated string versions = 3;
repeated Version versions = 3;
// current state of the connection end.
State state = 4;
// counterparty chain associated with this connection.
Expand Down
6 changes: 3 additions & 3 deletions proto/ibc/core/connection/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ 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 version = 4;
Version version = 4;
string signer = 5;
}

Expand All @@ -50,7 +50,7 @@ message MsgConnectionOpenTry {
string counterparty_chosen_connection_id = 3 [(gogoproto.moretags) = "yaml:\"counterparty_chosen_connection_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\""];
repeated Version 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 ->
Expand All @@ -76,7 +76,7 @@ message MsgConnectionOpenAck {

string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
string counterparty_connection_id = 2 [(gogoproto.moretags) = "yaml:\"counterparty_connection_id\""];
string version = 3;
Version 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];
Expand Down
60 changes: 47 additions & 13 deletions x/ibc/core/03-connection/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package cli

import (
"fmt"
"io/ioutil"
"strings"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/version"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/client/utils"
Expand Down Expand Up @@ -53,7 +56,7 @@ func NewConnectionOpenInitCmd() *cobra.Command {
return err
}

var encodedVersion string
var version *types.Version
versionIdentifier, _ := cmd.Flags().GetString(flagVersionIdentifier)

if versionIdentifier != "" {
Expand All @@ -64,16 +67,12 @@ func NewConnectionOpenInitCmd() *cobra.Command {
features = strings.Split(versionFeatures, ",")
}

version := types.NewVersion(versionIdentifier, features)
encodedVersion, err = version.Encode()
if err != nil {
return err
}
version = types.NewVersion(versionIdentifier, features)
}

msg := types.NewMsgConnectionOpenInit(
connectionID, clientID, counterpartyConnectionID, counterpartyClientID,
counterpartyPrefix, encodedVersion, clientCtx.GetFromAddress(),
counterpartyPrefix, version, clientCtx.GetFromAddress(),
)

if err := msg.ValidateBasic(); err != nil {
Expand All @@ -99,9 +98,9 @@ func NewConnectionOpenTryCmd() *cobra.Command {
cmd := &cobra.Command{
Use: strings.TrimSpace(`open-try [connection-id] [client-id]
[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] [path/to/client_state.json]
[counterparty-versions] [consensus-height] [proof-height] [path/to/proof_init.json] [path/to/proof_client.json] [path/to/proof_consensus.json]`),
[path/to/counterparty_version1.json,path/to/counterparty_version2.json...] [consensus-height] [proof-height] [path/to/proof_init.json] [path/to/proof_client.json] [path/to/proof_consensus.json]`),
Short: "initiate connection handshake between two chains",
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. Provide counterparty versions separated by commas",
Example: fmt.Sprintf(
`%s tx %s %s open-try connection-id] [client-id] \
[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] [path/to/client_state.json]\
Expand Down Expand Up @@ -132,8 +131,28 @@ func NewConnectionOpenTryCmd() *cobra.Command {
return err
}

// TODO: parse strings?
counterpartyVersions := args[6]
cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

versionsStr := strings.Split(args[6], ",")
counterpartyVersions := make([]*types.Version, len(versionsStr))

for _, ver := range versionsStr {

// attempt to unmarshal version
version := &types.Version{}
if err := cdc.UnmarshalJSON([]byte(ver), version); err != nil {

// check for file path if JSON input is not provided
contents, err := ioutil.ReadFile(ver)
if err != nil {
return errors.Wrap(err, "neither JSON input nor path to .json file for version were provided")
}

if err := cdc.UnmarshalJSON(contents, version); err != nil {
return errors.Wrap(err, "error unmarshalling version file")
}
}
}

consensusHeight, err := clienttypes.ParseHeight(args[7])
if err != nil {
Expand Down Expand Up @@ -161,7 +180,7 @@ func NewConnectionOpenTryCmd() *cobra.Command {

msg := types.NewMsgConnectionOpenTry(
connectionID, provedID, clientID, counterpartyConnectionID, counterpartyClientID,
counterpartyClient, counterpartyPrefix, []string{counterpartyVersions},
counterpartyClient, counterpartyPrefix, counterpartyVersions,
proofInit, proofClient, proofConsensus, proofHeight,
consensusHeight, clientCtx.GetFromAddress(),
)
Expand Down Expand Up @@ -233,7 +252,22 @@ func NewConnectionOpenAckCmd() *cobra.Command {
return err
}

version := args[8]
cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

// attempt to unmarshal version
version := &types.Version{}
if err := cdc.UnmarshalJSON([]byte(args[8]), version); err != nil {

// check for file path if JSON input is not provided
contents, err := ioutil.ReadFile(args[8])
if err != nil {
return errors.Wrap(err, "neither JSON input nor path to .json file for version were provided")
}

if err := cdc.UnmarshalJSON(contents, version); err != nil {
return errors.Wrap(err, "error unmarshalling version file")
}
}

msg := types.NewMsgConnectionOpenAck(
connectionID, counterpartyConnectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight,
Expand Down
8 changes: 4 additions & 4 deletions x/ibc/core/03-connection/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (suite *KeeperTestSuite) TestQueryConnection() {
connB := suite.chainB.GetFirstTestConnection(clientB, clientA)

counterparty := types.NewCounterparty(clientB, connB.ID, suite.chainB.GetPrefix())
expConnection = types.NewConnectionEnd(types.INIT, clientA, counterparty, types.GetCompatibleEncodedVersions())
expConnection = types.NewConnectionEnd(types.INIT, clientA, counterparty, types.ExportedVersionsToProto(types.GetCompatibleVersions()))
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, expConnection)

req = &types.QueryConnectionRequest{
Expand Down Expand Up @@ -121,9 +121,9 @@ func (suite *KeeperTestSuite) TestQueryConnections() {
counterparty2 := types.NewCounterparty(clientB, connB1.ID, suite.chainB.GetPrefix())
counterparty3 := types.NewCounterparty(clientB1, connB2.ID, suite.chainB.GetPrefix())

conn1 := types.NewConnectionEnd(types.OPEN, clientA, counterparty1, types.GetCompatibleEncodedVersions())
conn2 := types.NewConnectionEnd(types.INIT, clientA, counterparty2, types.GetCompatibleEncodedVersions())
conn3 := types.NewConnectionEnd(types.OPEN, clientA1, counterparty3, types.GetCompatibleEncodedVersions())
conn1 := types.NewConnectionEnd(types.OPEN, clientA, counterparty1, types.ExportedVersionsToProto(types.GetCompatibleVersions()))
conn2 := types.NewConnectionEnd(types.INIT, clientA, counterparty2, types.ExportedVersionsToProto(types.GetCompatibleVersions()))
conn3 := types.NewConnectionEnd(types.OPEN, clientA1, counterparty3, types.ExportedVersionsToProto(types.GetCompatibleVersions()))

iconn1 := types.NewIdentifiedConnection(connA0.ID, conn1)
iconn2 := types.NewIdentifiedConnection(connA1.ID, conn2)
Expand Down
38 changes: 20 additions & 18 deletions x/ibc/core/03-connection/keeper/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package keeper
import (
"bytes"

"github.com/gogo/protobuf/proto"

"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand All @@ -20,24 +22,24 @@ func (k Keeper) ConnOpenInit(
connectionID, // identifier
clientID string,
counterparty types.Counterparty, // desiredCounterpartyConnectionIdentifier, counterpartyPrefix, counterpartyClientIdentifier
version string,
version *types.Version,
) error {
_, found := k.GetConnection(ctx, connectionID)
if found {
return sdkerrors.Wrap(types.ErrConnectionExists, connectionID)
}

versions := types.GetCompatibleEncodedVersions()
if version != "" {
versions := types.GetCompatibleVersions()
if version != nil {
if !types.IsSupportedVersion(version) {
return sdkerrors.Wrap(types.ErrInvalidVersion, "version is not supported")
}

versions = []string{version}
versions = []exported.Version{version}
}

// connection defines chain A's ConnectionEnd
connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, versions)
connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, types.ExportedVersionsToProto(versions))
k.SetConnection(ctx, connectionID, connection)

if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil {
Expand Down Expand Up @@ -66,7 +68,7 @@ func (k Keeper) ConnOpenTry(
counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier
clientID string, // clientID of chainA
clientState exported.ClientState, // clientState that chainA has for chainB
counterpartyVersions []string, // supported versions of chain A
counterpartyVersions []exported.Version, // supported versions of chain A
proofInit []byte, // proof that chainA stored connectionEnd in state (on ConnOpenInit)
proofClient []byte, // proof that chainA stored a light client of chainB
proofConsensus []byte, // proof that chainA stored chainB's consensus state at consensus height
Expand Down Expand Up @@ -105,7 +107,7 @@ func (k Keeper) ConnOpenTry(
// NOTE: chain A's counterparty is chain B (i.e where this code is executed)
prefix := k.GetCommitmentPrefix()
expectedCounterparty := types.NewCounterparty(clientID, counterpartyChosenConnectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes()))
expectedConnection := types.NewConnectionEnd(types.INIT, counterparty.ClientId, expectedCounterparty, counterpartyVersions)
expectedConnection := types.NewConnectionEnd(types.INIT, counterparty.ClientId, expectedCounterparty, types.ExportedVersionsToProto(counterpartyVersions))

// If connection already exists for desiredConnectionID, ensure that the existing connection's
// counterparty is chainA and connection is on INIT stage.
Expand All @@ -120,9 +122,9 @@ func (k Keeper) ConnOpenTry(
return sdkerrors.Wrap(types.ErrInvalidConnection, "cannot relay connection attempt")
}

supportedVersions := types.GetCompatibleEncodedVersions()
supportedVersions := types.GetCompatibleVersions()
if len(previousConnection.Versions) != 0 {
supportedVersions = previousConnection.Versions
supportedVersions = previousConnection.GetVersions()
}

// chain B picks a version from Chain A's available versions that is compatible
Expand All @@ -134,7 +136,7 @@ func (k Keeper) ConnOpenTry(
}

// connection defines chain B's ConnectionEnd
connection := types.NewConnectionEnd(types.TRYOPEN, clientID, counterparty, []string{version})
connection := types.NewConnectionEnd(types.TRYOPEN, clientID, counterparty, []*types.Version{version})

// Check that ChainA committed expectedConnectionEnd to its state
if err := k.VerifyConnectionState(
Expand Down Expand Up @@ -179,7 +181,7 @@ func (k Keeper) ConnOpenAck(
ctx sdk.Context,
connectionID string,
clientState exported.ClientState, // client state for chainA on chainB
encodedVersion, // version that ChainB chose in ConnOpenTry
version *types.Version, // 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
Expand Down Expand Up @@ -222,18 +224,18 @@ func (k Keeper) ConnOpenAck(
)

// if the connection is INIT then the provided version must be supproted
case connection.State == types.INIT && !types.IsSupportedVersion(encodedVersion):
case connection.State == types.INIT && !types.IsSupportedVersion(version):
return sdkerrors.Wrapf(
types.ErrInvalidConnectionState,
"connection state is in INIT but the provided encoded version is not supported %s", encodedVersion,
"connection state is in INIT but the provided version is not supported %s", version,
)

// if the connection is in TRYOPEN then the encoded version must be the only set version in the
// if the connection is in TRYOPEN then the version must be the only set version in the
// retreived connection state.
case connection.State == types.TRYOPEN && (len(connection.Versions) != 1 || connection.Versions[0] != encodedVersion):
case connection.State == types.TRYOPEN && (len(connection.Versions) != 1 || !proto.Equal(connection.Versions[0], version)):
return sdkerrors.Wrapf(
types.ErrInvalidConnectionState,
"connection state is in TRYOPEN but the provided encoded version (%s) is not set in the previous connection %s", encodedVersion, connection,
"connection state is in TRYOPEN but the provided version (%s) is not set in the previous connection versions %s", version, connection.Versions,
)
}

Expand All @@ -250,7 +252,7 @@ func (k Keeper) ConnOpenAck(

prefix := k.GetCommitmentPrefix()
expectedCounterparty := types.NewCounterparty(connection.ClientId, connectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes()))
expectedConnection := types.NewConnectionEnd(types.TRYOPEN, connection.Counterparty.ClientId, expectedCounterparty, []string{encodedVersion})
expectedConnection := types.NewConnectionEnd(types.TRYOPEN, connection.Counterparty.ClientId, expectedCounterparty, []*types.Version{version})

// Ensure that ChainB stored expected connectionEnd in its state during ConnOpenTry
if err := k.VerifyConnectionState(
Expand Down Expand Up @@ -280,7 +282,7 @@ func (k Keeper) ConnOpenAck(

// Update connection state to Open
connection.State = types.OPEN
connection.Versions = []string{encodedVersion}
connection.Versions = []*types.Version{version}
connection.Counterparty.ConnectionId = counterpartyConnectionID
k.SetConnection(ctx, connectionID, connection)
return nil
Expand Down
Loading

0 comments on commit 426d195

Please sign in to comment.