Skip to content

Commit

Permalink
finish connection handshake chanes and some channel handshake changes
Browse files Browse the repository at this point in the history
Finish updating connection handshake changes, update genesis for connection and channel, some channel handshake changes, fix build for tests but still failing
  • Loading branch information
colin-axner committed Nov 20, 2020
1 parent 44174ec commit e01eb98
Show file tree
Hide file tree
Showing 23 changed files with 426 additions and 622 deletions.
1 change: 1 addition & 0 deletions proto/ibc/core/channel/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ message GenesisState {
[(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"recv_sequences\""];
repeated PacketSequence ack_sequences = 7
[(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"ack_sequences\""];
uint64 next_channel_sequence = 8 [(gogoproto.moretags) = "yaml:\"next_channel_sequence\""];
}

// PacketSequence defines the genesis type necessary to retrieve and store
Expand Down
15 changes: 7 additions & 8 deletions proto/ibc/core/channel/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,14 @@ message MsgChannelOpenTry {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
string desired_channel_id = 2 [(gogoproto.moretags) = "yaml:\"desired_channel_id\""];
string counterparty_chosen_channel_id = 3 [(gogoproto.moretags) = "yaml:\"counterparty_chosen_channel_id\""];
Channel channel = 4 [(gogoproto.nullable) = false];
string counterparty_version = 5 [(gogoproto.moretags) = "yaml:\"counterparty_version\""];
bytes proof_init = 6 [(gogoproto.moretags) = "yaml:\"proof_init\""];
ibc.core.client.v1.Height proof_height = 7
string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
string desired_channel_id = 2 [(gogoproto.moretags) = "yaml:\"desired_channel_id\""];
Channel channel = 3 [(gogoproto.nullable) = false];
string counterparty_version = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""];
bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""];
ibc.core.client.v1.Height proof_height = 6
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
string signer = 8;
string signer = 7;
}

// MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type.
Expand Down
1 change: 1 addition & 0 deletions proto/ibc/core/connection/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ message GenesisState {
repeated IdentifiedConnection connections = 1 [(gogoproto.nullable) = false];
repeated ConnectionPaths client_connection_paths = 2
[(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_connection_paths\""];
uint64 next_connection_sequence = 3 [(gogoproto.moretags) = "yaml:\"next_connection_sequence\""];
}
23 changes: 11 additions & 12 deletions proto/ibc/core/connection/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,23 @@ message MsgConnectionOpenTry {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
string desired_connection_id = 2 [(gogoproto.moretags) = "yaml:\"desired_connection_id\""];
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 Version counterparty_versions = 6 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
ibc.core.client.v1.Height proof_height = 7
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
string desired_connection_id = 2 [(gogoproto.moretags) = "yaml:\"desired_connection_id\""];
google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""];
Counterparty counterparty = 4 [(gogoproto.nullable) = false];
repeated Version counterparty_versions = 5 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
ibc.core.client.v1.Height proof_height = 6
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
// proof of the initialization the connection on Chain A: `UNITIALIZED ->
// INIT`
bytes proof_init = 8 [(gogoproto.moretags) = "yaml:\"proof_init\""];
bytes proof_init = 7 [(gogoproto.moretags) = "yaml:\"proof_init\""];
// proof of client state included in message
bytes proof_client = 9 [(gogoproto.moretags) = "yaml:\"proof_client\""];
bytes proof_client = 8 [(gogoproto.moretags) = "yaml:\"proof_client\""];
// proof of client consensus state
bytes proof_consensus = 10 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
ibc.core.client.v1.Height consensus_height = 11
bytes proof_consensus = 9 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
ibc.core.client.v1.Height consensus_height = 10
[(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false];
string signer = 12;
string signer = 11;
}

// MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type.
Expand Down
16 changes: 6 additions & 10 deletions x/ibc/core/03-connection/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ import (
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 [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]",
Use: "open-init [client-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.
- 'version-identifier' flag can be a single pre-selected version identifier to be used in the handshake.
Expand All @@ -38,7 +37,7 @@ func NewConnectionOpenInitCmd() *cobra.Command {
"%s tx %s %s open-init [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(4),
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
Expand All @@ -47,10 +46,9 @@ func NewConnectionOpenInitCmd() *cobra.Command {
}

clientID := args[0]
counterpartyConnectionID := args[1]
counterpartyClientID := args[2]
counterpartyClientID := args[1]

counterpartyPrefix, err := utils.ParsePrefix(clientCtx.LegacyAmino, args[3])
counterpartyPrefix, err := utils.ParsePrefix(clientCtx.LegacyAmino, args[2])
if err != nil {
return err
}
Expand All @@ -70,7 +68,7 @@ func NewConnectionOpenInitCmd() *cobra.Command {
}

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

Expand Down Expand Up @@ -115,7 +113,6 @@ func NewConnectionOpenTryCmd() *cobra.Command {
}

connectionID := args[0]
provedID, _ := cmd.Flags().GetString(flagProvedID)
clientID := args[1]
counterpartyConnectionID := args[2]
counterpartyClientID := args[3]
Expand Down Expand Up @@ -178,7 +175,7 @@ func NewConnectionOpenTryCmd() *cobra.Command {
}

msg := types.NewMsgConnectionOpenTry(
connectionID, provedID, clientID, counterpartyConnectionID, counterpartyClientID,
connectionID, clientID, counterpartyConnectionID, counterpartyClientID,
counterpartyClient, counterpartyPrefix, counterpartyVersions,
proofInit, proofClient, proofConsensus, proofHeight,
consensusHeight, clientCtx.GetFromAddress(),
Expand All @@ -192,7 +189,6 @@ func NewConnectionOpenTryCmd() *cobra.Command {
},
}

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

return cmd
Expand Down
1 change: 1 addition & 0 deletions x/ibc/core/03-connection/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) {
for _, connPaths := range gs.ClientConnectionPaths {
k.SetClientConnectionPaths(ctx, connPaths.ClientId, connPaths.Paths)
}
k.SetNextConnectionSequence(ctx, gs.NextConnectionSequence)
}

// ExportGenesis returns the ibc connection submodule's exported genesis.
Expand Down
36 changes: 9 additions & 27 deletions x/ibc/core/03-connection/keeper/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ func (k Keeper) ConnOpenInit(
// - Identifiers are checked on msg validation
func (k Keeper) ConnOpenTry(
ctx sdk.Context,
desiredConnectionID, // desiredIdentifier
counterpartyChosenConnectionID string, // counterparty used this identifier in proof
desiredConnectionID string, // desiredIdentifier
counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier
clientID string, // clientID of chainA
clientState exported.ClientState, // clientState that chainA has for chainB
Expand Down Expand Up @@ -90,33 +89,26 @@ func (k Keeper) ConnOpenTry(
return sdkerrors.Wrap(clienttypes.ErrSelfConsensusStateNotFound, consensusHeight.String())
}

// If the connection id chosen for this connection end by the counterparty is empty then
// flexible connection identifier selection is allowed by using the desired connection id.
// Otherwise the desiredConnectionID must match the counterpartyChosenConnectionID.
if counterpartyChosenConnectionID != "" && counterpartyChosenConnectionID != desiredConnectionID {
return sdkerrors.Wrapf(
types.ErrInvalidConnectionIdentifier,
"counterparty chosen connection ID (%s) must be empty or equal to the desired connection ID (%s)", counterpartyChosenConnectionID, desiredConnectionID,
)
}

// 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, counterpartyChosenConnectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes()))
expectedCounterparty := types.NewCounterparty(clientID, "", commitmenttypes.NewMerklePrefix(prefix.Bytes()))
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.
// Check that existing connection versions for initialized connection is equal to compatible
// versions for this chain.
connectionID := desiredConnectionID
previousConnection, found := k.GetConnection(ctx, desiredConnectionID)
if found && !(previousConnection.State == types.INIT &&
previousConnection.Counterparty.ConnectionId == counterparty.ConnectionId &&
previousConnection.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")
} else {
connectionID = k.GenerateConnectionIdentifier(ctx)
}

supportedVersions := types.GetCompatibleVersions()
Expand Down Expand Up @@ -156,12 +148,12 @@ func (k Keeper) ConnOpenTry(
}

// store connection in chainB state
if err := k.addConnectionToClient(ctx, clientID, desiredConnectionID); err != nil {
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", desiredConnectionID, clientID)
}

k.SetConnection(ctx, desiredConnectionID, connection)
k.Logger(ctx).Info("connection state updated", "connection-id", desiredConnectionID, "previous-state", previousConnection.State.String(), "new-state", "TRYOPEN")
k.SetConnection(ctx, connectionID, connection)
k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", previousConnection.State.String(), "new-state", "TRYOPEN")

defer func() {
telemetry.IncrCounter(1, "ibc", "connection", "open-try")
Expand Down Expand Up @@ -201,16 +193,6 @@ func (k Keeper) ConnOpenAck(
return sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID)
}

// If the previously set connection end allowed for the counterparty to select its own
// connection identifier then we use the counterpartyConnectionID. Otherwise the
// counterpartyConnectionID must match the previously set counterparty connection ID.
if connection.Counterparty.ConnectionId != "" && counterpartyConnectionID != connection.Counterparty.ConnectionId {
return sdkerrors.Wrapf(
types.ErrInvalidConnectionIdentifier,
"counterparty connection identifier (%s) must be 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
Expand Down
59 changes: 5 additions & 54 deletions x/ibc/core/03-connection/keeper/handshake_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
"fmt"
"time"

clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
Expand Down Expand Up @@ -58,19 +59,20 @@ func (suite *KeeperTestSuite) TestConnOpenInit() {

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, version)
connectionID, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenInit(suite.chainA.GetContext(), clientA, counterparty, version)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(fmt.Sprintf("%s/%d", types.ConnectionPrefix, 0), connectionID)
} else {
suite.Require().Error(err)
suite.Require().Equal("", connectionID)
}
})
}
Expand Down Expand Up @@ -100,50 +102,6 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
}, true},
{"success with empty counterpartyChosenConnectionID", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.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, exported.Tendermint)
suite.Require().NoError(err)

