共识机制
区块链节点使用共识引擎来商定区块链的状态。 本文涵盖了区块链系统的共识机制的基本知识点:共识算法如何在Substrate框架中与 Runtime 交互,及框架内所包含的几个共识引擎。
状态机和冲突
区块链的 Runtime 就是一个 状态机。 它有一些内部状态和状态迁移函数,使得它可从当前状态迁移到下一个状态。 在大多数 Runtime 中,某些状态可以有多个有效迁移函数迁移到多个未来状态,但只能从中选取一个进行迁移。
区块链必须对下述内容达成一致:
- 初始状态,也叫做“创世区块”,
- 一系列状态迁移,每个迁移被称为“区块”,以及
- 一个最终(当前) 状态。
为了在转换之后对结果状态达成一致,区块链状态迁移函数 里的所有操作必须是具备确定性的( deterministic)。
冲突排除
在中心化系统中,中央服务器通过先后顺序从互斥的备选状态转换事务中进行选择,在冲突发生时选择第一个备选方案。 在去中心化系统中,不同节点可能会看到不同的交易顺序,因此它们必须使用一套更加精心设计的方法来剔除交易。 更加复杂的是,区块链网络力求容错, 这意味着即使一些参与者不遵守规则,整个网络也应继续提供一致的数据。
区块链将交易分批纳入区块,并采取一些手段来选择由哪个参与者拥有提交区块的权力。 比如说,在用工作量证明的链中,第一个找到有效工作量证明的节点就有权提交区块到链上。
Substrate 提供了几个区块生成算法,也允许您创建自己的算法:
- Aura (轮询调度)
- BABE (基于时隙)
- 工作量证明
分叉选择规则
先说基础,一个区块包含一个区块头和一系列的 外部交易。 区块头必须包含一个对父区块的引用,以至可一直追溯回到创世区块。 当两个区块引用到同一个父区块时,就表示出现分叉。 而分叉是必须解决的,这样才有一条标准规范的链。
分叉选择规则是一个在区块链中选择应当被延续的“最佳”链的算法。 Substrate 将这概念展露在 SelectChain
Trait.
Substrate 允许你编写自定义分叉选择规则,或者从给定的规则中选择一个。 例如:
最长链规则
最长链规则简单来说,就是把最长的链作为最佳链。 Substrate 把选择链的规则放在 LongestChain
结构体。 GRANDPA 使用最长链规则进行投票。
GHOST 规则
GHOST(The Greedy Heaviest Observed SubTree,贪婪最重可观察子树)规则是指从创世区块开始,每一个分叉都是通过递归地选择包含最多区块的分支来解决的。
区块生成
区块链网络中的一些节点可以生成新区块,该过程称为“创建区块”。 究竟哪个节点可以创建区块,取决于你使用什么样的共识引擎。 在中心化网络中,可以是由单个节点来创建所有的区块。但在完全无许可网络中,必须要使用一种算法来选择每个区块的创建者。
工作量证明
在类似比特币这样的工作量证明系统中,任何节点在任意时刻都可以生成区块,只要它成功解决了一个计算密集型难题。 解决难题需要花费CPU时间,因此矿工只能使用他们的计算资源来生成区块。 Substrate 提供一个工作量证明区块生成引擎。
时隙
基于时隙的共识算法必须包含一组已知的、允许生成区块的验证者的集合。 时间被分成离散的时隙,在每个时隙中只有一部分验证人节点可生成一个区块。 指定哪些验证者可以创作区块的方法因共识引擎的不同而不同。 Substrate 提供 Aura 和 Babe,这两者都是基于时隙的区块生成引擎。
最终确定性
不管在什么系统中,用户都想知道他们的交易是什么时候确定完成的,区块链也一样。 在一些传统系统中,当收据交出或文件签名时,就是最终确定的了。
如果使用前述的区块创建模式和分叉选择规则,交易是永远不能最终确定的。 总是有机会出现一个更长的(或更重的) 链,从而回滚你的交易。 当然,在某个特定区块之上构建的区块越多,就越不可能回滚。 这样的话,采用适当的分叉选择规则的区块生成算法只提供了概率上的最终确定性。
当需要明确无误的最终确定性时,可以在区块链逻辑中添加一个最终确定性小工具。 固定验证人集合的成员为区块的最终性进行投票,当某个区块拥有足够数量的投票时,该区块将被视为是最终确定的。 在大多数系统中,这一阈值为2/3。 以这种方式确定的区块无法被回滚,除非采用像硬分叉这样的外部协调手段。
一些共识机制将区块生成和最终确定性组合在一起,就像这样:区块最终确定是区块生成流程的一部分,除非块
N
已最终确定,否则新的N+1
块无法创建。 但是 Substrate 分离了这两个过程,允许你使用任何具备概率上保证最终性的区块生成引擎,或者将其与一个最终确定性配件结合起来以具备完全的的最终确定性。
在使用最终确定性小工具的系统中,必须修改分叉选择规则以考虑最终确定性博弈的结果。 例如,节点应该选取包含有最近的最终确定区块的最长链,而不是简单地选择最长链。
Substrate中的共识
Substrate 框架配备了几个共识引擎,可以提供区块创建或者最终确定性。 本文简要概述了Substrate自身提供的共识引擎。 我们欢迎开发者提供自己的共识算法。
Aura
AURA 提供了基于时隙的区块生成机制。 在Aura中,通过一组已知的权威成员来生成区块。
BABE
BABE 也提供了基于时隙,通过一组已知的验证人节点来生成区块的方法。 在这些方面,它类似于Aura。 不同于AURA, 时隙分配是基于对可验证随机函数(VRF) 的计算。 在每一个时段 (epoch)中,每个验证节点得到一个权重。这个时段被分解为若干时隙,而验证节点在每个时隙里计算自己的VRF。 当一个验证者在该时隙的VRF输出值小于它的权重时,就可以创建一个区块。
由于同一个时隙中可能有多个验证者能够生成区块,分叉在BABE中要比Aura更常见,即使在良好的网络条件下也是常见的。
Substrate的BABE实现也提供了一个备用机制,用于在某个时隙中没有验证者被选中的情形。 分配这些“次要”时隙使得 BABE 实现了恒定的区块时间。
工作量证明
工作量证明 的区块生成不是基于时隙,也不需要已知的验证节点群。 在工作量证明中,任何人可以在任何时间生成一个区块,只要他们能解决一个计算密集性问题(通常如哈希原像搜索)。 通过调整这个问题的难度,可以统计性的实现出块的目标时间。
GRANDPA
GRANDPA 会最终确认区块。 它有一个类似BABE的权威验证人集合。 然而 GRANDPA 并不生产区块; 它只是监听其它共识引擎(如上面讨论的三个引擎)所产生的区块。 GRANDPA 验证人对 链,而不是区块进行投票。换言之,当验证人对他们认为 "最优" 的区块投票时,他们同时也对该链前面的所有区块作了投票。 一旦超过 2/3 的 GRANDPA 验证人给某一个特定的区块投了票,这个区块就被视为是最终确定的。
与Runtime协作
我们已经描述了完全在 runtime 之外就可以正常工作的最简单的静态共识算法。 然而,许多共识引擎通过添加需要与 runtime 协作的特性而变得更强大。 这方面的例子包括难度可调整的工作量证明、验证人轮换的权威证明,以及基于质押权重的权益证明网络。
为了实现这些共识机制功能,Substrate 有 DigestItem
, 就是从保存着共识机制的节点外部与 Runtime 相互传送的信息。
进一步学习
由于BABE和GRANDPA都将被用于Polkadot网络,Web3基金会提供了研究级别的算法介绍。
包括 GRANDPA 在内的完全最终性算法至少需要 2f + 1
个可靠节点, 其中 f
是错误或恶意节点的数量。 查看这些开创性的论文 Reaching Agreement in the Presence of Faults 或Wikipedia: Byzantine Fault,以了解更多的这些概念以及阈值的来源.
并非所有共识协议都定义了一个单一的、规范性的链。 有些协议在具有共同父节点的两个区块的状态变化不冲突时,可以验证directed acyclic graphs (DAG) 。