Polkadot:畅想一种异构的多链架构(第三部分)

本文译者:岳利鹏

6 协议细节

本协议可以大致分为三个部分:共识机制、平行链接口、跨链交易路由系统。

6.1 中继链操作

中继链会类似以太坊,也是基于状态的,包含一个账户信息到状态存储的映射关系,其中信息主要包含余额和交易计数器(防止重放)。把账户系统放在这里的目标是:记录每个身份在系统里控制了多少权益。但还有一些值得注意的差异:

不能通过交易部署合约;这是为了让中继链尽量缺乏功能性,不支持公开部署合约。

没有资源计数器(gas);因为公众能够调用的一些功能是固定的,gas记录系统的原理就不适用了。因此在所有功能中,会使用一个更通用的手续费标准,这样就能更高效地执行那些动态代码,交易格式也会更简单。

会有一些包含特殊功能的默认合约,他们管理交易的自动执行和网络消息的输出。

中继链会有一个基于EVM的虚拟机,但为了最大程度地简化会做很多修改。它会有一些内置合约(类似于地址在1-4之间的那些以太坊合约)运行平台的特定功能,包括共识合约、验证人合约、平行链合约。

如果不用EVM,很有可能会选择Web-Assembly(Wasm);这样的话,所有结构还是相似的,但是这些基于Wasm的内置合约使用的是通用功能的语言,而不再是EVM上面的那些带有很多限制的不成熟语言。

还可能借鉴目前以太坊上衍生出来的其他方面的概念,例如在Serenity版本中提出来一些改变,比如为了能在一个块里并行执行那些没有状态冲突的交易,将交易的回执格式简化等。

Polkadot有可能会部署一个类似于Serenity的纯净(pure)区块链系统,它不包含链的任何基础协议。但我们觉得这会带来更多的复杂性和开发不确定性,所以不太值得在目前阶段就去实现这么一个更高效且简介的伟大协议。

为了管理共识机制,需要很多小片儿的功能:验证人集合、验证人机制、平行链等。这些都可以放在一个整体的协议中。然而为了实现模块化,我们会把这些描述成中继链的合约。这意味着他们都是中继链共识机制管理的对象(类似面向对象语言),但不一定是类似EVM的字节码,也不一定能通过账户系统寻址。

6.2 权益合约

这个合约管理着验证人集合:

哪些账户是验证人;

哪些在短期内可以变成验证人;

哪些账户为了提名验证人而质押了权益

每个人的属性,包括余额、可接受的押金比例、地址列表、会话(session)身份

它让账户在想成为验证人的时候可以来注册(需满足某些要求)、也可以提名某用户、在想退出验证人角色的时候还可以来退出。它自身还包含了一些用于验证和达成一致性的功能。

6.2.1 权益代币的流动性

通常我们希望能从网络中把尽可能多的权益代币都抵押进来,因为这关系到抵押权益的总市值和网络的安全性。这可以很简单地通过货币增发和收益分发来激励验证人。然而,这么做会出现一个问题:如果代币都被抵押在权益合约里,用于防止作恶,那么如何保证代币在一定程度上的基本流动性,进而支持价格发现呢?

一种方法是提供一个前向衍生合约来管理由抵押代币衍生出来的二级代币。但这在非信任的情况下很难实现。这些衍生代币无法等值交易,原因就和欧元区的不同政府发行的债券一样:抵押的代币有可能被扣减而价值降低。至于欧洲政府,他们还可能会违约。对于由验证人质押而来的代币,要考虑到验证人的恶意行为可能会遭到惩罚的情况。

基于我们的原则,我们选择了一种更简单的方案:不能把所有的代币都质押进来。这意味着一部分(可能20%)代币会被强制保持可流通的状态。尽管从安全的角度上讲,这个方案不完美,但也没有从根本上影响网络的安全。相比于100%的质押,也将只可能没收80%的权益作为赔款。

我们还将会使用一个反向拍卖机制来公平地决定质押代币和流通代币的比例。有兴趣成为验证人的代币持有者可以给权益合约提交一个请求,说明他们希望支付的最小比例。每次会话(会话可能每个小时算一次)开始的时候,系统会根据每个意向验证人的押金和支出比例来填满验证人的插槽。一个可能的算法是从提交押金的验证人中,选择那些押金满足如下条件的人:押金不高于“总押金目标/插槽数量”且不低于“次低押金”的一半。如果不够填满这些插槽,那么我们会迅速降低这个“次低押金”来满足条件。

