Polkadota XCMP的设计大致是完成其目标的。但也因为XCMP设计比较复杂,目前还在实现中,未来可能会有一些变动,让我们共同关注。
导读:上一篇文章Polkadot 茶溪岸啤(XCMP),干杯!主要介绍了XCMP一些基本内容,还有XCMP消息路由方式。
「总体而言,XCMP主要分为2部分:XCMP消息的分发、XCMP消息的存取」,本文主要就是介绍XCMP消息的存取。
文末答题有惊喜:剩下3道题目准备好接招了吗?
前文回顾
如果上篇文章的内容你大致都能看懂,恭喜你,已经很厉害了!!
但是,请做好心理准备,因为接下去的内容将更加复杂,我们将用尽可能清晰的方式来解释。
XCMP消息的存取
当接收链接收到消息后,接下去要进行的流程是:处理消息,然后将消息及相关证明放进新块构建好后交给验证人,并最终确认出块。这个流程是比较复杂的,涉及到的新数据结构也很多。
先来看看一些接下去要用到名词的解释:
Para X
表示平行链X或者平行线程X。
因为平行链要接入Polkadot需要购买一个专用插槽Slot,Slot数量少且贵,所以更精益的方式是使用平行线程。平行线程接入Polkadot不需要专门购买一个Slot,而是按块付费。平行线程与平行链在开发上基本上一样,而且也能使用Polkadot的各种功能。
平行链
当我们说平行链的时候,其实是指由平行链收集人节点构成的区块链网络。如果提到了验证人,一般会专门指出这是验证人节点。
好,接下去我们借助一张看起来有点复杂、但其实比较清晰的图来讲解XCMP消息的存取。

上图是我们自己总结的XCMP消息存取的全景图,基本上概括了XCMP消息存取的全部内容。
图中描述了Para B要给Para A发送消息 m2020。虽然Para还可能表示平行线程,但接下去以平行链为例(平行线程也是类似的)来解释这张图,阐述XCMP的消息存取流程。
在平行链B要向平行链A发送XCMP消息前,首先要开一个链B通向链A的通道(Channel),然后接下去的流程是:
1. 平行链B发出消息 m2020(放至出口队列),并在新出的块 (假设为#3号块) 中包含了此消息。
2. 平行链B作为发送链,会维护对每个接收链的一条MQHC(Message Queue Hash Chain),可以看成是一种链表(如图中,平行链B到A、C、D、E都建立了通道并发送过跨链消息,所以平行链B有4条MQHC)。
3. 当平行链B将消息m2020包含进区块并最终被验证人验证确认后,其区块头会存储到中继链的区块中(如本例中B的#3号区块头)。这样一来,中继链就拿到了链B的#3号块的MR,bitfield、watermark三个关键数据结构。根据这三个数据结构,中继链就会做一些有趣的事情。
4. 中继链上有一个数据结构叫做CST(Channel State Table),中继链于是会使用该新提交的平行链区块头里的MR去更新自己的CST里相应的一行。
5. 当平行链A开始构建新PoV区块时,将会需要其所有消息的proof。
另外还有一些细节:
1)平行链的状态里不光要存储MQHC的链表头的Merkle proof,还要存储MQHC所有元素的Merkle proof(它们也曾当过链表头)。
2)如果确认消息被执行,则MQHC里的链表可以丢弃已经执行过的消息的对应元素(但不一定要求立即丢弃,因为可以多存一会起到冗余的作用)。
对上面第5点——平行链PoV区块的构造,Polkadot官网上有一个简例。

