Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBC content update prior to IDA cohort 3 #1274

Merged
merged 13 commits into from
Nov 30, 2022
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*.swp
*.swo
.vscode/settings.json
.vscode/
.idea

# Build
Expand Down
57 changes: 41 additions & 16 deletions academy/3-ibc/1-what-is-ibc.md

Large diffs are not rendered by default.

103 changes: 65 additions & 38 deletions academy/3-ibc/2-connections.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "IBC/TAO - Connections"
order: 3
description: Establishing connections in IBC
tags:
tags:
- concepts
- ibc
- dev-ops
Expand Down Expand Up @@ -39,7 +39,7 @@ In the IBC stack, connections are built on top of clients, so technically there

<HighlightBox type="note">

**Version negotiation**
### Version negotiation

Note that versioning here refers to the IBC protocol spec and not the ibc-go module. A backwards incompatible update is currently not planned.

Expand All @@ -56,17 +56,17 @@ type Version struct {

Protocol versioning is important to establish, as different protocol versions may not be compatible, for example due to proofs being stored on a different path. There are three types of protocol version negotiation:

1. *Default, no selection*: only one protocol version is supported. This is default to propose.
2. *With selection*: two protocol versions can be proposed, such that the chain initiating `OpenInit` or `OpenTry` has a choice of which version to go with.
3. *Impossible communication*: a backwards incompatible IBC protocol version. For example, if an IBC module changes where it stores its proofs (proof paths), errors result. There are no plans to upgrade to a backwards incompatible IBC protocol version.
1. _Default, no selection_: only one protocol version is supported. This is default to propose.
2. _With selection_: two protocol versions can be proposed, such that the chain initiating `OpenInit` or `OpenTry` has a choice of which version to go with.
3. _Impossible communication_: a backwards incompatible IBC protocol version. For example, if an IBC module changes where it stores its proofs (proof paths), errors result. There are no plans to upgrade to a backwards incompatible IBC protocol version.

</HighlightBox>

As discussed previously, the opening handshake protocol allows each chain to verify the identifier used to reference the connection on the other chain, enabling modules on each chain to reason about the reference of the other chain.

![Connection state](/academy/3-ibc/images/connectionstate.png)

With regards to the connection on the other side, the [connection protobufs](https://github.com/cosmos/ibc-go/blob/main/proto/ibc/core/connection/v1/connection.proto) contains the `Counterparty` definition:
With regards to the connection on the other side, the [connection protobufs](https://github.com/cosmos/ibc-go/blob/v5.1.0/proto/ibc/core/connection/v1/connection.proto) contains the `Counterparty` definition:

```go
// Counterparty defines the counterparty chain associated with a connection end.
Expand Down Expand Up @@ -97,11 +97,19 @@ Establishing an IBC connection (for example, between chain A and chain B) requir
3. OpenAck
4. OpenConfirm

<HighlightBox type="info">

Colin Axnér of Interchain gives an overview of how IBC Connections work (ICS-03), along with a code walkthrough, in the context of the Inter-Blockchain Communications Protocol (IBC).

<YoutubePlayer videoId="E3ZvqdY2tL8" />

</HighlightBox>

A high level overview of a successful four-way handshake is as follows:

### Handshake 1 - OpenInit
### Handshake step 1 - `ChanOpenInit`

`OpenInit` initializes any connection which may occur, while still necessitating agreement from both sides. It is like an identifying announcement from the IBC module on chain A which is submitted by a relayer. The relayer should also submit an `UpdateClient` with chain A as the source chain before this handshake. `UpdateClient` updates the client on the initializing chain A with the latest consensus state of chain B.
`OpenInit` initializes any connection which may occur, while still necessitating agreement from both sides. It is like an identifying announcement from the IBC module on chain A which is submitted by a relayer. The relayer should also submit a `MsgUpdateClient` with chain A as the source chain before this handshake. `MsgUpdateClient` updates the client on the initializing chain A with the latest consensus state of chain B.

![OpenInit](/academy/3-ibc/images/open_init.png)

Expand All @@ -111,7 +119,7 @@ The initiation of this handshake from chain A updates its connection state to `I

<!-- TODO insert image -->

The reference implementation for the connection handshake is found in the [IBC module repository](https://github.com/cosmos/ibc-go/blob/main/modules/core/03-connection/keeper/handshake.go). Examine `ConnOpenInit`:
The reference implementation for the connection handshake is found in the [IBC module repository](https://github.com/cosmos/ibc-go/blob/v5.1.0/modules/core/03-connection/keeper/handshake.go). Examine `ConnOpenInit`:

```go
func (k Keeper) ConnOpenInit(
Expand All @@ -121,7 +129,7 @@ func (k Keeper) ConnOpenInit(
version *types.Version,
delayPeriod uint64,
) (string, error) {
...
... //version negotiation logic

// connection defines chain A's ConnectionEnd
connectionID := k.GenerateConnectionIdentifier(ctx)
Expand Down Expand Up @@ -150,8 +158,16 @@ This function creates a unique `connectionID`. It adds the connection to a list
It creates a new `ConnectionEnd`:

```go
//@ func (k Keeper) ConnOpenInit
...
connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, types.ExportedVersionsToProto(versions), delayPeriod)
k.SetConnection(ctx, connectionID, connection)
...
```

With the following proto definition:

```go

// ConnectionEnd defines a stateful object on a chain connected to another separate one.
// NOTE: there must only be 2 defined ConnectionEnds to establish
Expand All @@ -172,9 +188,9 @@ message ConnectionEnd {
// clients.
uint64 delay_period = 5 [(gogoproto.moretags) = "yaml:\"delay_period\""];
}
````
```

`ConnOpenInit` is triggered by the **relayer**, which constructs the message and sends it to the SDK that uses the [`msg_server.go`](https://github.com/cosmos/ibc-go/blob/main/modules/core/keeper/msg_server.go) previously seen to call `ConnOpenInit`:
`ConnOpenInit` is triggered by the **relayer**, which constructs the message and sends it to the SDK that uses the [`msg_server.go`](https://github.com/cosmos/ibc-go/blob/v5.1.0/modules/core/keeper/msg_server.go) previously seen to call `ConnOpenInit`:

```go
// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit.
Expand All @@ -189,21 +205,21 @@ func (k Keeper) ConnectionOpenInit(goCtx context.Context, msg *connectiontypes.M
}
```

### Handshake 2 - OpenTry
### Handshake step 2 - `ChanOpenTry`

`OpenInit` is followed by an `OpenTry` response, in which chain B verifies the identity of chain A according to information that chain B has about chain A in its light client (the algorithm and the last snapshot of the consensus state containing the root hash of the latest height as well as the next validator set). It also responds to some of the information about its own identity in the `OpenInit` announcement from chain A.

![OpenTry](/academy/3-ibc/images/open_try.png)

The purpose of this step of the handshake is double verification: not only for chain B to verify that chain A is the expected counterparty identity, but also to verify that the counterparty has accurate information about chain B's identity. The relayer also submits two `UpdateClient`s with chain A and chain B as source chains before this handshake. These update the light clients of both chain A and chain B in order to make sure that the state verifications in this step are successful.
The purpose of this step of the handshake is double verification: not only for chain B to verify that chain A is the expected counterparty identity, but also to verify that the counterparty has accurate information about chain B's identity. The relayer also submits two `MsgUpdateClient`s with chain A and chain B as source chains before this handshake. These update the light clients of both chain A and chain B in order to make sure that the state verifications in this step are successful.

The initiation of this handshake from chain B updates its connection state to `TRY`.
The initiation of this handshake from chain B updates its connection state to `TRYOPEN`.

With regards to IBC protocol versioning, `OpenTry` either accepts the protocol version which has been proposed in `OpenInit` or proposes another protocol version from the versions available to chain A to be used for the IBC connection. A relayer-submitted `OpenTry` which contains an unsupported protocol version will be expected to fail.

<!-- TODO insert image -->

The implementation of OpenTry is as follows:
The [implementation of OpenTry](https://github.com/cosmos/ibc-go/blob/v5.1.0/modules/core/03-connection/keeper/handshake.go#L61-L147) is as follows:

```go
// ConnOpenTry relays notice of a connection attempt on chain A to chain B (this
Expand All @@ -214,33 +230,32 @@ The implementation of OpenTry is as follows:
// - Identifiers are checked on msg validation
func (k Keeper) ConnOpenTry(
ctx sdk.Context,
previousConnectionID string, // previousIdentifier
counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier
delayPeriod uint64,
clientID string, // clientID of chainA
clientState exported.ClientState, // clientState that chain A has for chain B
counterpartyVersions []exported.Version, // supported versions of chain A
proofInit []byte, // proof that chain A stored connectionEnd in state (on ConnOpenInit)
proofClient []byte, // proof that chain A stored a light client of chain B
proofConsensus []byte, // proof that chain A stored chainB's consensus state at consensus height
proofHeight exported.Height, // height at which relayer constructs proof of A storing connectionEnd in state
consensusHeight exported.Height, // latest height of chain B which chain A has stored in its chain B client
counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier
delayPeriod uint64,
clientID string, // clientID of chainA
clientState exported.ClientState, // clientState that chainA has for chainB
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
proofHeight exported.Height, // height at which relayer constructs proof of A storing connectionEnd in state
consensusHeight exported.Height, // latest height of chain B which chain A has stored in its chain B client
) ...
```

## Handshake 3 - OpenAck
## Handshake step 3 - `ChanOpenAck`

`OpenAck` is very similar to the functionality of `OpenInit`, except that the information verification now occurs for chain A. As in `OpenTry`, the relayer also submits two `UpdateClient`s with chain A and chain B as source chains before this handshake. These update the light clients of both chain A and chain B, in order to make sure that the state verifications in this step are successful.
`OpenAck` is very similar to the functionality of `OpenInit`, except that the information verification now occurs for chain A. As in `OpenTry`, the relayer also submits two `MsgUpdateClient`s with chain A and chain B as source chains before this handshake. These update the light clients of both chain A and chain B, in order to make sure that the state verifications in this step are successful.

![OpenAck](/academy/3-ibc/images/open_ack.png)

The initiation of this handshake from chain A updates its connection state to `OPEN`. It is important to note that the counterparty chain *must* have a `TRY` connection state in order for the handshake and connection state update to be successful.
The initiation of this handshake from chain A updates its connection state to `OPEN`. It is important to note that the counterparty chain _must_ have a `TRYOPEN` connection state in order for the handshake and connection state update to be successful.

With regards to version negotiation, `OpenAck` must confirm the protocol version which has been proposed in `OpenTry`. It ends the connection handshake process if the version is unwanted or unsupported.

<!-- TODO insert image -->

The `OpenAck` code is very similar to `OpenTry`:
The [`OpenAck` code](https://github.com/cosmos/ibc-go/blob/v5.1.0/modules/core/03-connection/keeper/handshake.go#L154-L247) is very similar to `OpenTry`:

```go
func (k Keeper) ConnOpenAck(
Expand All @@ -260,6 +275,8 @@ func (k Keeper) ConnOpenAck(
Both functions do the same checks, except that `OpenTry` takes `proofInit` as a parameter, and `OpenAck` takes `proofTry`:

```go
// @ func (k Keeper) ConnOpenAck

// This function verifies that the snapshot we have of the counter-party chain looks like the counter-party chain, verifies the light client we have of the counter-party chain
// Check that Chain A committed expectedConnectionEnd to its state
if err := k.VerifyConnectionState(
Expand All @@ -286,13 +303,13 @@ if err := k.VerifyClientConsensusState(

Therefore, each chain verifies the `ConnectionState`, the `ClientState`, and the `ConsensusState` of the other chain. Note that after this step the connection state on chain A updates from `INIT` to `OPEN`.

### Handshake 4 - OpenConfirm
### Handshake step 4 - `ChanOpenConfirm`

`OpenConfirm` is the final handshake, in which chain B confirms that both self-identification and counterparty identification were successful.

![OpenConfirm](/academy/3-ibc/images/open_confirm.png)

The conclusion of this handshake results in the successful establishing of an IBC connection:
The [conclusion of this handshake](https://github.com/cosmos/ibc-go/blob/v5.1.0/modules/core/03-connection/keeper/handshake.go#L253-L297) results in the successful establishing of an IBC connection:

```go
func (k Keeper) ConnOpenConfirm(
Expand All @@ -303,20 +320,30 @@ func (k Keeper) ConnOpenConfirm(
)
```

The initiation of this handshake from chain B updates its connection state from `TRY` to `OPEN`. The counterparty chain *must* have an `OPEN` connection state in order for the handshake and connection state update to be successful.
The initiation of this handshake from chain B updates its connection state from `TRYOPEN` to `OPEN`. The counterparty chain _must_ have an `OPEN` connection state in order for the handshake and connection state update to be successful.

<!-- TODO insert image -->
<HighlightBox type="remember">

The successful four-way handshake described establishes an IBC connection between the two chains.

</HighlightBox>

The successful four-way handshake described establishes an IBC connection between the two chains. Now consider two related circumstances: simultaneous attempts by the chains to perform the same handshake, and attempts by an imposter to interfere.
Now consider two edge circumstances: simultaneous attempts by the chains to perform the same handshake, and attempts by an imposter to interfere.

### Crossing hellos

"Crossing Hellos" refers to when both chains attempt the same handshake step at the same time.
"Crossing hellos" refers to when both chains attempt the same handshake step at the same time.

<HighlightBox type="warning">

If both chains submit `OpenInit` then `OpenTry` at same time, there should be no error. In this case, both sides still need to confirm with a successful `OpenAck`, but no `OpenConfirm` is required because both ConnectionEnds will update to an OPEN state.
While still discussed in the video earlier, crossing hellos have been removed from ibc-go v4 onward, as referenced in [this PR](https://github.com/cosmos/ibc-go/pull/1672). The `PreviousConnectionId` in `MsgConnectionOpenTry` has been deprecated.

</HighlightBox>

### An imposter

What if an imposter tried to open a connection pretending to be another chain?

In fact this is not an issue. Any attempted `OpenInit` from an imposter will fail on `OpenTry`, because it will not contain valid proofs of `Client/Connection/ConsensusState`.

<HighlightBox type="synopsis">
Expand Down
Loading