6.2.2 提名

用户可以把手中的权益代币非信任地交给一个已激活的验证人,让他们来履行验证人的职责。提名通过一个“批准-投票”系统来完成。每个准提名人可以给权益合约提交一个声明,指出他们信任的可以履行职责的一个或多个验证人的身份。

在每个会话期间,提名人的押金会散布给一个或多个代表他们的验证人。这些验证人的押金是等额分配的。提名人的押金用于验证人承担他们的责任,将能够获得利息或承受相应的扣减。

6.2.3 押金没收/烧毁

验证人的某些行为会导致惩罚性地没收他们的押金。如果押金降低到允许的最小值,会话就会提前结束,另一个会话开始。一个不完整的将导致惩罚的行为列表:

属于一条平行链的验证人小组,却不为该平行链的区块提供合法性验证;

签名了该平行链一个不合法的区块;

不去处理出口队列中被投票为已生效的消息;

不参与到共识流程中;

在中继链两个竞争性的分叉上同时签名。

有些行为会威胁到网络的完整性(例如签名不合法的平行链区块,或者签名多个分叉),为了驱逐这些验证人,会没收他们的押金。另外还有一些不那么严重的行为(例如不参与到共识流程中)或者那些无法清晰判别的行为(例如处于一个低效的小组),只会导致一小部分的押金被处罚。在后一种情况中,可以采用一个二级小组的搅拌功能来让恶意节点遭受到比正常节点更多的惩罚。

因为实时同步每条平行链的区块是个非常大的工作,所以在某些情况下(多叉签名和不合法签名),验证人无法很方便地检测到自身的不当行为。在这里有必要指出验证人之外的一些参与方也可以举报这些非法行为,并从中获得奖励,但他们和钓鱼人还不太一样。

因为有些情况非常严重,我们希望可以很简单地从没收的押金里支付奖金。我们通常倾向于使用烧毁代币的方法进行重分配,而不是采用批量转账的方法。烧币可以从整体上增加代币的价值,也就可以补偿整个网络而不仅是涉及到的特定几方。这主要是作为安全防范机制,只有非常恶劣的行为才会到会非常大金额的惩罚。

很重要的一点是奖金必须足够高才能让网络觉得验证工作是值得做的,当然也不能比成本高太多,否则会招致那些足够有钱的、精心策划的国际级别的犯罪黑客攻击那些不幸的验证人,迫使他们做出非法行为。

规定的奖金也不能比恶意验证人的押金高太多,否则会不正当地激励非法行为:验证人为了奖金自己举报自己。解决方法是要么直接限制成为一个验证人的最小押金量,要么间接教育提名人:如果验证人押金太少,他们可能没有足够的动机来遵守规则。

6.3 平行链的注册

这个模块用于记录系统中的每个平行链。它是个相对简单的类似数据库的结构,管理着每条链的静态信息和动态信息。

静态信息包括链的索引(一个整数)和验证协议的标识。协议标识用于区分不同的平行链,只有这样,验证人才能运行正确的验证算法,然后提交合法的候选块。一个最初的概念验证版本会关注于如何把一个新的验证算法放在客户端中,这样每增加一个新种类的区块链,就需要一次硬分叉。然而在保证严格和高效的情况下,还是有可能不用通过硬分叉就能让验证人知晓新验证算法。一个可能的实现方法就是用一种确定的、本地编译的、平台无关的语言来描述平行链的验证算法,例如WebAssembly等。为了验证这种方法的可行性,我们还要做更多的调查,毕竟如果能够避免硬分叉还是会有很大优势的。

动态信息涉及交易路由系统,比如必须对平行链的的入口队列进行全局共识(在下一节讨论)。

必须通过全民公投才能注册新的平行链。这本来可以直接内部管理,但通过一个外部的全民公投合约会更好,因为这个合约还可以用于更多其他场景的治理。关于平行链投票注册系统的具体参数(例如法定人数、多数派的比例)会用形式化证明做成一个不常更新的“主宪法”系统,当然初始阶段也可能只是用传统的方法。具体的公式不在本文的讨论范围内,例如占2/3的多数派通过,并且全系统1/3的代币都参与了投票才算通过。

还有一些暂停和删除平行链的操作。我们希望永远不要暂停一个平行链,但这个设计是为了能应对平行链的一些紧急情况。最明显的情况是由于验证人运行了平行链的多种客户端实现,导致可能无法对某区块达成共识。我们也鼓励验证人使用多种客户端实现,以便能尽早检测到这类事情,防止押金被扣减。