以上面这张图中的链B为例。链B给链A发送了跨链消息,且通过Channel State Table可知,链A上一次处理链B发过来的消息的时间是中继链块号位rc_1的时候,上一次的watermark1为(rc_1, A),而当前的watermark2为(rc_6, A)。
假设链A要出新块,其要把[watermark1,watermark2) 之间的跨链消息都进行处理。链A出块需要的数据有(以下的1、2、3就是构成整个的proof):
1) 中继链State Root到CST row_root的Merkle proof(红色部分);
2) CST row_root到 (MR,block_number) 构成的表项的Merkle proof(蓝色部分);
3) MR到MQHC链表头的Merkle proof(橙色部分);
4) 所有消息对应MQHC的元素(图中左下方绿色矩形);
5) 所有消息的原文(图中左下方绿色信封);
最后当平行链构造完PoV区块后,验证人会对其进行验证,验证通过则完成出块,然后区块头会上到中继链,中继链更新状态,而发送链通过查询中继链也能知道自己发出的消息最终被处理完成了。
总结
本次Polkadot XCMP的干货文章到此就结束了。这杯茶(X)溪(C)岸(M)啤(P)的味道如何?
XCMP的内容,尤其是本篇中讲到的XCMP消息存取部分,还是比较复杂的,用到了很多新创造的概念,比如消息哈希链表(MQHC),以及各种类型的Merkle树(消息树、CST Item构成的树、CST Row构成树、状态树等等)。确实很难一次性看懂,建议大家多看几遍(划重点:可以仔细看看我们画的那张XCMP消息存取的图)。
之所以设计得这么复杂,是为了XCMP的设计目标:快速、有序、可验证、无遗漏。
XCMP的设计主要分为XCMP消息分发和XCMP消息存取,现在我们回顾下,Polkadot是否实现了其设计目标:
消息分发:通过平行链直接直接发消息,而不中继链达到了快速√。
消息存取:通过watermark及其相关机制达到有序√、无遗漏√的目的;通过MQHC、各种Merkle树及Proof做到了可验证√。
综上,Polkadota XCMP的设计大致是完成其目标的。但也因为XCMP设计比较复杂,目前还在实现中,未来可能会有一些变动,让我们共同关注。
课后小习题
一共准备了5个小题目
(都是单选,包括了上篇文章的2个题目,把你的答案集齐5个给桔子,前五名全对的小伙伴有惊喜好礼哦😯)
1. 以下内容中,不是Polkadot XCMP设计的目标的是?
【A】快速
【B】消除跨链消息的「饥饿」现象
【C】高效
【D】可验证
2. 根据本文内容,目前在Polkadot XCMP不可能发生的消息路由方式的是?
【W】发送链将跨链消息发送给一个自己的全节点,该全节点转发至接收链
【X】接收链的收集人去找发送链的钓鱼人拿跨链消息,然后在本链的网络中gossip这个消息
【Y】发送链将跨链消息发送给一个中继链的全节点,该中继链全节点转发至接收链
【Z】接收链的验证人主动去找发送链的验证人拿跨链消息,然后在本链的网络中gossip这个消息
3. 下列关于MQHC的说法错误的是?
【H】 MQHC会存储在平行链的区块头里,而且因为平行区块头上中继链,所以中继链也会存储MQHC
【I】 MQHC是指Message Queue Hash Chain,MR是指Message Root
【J】MQHC的链表头作为叶节点构成的树的树根为称为消息根Message Root
【K】 当拥有MR、MQHC链表头的Merkle Proof、MQHC链表头、链表头包含的消息原文时可以证明链表头里的消息原文的存在性和正确性
4. 下列关于CST的说法正确的是?
【L】CST的全称是Channel Send Table
【M】CST是按列存储的,每一列的表项对应相同的接收链
【N】CST除了一张表外,还有第二部分映射(para_id => row_root),其中row_root会作为叶子继续构出一棵Merkle树,其根为XCMP_Root
【O】当新的平行链区块头到来时,中继链会根据区块头里的交易树的树根去更新CST
5. 关于接收链进行PoV区块的构建的下列说法中错误的是?
【A】中继链状态根(State Root)路径到CST的表项分为2部分,先从State Root到row_root,再从row_root到表项,因此从State Root直接到表项里的MR的整个merkle proof被称为「nested proof」
【B】PoV区块出块是一步完成的,没有比较明显先构建、再验证确认的分割阶段
【C】基于State Root的那些proof需要在同一时刻构建,这样这些proof才能基于中继链的同一个State Root
【D】PoV区块里需要包含内容至少有:所有的消息原文,及其对应的MQHC元素,及其整个的proof
5题全对的前五名小伙伴
会有好礼相送哟!
作者简介
楼嵩
来自致力于「构建区块链互联网络,打通价值孤岛」的BitXHub团队
研究方向:Web3+