# IBC协议介绍

By [gcc2ge](https://paragraph.com/@gcc2ge) · 2022-06-02

---

`IBC`可以认为是连接`cosmos`生态中各个链之间的高速公路，那么，什么是`IBC`？`IBC`是如何实现区块链之间的互操作性的？我将介绍`IBC`的架构和主要组成部分，包括`IBC/TAO`和`IBC/APP`。在`IBC`协议的基础是可以建立跨链应用例如：跨链转账，链间账户等。最后，我将举例说明如何实现跨链代币转移。

什么是IBC
------

`IBC`是`Inter-Blockchain Communication`（跨链通信）的缩写。`IBC`是一个端到端的、面向连接的、有状态的协议，用于可靠、有序和认证的分布式账本上的模块之间的通信。

`IBC`协议采用分层设计，主要分为2层：

*   `IBC/TAO`：`TAO`指的是：`transport`, `authorization`, `organization`，该协议处理分布式账本之间的数据之间的传输，认证，排序。
    
*   `IBC/APP`：基于`TAO`构建的上层应用层，定义了从传输层发送过来的数据的处理方式，如可分割代币转移(`ICS-20`),`NFT`代币转移(`ICS-721`)，`interchain accounts`（链间账户 `ICS-27`)
    

实现`IBC`协议的大多数工作集中在`TAO`层，一旦`TAO`层实现，则很容易在`TAO`层之上实现不同的`APP`层协议。

和`TCP/IP`协议类似，`IBC`的特殊性在于它可以将应用层（`application layer`）从传输层和网络层（`TAO`, `transport`, `authorization`, `organization`）中剥离出来。这意味着`IBC`定义了数据是如何跨链被发送和接受的。不过它并没有明确具体的数据以及这些数据是如何组织的。这使得`IBC`从其他一些需要在应用层实现大量标准化的跨链解决方案中脱引而出。

下图展示了`IBC`工作流程：