err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint)
suite.Require().NoError(err)

// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
}, true},
{"counterpartyChosenConnectionID does not match desiredConnectionID", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.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, exported.Tendermint)
suite.Require().NoError(err)

err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.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, exported.Tendermint)
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
Expand Down Expand Up @@ -298,13 +256,6 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
connB := suite.chainB.GetFirstTestConnection(clientB, clientA)
counterparty := types.NewCounterparty(clientA, connA.ID, suite.chainA.GetPrefix())

// get counterpartyChosenConnectionID
var counterpartyChosenConnectionID string
connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID)
if found {
counterpartyChosenConnectionID = connection.Counterparty.ConnectionId
}

connectionKey := host.ConnectionKey(connA.ID)
proofInit, proofHeight := suite.chainA.QueryProof(connectionKey)

Expand All @@ -320,7 +271,7 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
proofClient, _ := suite.chainA.QueryProof(clientKey)

err := suite.chainB.App.IBCKeeper.ConnectionKeeper.ConnOpenTry(
suite.chainB.GetContext(), connB.ID, counterpartyChosenConnectionID, counterparty, clientB, counterpartyClient,
suite.chainB.GetContext(), connB.ID, counterparty, clientB, counterpartyClient,
versions, proofInit, proofClient, proofConsensus,
proofHeight, consensusHeight,
)
Expand Down
11 changes: 7 additions & 4 deletions x/ibc/core/03-connection/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ func NewConnectionPaths(id string, paths []string) ConnectionPaths {
// NewGenesisState creates a GenesisState instance.
func NewGenesisState(
connections []IdentifiedConnection, connPaths []ConnectionPaths,
nextConnectionSequence uint64,
) GenesisState {
return GenesisState{
Connections: connections,
ClientConnectionPaths: connPaths,
Connections: connections,
ClientConnectionPaths: connPaths,
NextConnectionSequence: nextConnectionSequence,
}
}

// DefaultGenesisState returns the ibc connection submodule's default genesis state.
func DefaultGenesisState() GenesisState {
return GenesisState{
Connections: []IdentifiedConnection{},
ClientConnectionPaths: []ConnectionPaths{},
Connections: []IdentifiedConnection{},
ClientConnectionPaths: []ConnectionPaths{},
NextConnectionSequence: 0,
}
}

Expand Down
Loading

0 comments on commit e01eb98

Please sign in to comment.