书接前文,GHAST 机制的核心是一套判断整个系统当前是否处于特殊状态、是否需要采用自适应权重的规则。
判断一个区块是普通区块还是特殊区块的依据,必须也只能是这个区块的“历史树图结构”——这个结构包含了矿工在产生该区块时的主观视角下能看到的所有可被其他人验证的信息。
正常的树图结构 vs 异常的树图结构
在接下来的讨论中,我们把看起来没有受到攻击,应该生成普通区块的历史树图结构称为“正常的树图结构”,另一种需要自适应调整区块权重的情况称为“异常的树图结构”。
GHAST 规则首先要解决的就是判断一个树图结构是不是正常的。
为了方便理解,让我们从几个简单的例子出发,看一下矿工(节点)应当如何根据看到的树图结构判断整个区块链网络的运行状态。
例子 1
在例子1的图中,绝大多数区块都在一条主链上,偶尔有一个区块落在主链之外,但是也很快就被后面的主链区块引用。
实际上,这也是以太坊在一般情况下的运行状态。这种状态代表了一个运行良好,没有受到攻击,因此也几乎没有分叉的区块链网络。
这种情况下,每一个区块的确认时间都与设计的确认时间基本一致,不需要用到特殊区块。
例子 2
在例子2的图中,有两个大小相近的分支,且每个分支上都有比较多的区块。
虽然此时的树图看上去是下面分支的权重略大一点点,但是考虑到网络中区块传输的延迟,很有可能在另一些诚实节点看来,上面的分支权重更大。
这种情况下,从分叉的区块开始,后面的区块都无法确认。
因为现在两个分支都还没有显示出足够的优势。这时就需要再“让子弹飞一会儿”,等算力占优势的那个分支上累积了足够多的工作量,权重显著超过另一个分支以后才能确认之前的区块。
在通常的情况下,有更多算力支持的分支会很快在权重上积攒出足够的优势,之前的区块就可以确认了。
比如说比特币上很少见到超过三个区块的分叉,以太坊上超过十个区块的分支也很少。
正常情况下,几乎不可能有两个大小相近、且都有很多区块的分支出现。如果观察到这样的情况,就说明很可能整个区块链网络遇到了严重的问题,比如说正在遭受平衡攻击。
因此,这时候区块链网络的运行状态是异常的,我们需要放慢出块速度让算力重新集中,尽快解决分叉问题。
例子 3
下面我们来看一个更复杂的案例:
如果把上图中的引用边(虚线)去掉,我们可以看到一个更清晰的树状结构:
忽略掉引用边后,可以清晰地看出树的结构有一条主链以及频繁出现的分叉,但是好在每个分叉都没有变得很大。
整体上来看,大家不断地对新的主链区块达成共识,一切看起来都是岁月静好的样子。然而,如果仔细观察虚线的引用边,不难发现一个细节:
上下两侧在“分叉”上的区块都在互相引用对方,而主链区块却没有引用任何两侧的区块。
这是一种异常的情况,导致这个情况有两种可能:
• 一种可能:两侧的区块都是由攻击者生成并且藏了一段时间的,主链区块生成的时候没有看到这些区块,自然也不可能引用它们;
• 另一种可能:中间主链的区块才是攻击者生成的,攻击者故意没有引用两侧的区块。
在这个案例中,由于主链的区块总数少于两侧区块的总数,所以我们更倾向于第二种情况。实际上,这样的历史树图结构表明区块链网络很可能正在遭受到一种比较高级的攻击(参见之前的《Conflux研究组 | 最重链规则缺陷2:你的主链我做主》)。
通过这种攻击方式,攻击者有可能让一个藏了很久的区块成为诚实节点认可的主链区块,从而实现双花攻击。
通过这个案例我们可以看出,没有引用边的 GHOST 规则是完全无法察觉出异常,并对这种双花攻击做出预警的。
GHOST 居然有这样的缺陷,是不是原始论文有错误呢?严格来说倒也不是。
原论文用一个很“狡猾”的方式绕开这个问题:在 GHOST 的确认规则中,你需要知道每个主链区块是什么时候生成的——哪怕这个区块是一个被攻击者藏了很久的区块。
但在现实中,想要“火眼金睛”地看破每个区块的真实生成时间是很难做到的。
GHAST 的判断规则
这三个例子或许能够帮助你对“正常的树图结构”有一个大概的感觉。
在这里,我们直接给出 Conflux 最早设计出的规则:给定树图结构,我们对每一个主链区块 b 计算如下比值:
(b 的子树权重)/ (所有区块 - b 的父亲区块的祖先区块)
如果这个比值大于某个常数(比如 0.6),说明在所有生成时间可能晚于 b 的父亲区块中,多数区块都在 b 的子树中。如果本身分母也比较大的话,就足以保证 b 的子树权重优势足够大,很难被它的兄弟区块超过了。
如果从创始块到区块 b 的所有主链区块都有这个性质,那么这些区块都可以得到确认,也说明此时区块链网络运行良好,没有遭到存活性攻击。这样的树图结构就是一个“正常的树图结构”。
反之,如果晚于某个主链区块生成的区块没有聚集在之后的主链分支内,则可以推测区块链网络可能受到了攻击,此时的树图结构是异常的。
GHAST 规则的严格定义和形式化描述将在我们后续公开的论文中详细介绍。
*** 后注**
在上一期的评论区里有朋友提到“机制越复杂,就越可能出问题”。这个说法是有点不准确的,更准确的说法是:“协议越复杂,分析它有没有漏洞就越困难”。
Conflux 研究组的研究经验表明,每当在区块链的共识设计中引入一个新机制来解决老的问题的时候,同时也可能为攻击者带来新的攻击机会。引入一个新机制解决老问题并不困难,但确保引入的新机制不带来新的问题就非常困难了。
令人遗憾的是,目前的很多共识机制设计只是着重于用新的机制防御老的攻击策略,对于新机制本身是否带来了新的漏洞却缺乏考虑。
我们在探索基于树图的共识方案(特别是 GHAST )的设计细节的这条路上踩过很多坑,重复了无数次“设计方案——寻找并发现漏洞——否决并修改设计”的循环。
比如上面提到的这个设计,其实也有一些微妙的问题。它虽然有能力检测攻击行为,但是检测规则过于敏感。
因此,一个算力不大的攻击者也可以刻意制造出“异常的树图结构”,从而让诚实节点误以为整个系统正遭受到严重的攻击。尽管此时攻击者并不能实现双花或实质上影响共识的安全性,但是可以让整个区块链系统长时间处于异常状态,严重影响确认速度和运行效率。
幸运的是,我们最终设计出了一个方案,在保留上面设计的所有优点的前提下,还可以抵抗以降低效率为目标的“损人不利己”的恶意攻击,并且完成了对这个方案安全性的分析和证明。