在平行链B要向平行链A发送XCMP消息前。平行链B到A、C、D、E都建立了通道并发送过跨链消息。链A还需要所有消息的从MR到MQHC元素的merkle root。
导读:上一篇文章Polkadot 茶溪岸啤(XCMP),干杯!主要介绍了XCMP一些基本内容,还有XCMP消息路由方式。
「总体而言,XCMP主要分为2部分:XCMP消息的分发、XCMP消息的存取」,本文主要就是介绍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设计比较复杂,目前还在实现中,未来可能会有一些变动,让我们共同关注。