As blockchain technology continues to evolve, achieving seamless communication and interoperability between different chains has become a crucial objective. In this article, we delve into two prominent protocols - Inter-Blockchain Communication (IBC) and Cross-Consensus Messaging (XCM) - that enable secure, permissionless, and trustless transfer of data between blockchains. We will explore both IBC and XCM, their functionality, features, and potential use cases.
At its core, IBC is an interoperability protocol that facilitates the transfer of data, assets, and logic between distinct blockchains. The protocol operates on the principles of simplicity, flexibility, and decentralization, offering a powerful solution for connecting blockchain networks.
Three abstraction layers: channels, connections, clients. Channels to identify application, connections for double identity verification, and clients to track consensus state of recipient chains.
When we send a packet on one chain we will submit a commitment proof, it will be recorded into the state. Then a relayer will construct a packet and add a proof that this was submitted into state and then submit this on the receiving chain which can then verify it using the Light Client of chain A that they have stored on chain B.
There are different Light Clients per consensus type. IBC's scope has expanded beyond the Tendermint consensus chains, thanks to the efforts of projects like Composable, which now support Substrate-based chains.
On top of clients there are connections. They operate once clients have been set up. It is a double identity verification. Both channels and connections are set up by handshakes.
The last layer of abstraction is channels. They are also set up with a handshake. In combination with the port they identify the application. Channel for a fungible token transfer over IBC could look like transfer/channel-0/base-denom where ‘transfer’ is the port name.
Relaying is permissionless and can be incentivized. IBC v4 and onwards contains fee middleware. Two implementations of relayer software available: one is Hermes developed in Rust and another is Go Relayer.
Let’s look at the IBC packet lifecycle using ICS-20 fungible token transfer standard.
Tokens on the left side are locked up by a user on Chain A, and after the tokens are locked, the packet is sent. The Light Client verification algorithm on Chain B checks whether the tokens on Chain A have been locked and mints IBC vouchers representing tokens of Chain A on Chain B.
Here’s a more generalized packet flow visualization:
This packet flow representation can be applied not only to fungible tokens but also to any data packets. Flow can be done in two different ways: by using interchain accounts or via custom applications.
Let’s look at custom IBC applications first.
Custom IBC applications allow for the development of completely customizable data transfers between chains. The exact requirements for module application to be IBC compatible can be found in the documentation. Specific application logic can then be added to such IBC compatible modules. Any data can be sent to the corresponding counterparty module. ICS-x means that the token will have a number instead of the ‘x’ which refers to a particular application.
Let’s now examine interchain accounts.
The interchain accounts option allows the use of functionality on Chain B from Chain A without leaving Chain A's environment.
Chains can implement both or either controller or host functionality. Host chain hosts ICA, executes sent txs. Controller chain triggers actions to be executed on the Host chain.
Let’s now explore a scenario where the relayer didn’t pick up the packet.
To avoid funds getting locked up forever a timeout functionality is implemented. The cool thing about IBC is it allows you to query not only receipts but also non-receipts. Such a query allows the user to submit a timeout command and revert the original send packet logic.
ICA have ordered channels. If such a channel has a timeout it is closed automatically.
Functionality that doesn't go in the IBC core can be used as middleware and reused for different applications thus building a middleware stack.
This diagram shows that we can keep stacking middleware and create functionality that way. Here packet and write_ack go from base application to Core IBC. Handshake, acks and timeouts go from Core IBC through the middleware to the base application. Order matters and must be replicated on the counterparty chain.
XCM is a cross-chain messaging protocol that enables the transfer of data and assets between chains in a more sophisticated and programmable way than ever before. XCM V3 includes improvements in three key areas: expectations and branching, introspection and safe dispatches, and asset exchange and NFTs.
Let’s now examine expectations and branching in more detail.
There are three new instructions: ExpectAsset, ExpectError and ExpectOrigin. They are related to three existing registers: Holding, Error, Origin. This allows for branching: changing the flow depending on errors thrown.
Safe dispatches allow for version control of destination chain and specific pallet. There is a new register called ‘Transact Status Register’ and four new instructions: QueryPallet, ExpectPallet, ReportTransactStatus, ClearTransactStatus. The new register holds the result of the most recent transact operation. QueryPallet gives back the instances of a specific pallet or module. ExpectPallet throws an error if the expected version does not match the one we get back. ReportTransactStatus reports what the Transact Status Register holds and ClearTransactStatus clears the data.
The goal of these statuses is to ensure no unexpected behavior is happening.
The second big category introduced in XCM v3 is Functional Multichain Decomposition. It is designed to allow for building utilizing logic from multiple chains. The changes here can be grouped into three categories:
- Remote Locking
- Context/ID for tracking messages & queries
- Asset Namespacing
Remote Locking enables chains to use assets in other chains. Four new instructions here:
One of the goals for Functional Multichain Decomposition is to enable tracking XCM messages. A new register ‘Topic’ is introduced. It can be set to any value and used as an ID by itself or in combination with ‘Origin’ to create a unique identifier.
There is a way to let ExmExecutor know about the context of the instruction using the XcmContext struct. It has three fields: Origin, XcmHash, Topic. This allows to track XCM message’s context and thus have an application spread between different shards.
The third big area of note is bridging. The four key improvements here are:
- Universal Location
- Message Exporting
- Two stage Send and Export
- Logical Origins
Universal Location is a new and unique location, a parent of all locations (different consensus systems). It encompasses relay chains and parachains. It has no parent and allows to use ‘Context’ for locating within the Universal Location.
There are three new SendXcm impls to manage routing over a bridge. They cover three scenarios:
- The bridge is local
- The bridge is in Local consensus but not on local chain (no fees expected)
- The bridge is not local (fees expected)
Two stage Send and Export means that SendXcm is now a two-stage process: validate and deliver. Validate does price discovery and returns a ticket. Deliver executes the transaction.
The rise of IBC and XCM protocols represents significant milestones in achieving seamless communication and interoperability across blockchain networks. Through their secure, permissionless, and trustless nature, IBC and XCM empower developers to create decentralized applications that transcend the boundaries of individual chains. By enabling data transfer, asset exchange, and sophisticated programmability, these protocols pave the way for the next generation of blockchain innovation, facilitating collaboration, scalability, and enhanced user experiences in the decentralized ecosystem.