因为暂停操作是个紧急措施,所以会采用验证人动态投票的方式,而不是通过全民公投。对于重启操作,可能直接通过验证人投票,也可能通过全民公投来完成。

删除操作平行链只能通过全民公投来进行,而且要提供一个宽松的平滑退出过渡期,能让它们成为一个独立的区块链或变成其他共识系统的一部分。这个期限可能是几个月,而且最好由平行链根据自身的需求来制定。

6.4 打包中继链区块

区块打包的过程本质上是共识的过程,也是把基本的数据变得有意义的过程。在一个PoW链里,打包有一个同义词叫挖矿。在本方案里,它涉及收集验证人对于区块有效性、可用性、一致性的签名,这些区块包括中继链区块和它所包含的全部平行链的区块。

底层的BFT共识算法也不是当前的工作范围。我们不描述它,而是使用一种原语描述一种由共识推动的状态机。最终我们希望能受到一些现有共识算法的启发:Tangaora(Raft的BFT变体)、Tendermint和HoneyBadgerBFT。共识算法需要并发地对多条平行链达成共识。假设一旦共识达成,我们就可以不可辩驳地记录哪些人参与了其中。我们也可以在协议内把不正当行为的人缩小到一个小组中,里面仅包含哪些恶意参与者,这样就可以在惩罚时可以降低附带伤害。

以签名声明形式存在的这些证明、中继链的状态树根和交易树根一起存储在中继链的块头里。

对于中继链区块和平行链区块的打包过程是在同一个共识生成机制中,两类块共同组成了中继链的内容:平行链并不是由他们的小组隔离地进行“提交”之后再被收集的。这虽然导致中继链的流程更加复杂,但也让我们可以在一个阶段里就完成整个系统的共识,能够将延迟最小化,并且能支持更加复杂的数据可用性,这在路由流程中将会很有用。

可以用一个简单的表格(二维的)来建模每个参与方的共识机。每个参与方都有一系列以签名形式存在的来源于其他参与方的信息,描述着每个平行链的候选块和中继链的候选块。这些信息有两部分数据:

可用性:对于出口队列里这个块的已提交交易,验证人是否有足够的信息才能在下一个块正确地验证平行链的候选块?他们可以投1(知道)或0(不确定)。当他们投了1,他们就承诺在后续的投票中也要这么投票。后面的投票和这个不对应会导致惩罚。

有效性:平行链的区块是否有效,是否包含了引用的所有的外部数据(比如交易)?这和验证人对平行链的投票相关。他们可以投1(有效)、-1(无效)或0(不确定)。只要他们投了非0,他们就承诺在后续的投票中也要这么投票。后面的投票和这个不对应会导致惩罚。

所有验证人都必须投票;在上面的规则限制下,还可以重新提交投票。共识流程可以像很多标准BFT共识算法那样来建模,每个平行链是并行的。除了有很小的概率把少数恶意参与者都被分配到了同一个平行链小组之外,共识算法在整体上还是能支撑网络,最坏的情况也不过只是出现一个或多个平行链因空块而死锁的情况(还有一个回合做出惩罚)

判断一个独立区块是否有效的基本规则(允许全部的验证人作为一个整体达成共识,然后这些平行链区块就成为中继链上具有一致性的数据引用):

需要有至少三分之二的验证人投票“是”,并且没人投“否”。

需要超过三分之一的验证人对出口队列消息的可用性与否投票“是”。

对于有效性而言,如果至少有一个“是”且至少有一个“否”投票,一个特殊的条件就开启了,整个验证人就必须投票决定是否有恶意参与者,或者是否产生了意外的分叉。除了有效和无效之外,还支持投第三种票,等效于同时投了“是”和“否”,表示这个节点有相互冲突的意见。这可能是因为节点所有者运行的多种客户端实现而产生了分歧,也预示着平行链协议可能存在不清楚的地方。

当所有验证人的票都被记录过后,发现赢的那个意见少于一定数量的票(详细参数最多可能是一半,也许更少),那就可以假设平行链发生了意外的硬分叉,这个平行链的共识就会被自动暂停。否则,我们假设就是有恶意行为发生,并惩罚那些给输的那个意见投了“是”票的验证人。

结论是只有足够的签名票数才能达成一致性,然后中继链的区块就打包完成了,开始打包下一个区块。

相关文章:

Leave a Reply

消息接收
avatar
500
wpDiscuz