# XCMP & IBC报告

By [Fan ](https://paragraph.com/@fan-3) · 2022-03-23

---

本文沿着跨链通信需要解决的5大难题这一框架，通过深入挖掘XCMP与IBC二者的技术原理，刨析其不同的技术解决路径，结合当前不同项目的开发情况，拆解应用生态的代码部署流程，对二者的通信效率、开发进度、部署便捷性、应用场景、安全性这五个方面进行了对比，旨在为读者提供一个更为全面的分析。

本文认为： **相比于IBC，XCMP技术原理更为复杂的根本原因是为了实现平行链通信的去信任化与通信信息的多元化。而这也在同时限制了对平行链安全性的自定义化需求并提高了系统整体崩溃的风险**。 此外，如忽略技术实现细节，IBC与XCMP的不同表现在：

*   XCMP中平行链之间能够直接传输信息，但是目前Channel被限制在100个。而IBC依靠Hub进行通信，无法直接传输。
    
*   XCMP目前仍在开发，是以HRMP为临时替代协议实现跨链信息交互。而IBC已经完成了上线，并在2020年10月份后稳定。
    
*   IBC技术实现细节远简单于XCMP协议，但是好处是大幅降低开发难度于维护成本。
    
*   XCMP与IBC都通过高度封装之后的抽象函数调用，目前看来其部署均较为简单，并不存在一方过于复杂的情况。而只要是生态中需要跨链交互的均需要调用这两个协议。
    
*   XCMP设计之初，就不仅仅是针对于平行链之间消息的传递，更是为了实现智能合约，pallet，跨链桥、甚至SPREE之间的通信。而IBC设计的初衷与目前的应用场景只针对于平行链之间消息的传输。
    

XCMP对于平行链的安全性并无要求，其统一由中继链进行保证。而IBC并不保证平行链的安全性，需要依赖于平行链自身的安全性。

跨链通信的难题
-------

目前跨链技术协议有很多，但是归纳下来，跨链通信需要解决以下五个最主要的问题：

*   有序性：如何使得消息能按序到达目的链。
    
*   可验证：如何识别未处理的消息、验证到达的消息确实是由相应发送链发送的，如何验证消息的正确性。
    
*   无遗漏：如何确保链公平地接收每条消息、发送链不会无限期等待消息被接收链接收和处理。
    
*   有效性：需要防止中继链过载，防止网络拥堵与过载。
    
*   安全性：如何解决平行链与中继链的安全性问题。
    

Substrate框架下的XCMP与Cosmos中的IBC采用了不同的方法来处理与解决上述五个问题，本文将会沿着这一框架来对这两种协议的实现原理、发展现状、优缺点等方面进行深入研究与阐述。

XCMP解决方案
--------

### XCMP与XCM的含义、差别及各自实现的功能

XCMP的全程叫做跨链消息传递（Cross-chain Message Passing），XCMP目前还在开发当中，跨链的通信采用HRMP进行替代。总体来说，波卡有4种不同的跨链消息传递方式，每种不同的传递方式具有不同的特点：

*   **中继链与平行链之间UMP（Up Message Passing）、DMP（Down Message Passing）**
    
    UMP是指中继链向上向平行链传递消息，DMP指平行链向下向中继链传递消息，如图1所示。这两种消息传递方式早已完全实现，但这两种方式并不能实现平行链之间的消息传递。
    
*   **平行链之间HRMP、XCMP（Cross-chain Message Passing）**
    
    HRMP是指以中继链为中介，来实现两个平行链之间的信息传送功能。由于这种方法使得中继链承担较大储存与运算压力，使得整体的效率非常低，其为波卡推出的临时解决方案，在XCMP上线之后将会取代HRMP方案。XCMP如上文所述，是平行链之间进行跨链信息交互的最终形式，其不会给予中继链过大的运行与存储负担。
    

![平行链之间通信方式](https://storage.googleapis.com/papyrus_images/58a864f83b6417aa9e8879169998613f24dcbc00459c735faa8f994058892851.png)

平行链之间通信方式

![中继链与平行链之间通信方式](https://storage.googleapis.com/papyrus_images/e6b5c48b807cfb07bc7cf25fd8b0f0bad8c269d01b685adf4aa93fde49e7e49f.png)

中继链与平行链之间通信方式

要解决跨链信息传输与交互的功能，**不仅需要标准化的传输协议对传输的过程与形式进行规范，更需要将传输的消息形式进行统一与标准化**，因此，在这里需要将XCMP与XCM（Cross-chain Message）两者定义进行区别：

*   **XCM（Cross-chain Message）**
    
    XCM是跨链传输的信息的标准格式，可以类比于ERC20格式。波卡不仅想让跨链的信息在链间进行交互，更可以在智能合约，pallet，SPREE之间进行交互。因此，为了更高效的实现这一点，统一的跨链消息格式是必须的组件。
    
*   **XCMP（Cross-chain Message Passing）**
    
    XCMP如上所述，为跨链传输信息的标准流程。其包含消息传递与消息存取两个关键的部分。消息传递主要是指消息通过什么样的路由方式在平行链之间传递，而消息的存取为中继链、平行链之间如何存取消息及消息的相关证明。本文为了保证逻辑的连贯，将这两个主要部分拆分至下文的部分进行阐述。
    

值得注意的是，由于区块链可以被是做一个全局的状态转换机器，因此，我们可以将XCM与XCMP总体看作是跨链状态转化过程。

### 如何实现有序性

由于不同平行链上运行着不同的DAPP，而对于一些类似DEFI的协议来说，按时有序的接收并处理消息显得至关重要。因此可以看出，**有序性主要体现在消息的传递过程当中**。

总体而言，两条平行链之间传输消息需要分别对彼此建立**通道（channel）**。当前而言，**通道为单向通道（理论上也可以成为双向通道）**。当通道处于打开状态时，通道中会包含以一个已发送但是未被接收的**有序队列**。

此队列的规则为，当消息发送者在此通道中发送新的消息时，将新的消息压到队列的末尾，接收者从队列的排头取出新消息，体现在队列中即为删除最前面的消息。**由此，消息的有序性就得到了保证，新发送的消息后接收，已发送的消息先接收**。

![发送链与接收链消息队列](https://storage.googleapis.com/papyrus_images/f2d1e7397f84e322b451a8706311b0137d32ff754b5759e8bbe810f40cb34d9f.png)

发送链与接收链消息队列

### 如何实现可验证性与无遗漏性

对于接收链来说，保证消息有序的接收与处理只是其中一个关键的环节，更需要解决的是，如何去识别哪些消息并未处理，如何取验证获取消息是正确的。想要理解如何解决这一问题需要深入到数据结构层面。

*   \*\*MQC（Message Queue Chain，消息队列链）。\*\*MQC是每个消息发送链自身负责维护的链，每有一个接收链即会产生一条对应的MQC。
    
*   \*\*MQHC（Message Queue Hash Chain，消息队列哈希链）。\*\*其是由MQC每个信息进行哈希计算得到的。MQHC中有三个元素 HC = {H(M), relay\_number, H(pre\_HC)}， H(M)表示消息的哈希值，relay\_number代表该消息发送链上一次对接收链发送消息时的中继链的区块号，也即为上次发送消息的时间，H(pre\_HC) 代表上一个区块的哈希值。
    

![MQHC示意图](https://storage.googleapis.com/papyrus_images/18a71ca3a15a522978be798f66ca4e456d67d86d53bb0cdb517ca2685d1d43f7.png)

MQHC示意图

![MQHC示意图](https://storage.googleapis.com/papyrus_images/a1302c27977bd5f56d2003eedc5255afc201a84c48ee8f3785ad9f413ab9d5e9.png)

MQHC示意图

可见，**如果接收链能够拿到对应发送链的HC，则可以通过对比消息的哈希值来验证获得消息的正确无误性**。而relay\_number可以用于定位处在某些时间之间的所有消息。

值得注意的是，**MQHC的大小决定了消息通道的负载程度**。因此，当接收链最终在中继链上确认了消息的接收之后，可以在MQHC中删除相应的消息以维持整个通道中消息的负载程度处在合理的区域。

由于每一条发送链对于每一个接收链都会维护一个MQHC，为了更加高效的查询与定位，**将所有的MQHC最新区块头作为Merkle Tree的叶子节点，所得到的根节点值被称为Message Root（MR）**。因此，通过提供对应的Merkle Proof 可以查询得到底层的HC。

![Message Root a](https://storage.googleapis.com/papyrus_images/43195b4f054ae49de2984c634e47fae1e02a222d75db96d5f38e0013a7dabc45.png)

Message Root a

MR会被包含在发送链区块的区块头中，与此相伴的还有water mark和bitfield两个参数。

*   **Water mark（水印）**
    
    其是接收链用于判断是否处理该消息的工具，包含（block\_number，para\_id）两个参数，其中Block\_number 表示中继链的区块号，para\_id表示接收链的ID号（substrate对每一个链都会有一个唯一ID号）。
    
    若有两个water\_mark，其分别为W1 =（10，B），W2 =（20，B），则可以通过\[W1,W2\]表示处于\[10,20\]中继链区块时间的所有发送给B的消息集合。\*\*Water mark首先是由发送链构建，然后验证后传递至中继链上，最后传递至接收链上。因此，接收链收集人可以将当前的water mark与上一个water mark之间的所有消息确认为发送链已发送但未被接收链处理的消息。\*\*由此，解决了识别哪些消息为未处理消息的功能。
    
*   **Bitfield**
    
    其是一组Bit信息，每一个Bit表示有没有对应接收链的消息。若第1，2，3位分别表示链A,B,C，则110 表示此发送链中的此区块有发送给链A,B的信息，无对链C的信息。因此，接收链的收集者可以通过bitfield信息来判断需不需要从此区块中获取信息。
    

![Message Root b](https://storage.googleapis.com/papyrus_images/63cff9ecb7c1cfd09ebd90eca577ae409eeaa11db9c9d96fa4e8fd48373d7b2a.png)

Message Root b

我们用SCH表示发送链区块头，则**SCH = {MR, water mark, bitfield,…}**，当发送链的验证人验证通过并打包进入中继链后，中继链区块头中也会包含着SCH的信息。**此时，中继链会在其链上储存资源中更新CST（Channel State Table）**。

不同于消息本身，其并不会在中继链中得到储存，但是中继链会储存关于通道状态的表。**表的行由发送链的ID组成，表的列由接收链的ID组成，其中的每一个元素是（sender\_mr, block\_number）组成**。因此每一个cell可以得到一个通道最新更新的时间（block\_numer）与发送链的MR。由于发送链的MR对于每行来说是相同的，因此，CST是以行为单元来进行更新的。

![CST（Channel State Table）](https://storage.googleapis.com/papyrus_images/7cf34f2e852e54bcc79c80d78d682f8c68851a2ff05d952173f0ad5dcab3c83d.png)

CST（Channel State Table）

**将CST每一行的各个cell作为Merkle树的叶子节点来构造出以row\_root为根节点的Merkle树，将CST所有的row\_root作为新的叶子节点可以构造出以XCMP\_root为根节点的Merkle树**。所得到的XCMP\_root**将会被包含进中继链的状态根中**。

![XCMP_root与Row_root](https://storage.googleapis.com/papyrus_images/7602535f9692b45f9c9852f348bfe73ebe65873efaa2291e43bb14e3dc1a24d8.png)

XCMP\_root与Row\_root

对于接收链的收集者而言，其通过查询CST表上的通道信息来判断是否有新的消息其需要去对应的发送链的节点上接收信息，由此实现了验证是否有新的消息的功能。 接收链上的收集者在构建POV区块的时候，需要从中继链上获取相应的证明来证明此时已经获得尚未被处理的正确信息。证明由一组Merkel证明变体组成的轻客户端证明。此证明包括以下几个部分：

*   从XCMP\_root到MR的一组Merkle证明
    
*   从MR到HC的一组Merkle证明
    

除了这组轻客户端证明之外，构建POV区块还需收集人收集得到以下两个信息：

*   发送的消息本身
    
*   最新water mark与上一次water mark之间的HC
    

由此，验证人可以通过亲客户端证明定位到发送链的HC，并且利用两次water mark来定位所有最近发送的但是并未处理的消息，通过对比每个HC上消息的哈希值，与自己接收消息的哈希值，验证是否是正确的消息，并且可以验证是否有消息缺失并未接收到的现象。若有，收集人便会向发送链重新索要相应的信息。

由此做到了对消息正确性与无遗漏性的验证。

### 如何实现有效性

中继链并不能储存过多的信息与执行过多的运算，否则将会严重影响整个系统的运转效率。XCMP的解决方案是只让中继链储存CST，消息并不通过中继链进行处理，而是通过通道来进行传递。

### 如何实现安全性

依靠中继链本身的验证者为平行链提供安全性，因此无需信任平行链是安全的，整个系统确保每一条平行链都是安全的。

IBC原理
-----

IBC全称叫做链间通信协议（Inter-Blockchain Communication Protocol），是Cosmos中zone与zone通信的协议。

每个zone与zone之间并不直接通信，而是分别与Hub通信来实现zone之间的相互联系。这一点与波卡不一样，波卡通信是通过直接通信来实现的，而通过中继链来传递相关的证明并保证平行链的安全性。 IBC协议中包含了三个主要的交易类型：MsgPacket，MsgAcknowledgement，MsgTimeout。

*   MsgPacket：跨链交易数据包，包含跨链交易、目的链的超时高度和时间戳。
    
*   MsgAcknowledgement：响应数据包，包含跨链交易执行成功或者失败的状态。
    
*   MsgTimeout：超时数据包，包含下一个接收包的序列号。
    

IBC的协议流程总体来说比波卡要简单许多，其**简化版的实现流程**如下图所示：

![IBC简化流程](https://storage.googleapis.com/papyrus_images/6e799fc2ed5a383a296a4904890021abc75b543caf7462ac705a8d2d6fe19e19.png)

IBC简化流程

首先是外部跨链交易（TX）向发送链A的Tendermint模块发起请求，验证有效后将会改变链A的账户状态，并且构建MsgPackage至其**出口队列**当中。Hub中的Relayer会不断扫描发送链的出口队列，若发现MsgPackage则会将其传递至接收链B中，接收链B验证通过后会执行并改变相应的账户的状态，执行成功后，会返回MsgAcknowledgement，发送链接收到后，会确认出块。

### 如何实现有序性

IBC采用**Outing 队列与Inputing队列**来对消息进行排序，从而实现消息的有序性。

### 如何实现可验证性与无遗漏性

如上图10所示，**MsgPackage中会包含Proof值，接收链收到MsgPackage后通过Poof与消息本身的哈希值来验证消息的正确性**。

而其**通过Hob relayer的不断扫描出口队列来验证是否有新的已发出但是未处理的消息**，从而实现了消息的可验证性与无遗漏性。

### 如何实现有效性

其并非是由两个平行链之间直接通信，而是通过Hub来进行通信，**由此回避了由于直接接连导致的网络拥堵的现象**。

### 如何实现安全性

**其无法保证平行链是安全的，必须信任平行链是无法作恶的**，而如果接入安全性较低的平行链其整体系统的稳定性将会大幅降低，并且可能会有双花等攻击。

XCMP与IBC对比
----------

### 1\. 通信效率

*   **XCMP**
    

**为了避免平行链之间直接通信使得channel指数增长导致网络拥堵甚至瘫痪的现象发生，目前一条发送链最多只能同时建立100个channel**，意味着一条平行链只能同时与100个平行链进行通信。未来这个数量可能会进一步扩充。其通信效率并不完全取决于中继链的效率。

*   **IBC**
    

同样是为了避免网络拥堵与瘫痪现象的发生，IBC不是通过限制每一条平行链可以通信的数量来解决的，\*\*而是直接不允许平行链之间通信，只允许其与Hub进行通信。\*\*因此，处理效率完全取决于Hub的效率。

### 2\. 开发进展

*   XCMP
    

目前只完成了对XCM格式与HRMP的开发工作，**XCMP仍然在开发过程当中**，**由于其暂未在GitHub中同步，暂时无法得知最新的开发进展**。但是，**由于XCMP是包含在Substrate主体中来进行开发的，Substrate与Cosmos-sdk二者均为Framework，因此通过对比二者的点赞与folk数在一定程度上也能反映二者的差距**。

从项目的folk数与点赞数来看，Cosmos-sdk的点赞与folk数较少，可能从侧面反映了技术的革新性可能并不大。

![Cosmos-sdk Github相关信息](https://storage.googleapis.com/papyrus_images/bc9ba236a187efe13293dc09ec260bf364e7654fdd08923c856064fd67fcdc9a.png)

Cosmos-sdk Github相关信息

![Substrate Github 相关信息](https://storage.googleapis.com/papyrus_images/51f02e181f028659a3f14b676eab72d198ad03fbee9ecdabf0c45c7220814b40.png)

Substrate Github 相关信息

*   IBC
    

**IBC目前已经基本完成了开发**，自2019年8月25日上线第一版以来，不断做出更新，在**2020年10月份推出了较为稳定的第六次更新**。至此以后，虽不断有小调整，但是并无重大的版本更新。并且从图中可以看出，**目前的更新速度放缓，项目基本已经稳定**。

![IBC开发进展](https://storage.googleapis.com/papyrus_images/e18eb597bd0c1888439952a47ec57affce849214af1a8223e80553bd5845b6d9.png)

IBC开发进展

### 3\. 部署便捷性

*   XCMP
    

XCMP是非常底层的协议，类似于HRMP，是通过XCM pallet 与平行链整体的Runtime来进行调用的，其包含在平行链Runtime的开发逻辑当中。

**本文通过挖掘Encointer项目的代码来展示其是如何调用XCMP协议来实现跨链通信的**。

我们从Encointer的预言机的pallet来入手。首先，Encointer在主pallet中引用xcm的库，其目前托管在波卡库中。

![Encointer项目XCMP部署解读 a](https://storage.googleapis.com/papyrus_images/b9a6e26c4ff64ccba039d23e134e4c874817a349637682193c16c140ee399051.png)

Encointer项目XCMP部署解读 a

其次在主要配置中声明XcmSender的类型。

![Encointer项目XCMP部署解读 b](https://storage.googleapis.com/papyrus_images/fdccae83715c38900d41c713d9a6faa18bb2e3de68282ed3110f31110a02e427.png)

Encointer项目XCMP部署解读 b

之后**在主逻辑Module中利用XCM pallet中的方法来构造交易**。而如Transact等这类通信函数已经高度抽象化与高度封装，不需要对底层的XCMP的处理细节进行声明即可实现。

![Encointer项目XCMP部署解读 c](https://storage.googleapis.com/papyrus_images/fc826abc47509a6c5a975f614eaa0d16b309487c33f223200bd95640b112833f.png)

Encointer项目XCMP部署解读 c

其跨链消息功能的大致调用情况如上所述，因此可见，XCMP是非常底层的协议，上述的调用基本不会涉及到相应的原理，总体来说调用还是较为简洁。

*   IBC
    

IBC的部署方法由于**笔者目前对Cosmos的开发代码并不是十分熟悉，因此不采用上述的深入刨析项目代码的方式来分析，而是采用分析关键代码的作用来进行阐述**。

首先要再module中声明 –ibc参数，**以此将所有ibc的逻辑引用到此module中**。代码如下所示：

`starport module create blog --ibc`

其次如果要发送消息的话，需要再blog模块中首先生成post

`starport type post title content --module blog`

然后发送posts

`starport type sentPost postID title chain --module blog`

管理post的超时信息：

`starport type timedoutPost title chain --module blog`

发送确认消息可以用：

`AppendSentPost（）`

上述为IBC部署的大致过程，因此可以看出如同XCMP一样，其也为非常抽象的封装完整的函数，在开发中并不会接触的底层的逻辑。

由于笔者只是从函数的逻辑上进行分析，没从实际的项目开发中进行分析，由此可能对于真实的开发难度的理解有一定的偏差，因此**后续计划深入Cosmos开发代码，从实际项目开发情况中分析这两个技术实际部署的难易程度**。

### 4\. 应用场景

*   XCMP
    

**XCMP在设计之初，就可以不仅仅可以用于平行链之间的消息的传递，其更可以实现在智能合约之间，在pallet之间，在不同的跨链桥之间，在SPREE之间进行通信**。

例如Phala团队利用XCMP协议计划实现的功能，**图18中智能合约之间均可以与波卡主链进行通信。**

![Phala项目计划运用XCMP协议实现的功能](https://storage.googleapis.com/papyrus_images/0075b513a7790e9d343fdf407e861838472b78152f72d4babb102f2745349c32.png)

Phala项目计划运用XCMP协议实现的功能

*   IBC
    

目前来说，**IBC主要运用的场景仍为ICS27-跨链交易**，**其并没有明确针对于智能合约、桥之间的通信功能**，是一个较为简洁的方案。

![IBC目前的应用案例](https://storage.googleapis.com/papyrus_images/065ec6e6dd400d05e94e988a3f9e9e88f263330d260bd876fd54ece8d32f3084.png)

IBC目前的应用案例

### 5\. 安全性

*   XCMP
    

从技术原理来进行解析，可以发现，XCMP对于平行链的安全性是**统一由中继链进行保证的，因此跨链传输的时候不需要信任平行链的安全性，整个系统的稳定性较高**。**缺陷是如果中继链作恶，整个系统将会崩溃**。

*   IBC
    

而对于IBC来说，其总体的协议较为简单，**其并不保证平行链的安全性，需要平行链自身对于安全性有保证**。因此若接入安全性较低的平行链的话，会对整个网络中与平行链相关的平行链产生双花等攻击，整个系统的稳定性大大降低。**但是好处是减少了跨链系统的维护成本和降低了设计实现难度，并且由于平行链作恶行为无法影响全系统，只能影响与平行链相关的链条，因此又潜在的降低了整个系统崩溃的风险**。**此外，由于不受到整个网络中安全性的限制，可以满足对于某些想要保留自己链对网络控制权的需求（如币安）**

本文只刨析了Polkadot网络中的Encointer项目代码，并未刨析Cosmos中的项目代码，后续计划深入Cosmos代码，从实际项目开发情况中分析XCMP与IBC的差异及实际部署的难易程度

---

*Originally published on [Fan ](https://paragraph.com/@fan-3/xcmp-ibc)*
