# Transport, Authentication, and Ordering Layer - Connections
IBC in depth. Discover the IBC protocol in detail:
- Learn more about connection negotiation.
- Explore connection states.
- How IBC repels hostile connection attempts.
Now that you covered the introduction and have a better understanding of how different Inter-Blockchain Communication Protocol (IBC) components and interchain standards (ICS) relate to each other, take a deep dive into IBC/TAO (transport, authentication, and ordering) and the IBC module (opens new window).
# Connections
If you want to connect two blockchains with IBC, you will need to establish an IBC connection. Connections, established by a four-way handshake, are responsible for:
- Establishing the identity of the counterparty chain.
- Preventing a malicious entity from forging incorrect information by pretending to be the counterparty chain. IBC connections are established by on-chain ledger code and therefore do not require interaction with off-chain (trusted) third-party processes.
The connection semantics are described in ICS-3 (opens new window).
In the IBC stack, connections are built on top of clients, so technically there could be multiple connections for each client if the client is interacting with multiple versions of the IBC protocol. For now, the setup should connote one connection for each client.
# 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.
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:
- Default, no selection: only one protocol version is supported. This is default to propose.
- With selection: two protocol versions can be proposed, such that the chain initiating
OpenInitorOpenTryhas a choice of which version to go with. - 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.
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.

With regards to the connection on the other side, the connection protobufs (opens new window) contains the Counterparty definition:
In this definition, connection-id is used as a key to map and retrieve connections associated with a certain client from the store.
prefix is used by the clients to construct merkle prefix paths which are then used to verify proofs.
# Connection handshakes and states
Establishing an IBC connection (for example, between chain A and chain B) requires four handshakes:
- OpenInit
- OpenTry
- OpenAck
- OpenConfirm
Colin Axnér of the Interchain Foundation 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).
A high level overview of a successful four-way handshake is as follows:
# Handshake step 1 - ConnOpenInit
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.

The initiation of this handshake from chain A updates its connection state to INIT.
OpenInit proposes a protocol version to be used for the IBC connection. A relayer-submitted OpenInit which contains a protocol version that is not supported by chain A will be expected to fail.
The reference implementation for the connection handshake is found in the IBC module repository (opens new window). Examine ConnOpenInit:
This function creates a unique connectionID. It adds the connection to a list of connections associated with a specific client.
It creates a new ConnectionEnd:
With the following proto definition:
ConnOpenInit is triggered by the relayer, which constructs the message and sends it to the SDK that uses the msg_server.go (opens new window) previously seen to call ConnOpenInit:
# Handshake step 2 - ConnOpenTry
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.

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 MsgUpdateClients 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 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.
The implementation of OpenTry (opens new window) is as follows:
# Handshake step 3 - ConnOpenAck
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 MsgUpdateClients 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 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.
The OpenAck code (opens new window) is very similar to OpenTry:
Both functions do the same checks, except that OpenTry takes proofInit as a parameter, and OpenAck takes proofTry:
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 step 4 - ConnOpenConfirm
OpenConfirm is the final handshake, in which chain B confirms that both self-identification and counterparty identification were successful.

The conclusion of this handshake (opens new window) results in the successful establishing of an IBC connection:
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.
The successful four-way handshake described establishes an IBC connection between the two chains.
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.
While still discussed in the video earlier, crossing hellos have been removed from ibc-go v4 onward, as referenced in this PR (opens new window). The PreviousConnectionId in MsgConnectionOpenTry has been deprecated.
# 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.
To summarize, this section has explored:
- How a connection between two blockchains with IBC is established by a four-way handshake, thereby establishing the identity of the counterparty chain and preventing any malicious entity from pretending to be the counterparty.
- How versioning is important to establish, to ensure that only compatible protocol versions attempt to connect.