![](https://storage.googleapis.com/papyrus_images/8dabef2bff0b46fe69c11562faa58477058813d64f64cd262a59bcaf699c45ce.jpg)

上图中有三个关键点需要注意:

*   链之间依赖`relayer`通信，`relayer`相当于`IBC`协议中的物理层连接，`relayer`会扫描运行`IBC`协议的链，并负责向其他链报告最新的状态。
    
*   多个`relayer`可以为多个`channel`传输数据
    
*   `relayer`使用每个链上的`light client`来交易发送过来的消息
    

IBC/TAO 网络传输层
-------------

`IBC/TAO`层的主要作用为：在两链之间以`reliable`，`ordered and authenticated`方式传递数据包。

*   `reliable`：是指源链仅发送一个`packet`，目标链仅接收一次，二者无需信任任何第三方。
    
*   `ordered`：是指目标链接收`packet`的顺序与源链发送`packet`的顺序一致。
    
*   `authenticated`：每个`channel`分配给特定这智能合约，只有分配到`channel`的智能合约可以通过这个`channel`发送`packet`，任何其他智能合约无法使用该`channel`发送packet。
    

`IBC/TAO`主要包含以下三个模块：

*   链上轻客户端（`on-chain light client`）
    
*   连接（`connection`）
    
*   通道（`channel`）
    

### Light Client

轻客户端是 `IBC/TAO`的基础，轻客户端有一个为一个`client ID`作为标识，`light client`会追踪其他区块链的共识状态，并且会基于共识状态交易对方区块链发送过来数据的合法性。`relayer`只负责消息的传递，消息的合法性是依赖于轻客户端做验证，所以`IBC`的安全性并不依赖于第三方服务比如`relayer`。

![img](https://storage.googleapis.com/papyrus_images/e78b87d9100ceb4b53533988e15ffb2684024302e9f93c469c8b5ad175c8a99d.png)

img

### Connection

有了`light client` 就可以在`light client`是建立`connection`，`connection`算是一个连接两个分布式账本的通道，一个`light client`可以接受任意数量的`connection`。

`connection`通过四次握手完成，所有操作都是由`relayer`发起交易来触发，`A`链发起连接到`B`链过程如下：

*   `connOpenInit`：在`A`链上会创建并存储`INIT`状态。
    
*   `connOpenTry`：`B`链若验证`A`链上该`connection`状态为`INIT`，则在`B`链上创建并存储`TRYOPEN`状态。
    
*   `connOpenAck`：`A`链若验证`B`链上该`connection`状态为`TRYOPEN`，则将`A`链上该`connection`的状态由`INIT`更新为`OPEN`。
    
*   `connOpenConfirm`：`B`链若验证`A`链上该`connection`状态已由`INIT`更新为`OPEN`，则将B链上该`connection`状态由`TRYOPEN`更新为`OPEN`。
    

![](https://storage.googleapis.com/papyrus_images/78dcece19a4936df6bbcd287bfd517117bb7e0d0ec0e853c170099e6b9368327.jpg)

### Channel

`connection`和`light client`构成了`IBC`中传输层的主要组件。但是，`IBC`中的应用程序之间的通信是通过`channel`进行的，`channel`在应用程序模块与另一条链上的相应应用程序模块之间进行路由。这些应用程序由端口标识符命名，例如 `ICS-20 token`传输的`transfer`。

`channel`通过四次握手完成，所有操作都是由`relayer`发起交易来触发，`A`链发起连接到`B`链过程如下：

*   `chanOpenInit`：在`A`链上会创建并存储`INIT`状态。
    
*   `chanOpenTry`：`B`链若验证`A`链上该`channel`为`INIT`状态，则在`B`链上创建并存储`TRYOPEN`状态。
    
*   `chanOpenAck`：`A`链若验证`B`链上该`channel`为`TRYOPEN`状态，则将`A`链上该`channel`的状态由INIT更新为`OPEN`。
    
*   `chanOpenConfirm`：`B`链若验证`A`链上该`channel`状态已由`INIT`更新为`OPEN`，则将`B`链上该`channel`状态由`TRYOPEN`更新为`OPEN`。
    

![](https://storage.googleapis.com/papyrus_images/832885bb27f0cdab8bed952f4441dfc0345864ba09e892a64f90372ec55b03c6.jpg)

IBC/APP 应用层
-----------

### 跨链转账

在`IBC`的技术上可以构建跨链`token`转移的应用，在`token`进行转移的时候最重要的是确定要转移的`token`是不是属于当前链，下面流程图展示了如何区分`token`是是否是属于当前链：

*   如果`token`是当前链的`native token`，那么当前链是`token`的源链
    
*   如果`token`是当前链通过`channel`从其他链接受的`token`，那么当前链不是`token`的源链，否者当前链是`token`的源链
    

![](https://storage.googleapis.com/papyrus_images/a4ba090bb7cc0e1fb8efd42406facccd40c1cb6d0503a0fe9ecb26bc5886884d.jpg)

区分当前链是否为`token`的源链就可以进行`token`转移了，因为`token`从源链到目标链，和`token`从目标链到源链的逻辑是不相同的。下图展示了两者的区别：

*   `token`从目标链转移到目标链
    
    *   托管`token`
        
    *   目标链mint新的`token`
        
*   `token`从目标链转移回源链
    
    *   目标链`burn token`
        
    *   源链释放托管的`token`
        

![](https://storage.googleapis.com/papyrus_images/c09f07107eae2d6b82b31fef285b1d5ecaf3608051ebdf3cb6208deb8373a860.jpg)

当`token`从一个链转到另一个链后，它的`denom`（`token`的标识符类似`ethereum`中的`symbol`）会产生变化，比如在`Ethereum`的跨链桥方案中，`eth`从`Ethereum`跨到`bsc`链上时就会变成`eth.e`或者其他的名称（和你使用的跨链桥有关，不同的桥跨链后的资产名称是不一样的）。那么在`IBC`方案中并没有中心化的桥提供服务，那么跨链后的资产名称如何命名？

![](https://storage.googleapis.com/papyrus_images/d27c2a3fd521866847927ab947ba29f2ed7bb7c669784e5de96dec8c513f3c00.jpg)

如上图所示，链`A`（`channel-2`）与链`B`（`channel-40`）之间的已经建好了`channel`，当`token`从A链转到B链时，`token`在`B`链的`denom`为`{Port}/{Channel}/{denom}`，`channel`建立好后，会绑定`port`，`transfer` 模块将绑定到一个名为 `transfer` 的端口。如果链`A`发送 `100` 个`ATOM token`，则链`B`将收到 `100` 个 `ATOM token` 并附加链B的`channel`前缀`port/channel-id`。所以链 `B` 会将这 `100` 个 `ATOM` 代币铸造为`transfer/channel-40/atom`。

#### 案例

接下来演示`IRIS`的`native token uiris`经过`cosmos hub`转移到`KAVA`链的过程。

**Native Token On** `IRIS`

*   denom: `uiris`
    

**IBC Token On** `COSMOS`

*   Denom: `ibc/hash(transfer/channel-20/uiris)`
    
*   DenomTrace
    
    *   BaseDenom: `uiris`
        
    *   Path: `transfer/channel-20`
        

**IBC Token On** `KAVA`

*   Denom: `ibc/hash(transfer/channel-30/transfer/channel-20/uiris)`
    
*   DenomTrace
    
    *   BaseDenom: `uiris`
        
    *   Path: `transfer/channel-30/transfer/channel-20`
        

##### IRIS->COSMOS-KAVA

![未命名23](https://storage.googleapis.com/papyrus_images/70f99352816636feda419fb57935ebf659efabe24949fbbd2bcd74cbb678607b.png)

未命名23

上图流程如下：

*   `uiris`是`IRIS`的`native token`所以直接将`uiris`托管在`IRIS`链中
    
*   `cosmos`链在`channel-20`通道中`mint ibc token` `transfer/channel-20/uiris`，并将`ibc token`从`channel-21`通道发送给`KAVA`
    
*   `cosmos`检查`transfer/channel-20/uris`并不是通过`channel-21`通道接受的`token`，所以在`channel-21`中托管`ibc token`
    
*   `Kava`收到`cosmos`的消息，在`channel-30`中`mint ibc token`
    

##### KAVA->COSMOS->IRIS

![未命名24](https://storage.googleapis.com/papyrus_images/f7a790d4a93d1e28ec71a47c6329c9a04498581d2f0d907ece940209558722e6.png)

未命名24

上述过程的逆操作，可看上图中的注释。

### interchain account

跨链账户允许区块链使用`IBC`安全地控制另一个区块链上的账户。

跨链账户最重要的两个特点如下：

*   通过`IBC`在另一个链上创建一个新的跨链账户
    
*   通过`IBC`可以控制远程的跨链账户
    

![](https://storage.googleapis.com/papyrus_images/4a0854db0f71e723637389f1d7836fce52bfb412fa65f5040c9d72e9e28690f3.jpg)

`Host Chain`：跨链账户在`Host Chain`上注册生成。`Host Chain`监听来自`controller chain`的 IBC 数据包（创建`interchain account`的数据包）。

`controller chain`：该链可以在`Host Chain`上注册跨链账户，完成后可以控制跨链账户（通过发送IBC packet给`Host Chain`来控制）。`controller chain`必须具有至少一个跨链帐户身份验证模块（`Authentication Module`）才能充当`controller chain`。

`Authentication Module`（身份验证模块）：`controller chain`上的自定义`IBC`应用程序模块，使用跨链账户模块 API 构建自定义逻辑，用于创建和管理跨链账户。`controller chain`需要身份验证模块才能利用链间帐户模块功能。

跨链账户（`ICA`）：`Host Chain`上的账户。跨链账户具有普通账户的所有功能。但是，`controller chain`的身份验证模块不会使用私钥对交易进行签名，而是将`IBC`数据包发送到`Host Chain`，以指示跨链帐户应该执行哪些交易。

总结
--

![](https://storage.googleapis.com/papyrus_images/077a981146b0433806f37954333a7899b372d72e2d4237f0b7f1827a22d5145b.jpg)

`IBC`协议一共分为四层分别是：应用层，`channel`，`connection`，`light client`。 应用层处理来自`channel`的数据报，并将处理完成后的数据交给`channel`发送给对方链。目前用的比较多的应用就是跨链token转移和链间账户。

`channel`建立在`connection`上，一个`connection`上可以拥有多个`channel`，每个`channel`的id是自增的，`channel`和模块进行绑定。

`connection`建立在`light client`的基础上，一个 `light client`上可以有多个`connection`，`connection`的id也是自增的。

每个链都会拥有另一条链的`light client`，`light client`跟踪其他链的共识状态，以及根据对方链的`light client`的共识状态验证对方的数据包的合法性。

`relayer`不对数据包进行任何验证，因此不需要被信任，但`relayer`在 `IBC` 中具有特别重要的作用，除了通过提交数据包以保持`IBC`网络的活跃性。他们负责提交init消息以创建新`light client`，并在每个链上保持`light client`状态的更新，以确保`light client`可以验证传递过来的数据包的合法性。`relayer`还负责发送`connection`和`channel`握手数据包，在链之间建立`connection`和`channel`。此外，如果连接另一端的链尝试分叉或尝试其他类型的恶意行为，`relayer`可以提交不当行为的证据。

---

*Originally published on [gcc2ge](https://paragraph.com/@gcc2ge/ibc)*
