Conflux 的自我进化:从 DAG 到树图| 对话伍鸣

Conflux 的自我进化:从 DAG 到树图| 对话伍鸣

Conflux 的身份不再是 DAG,它是树图。

受访者:Conflux CTO 伍鸣
采访 &.撰文:李画

这是一次特别的采访。

采访前我们想要 Conflux 的首席技术官伍鸣博士帮我们解答的疑问是:「DAG」与「链」的本质区别是什么?我们为什么要用它?它自身的局限性又在哪里?

采访时伍鸣却告诉我们,Conflux 已不再把自己归类为 DAG,它的新身份是树图(Tree-Graph)。

不过我们的疑问依然被解答了,因为最有趣的地方就在于,Conflux 从 DAG 类别变更为树图类别的原因,恰恰能回答采访前我们想要弄明白的那三个问题。甚至因为引入了树图概念,我们能从一个更高的角度来理解这些问题。

区块链账本的结构反映的是区块与区块之间的连接关系,而这种连接关系是由「指针」决定的。更科学的账本分类方法不是基于它的形状,而是基于其「指针」的类别、数量。

我们的采访对象伍鸣是 Conflux 的联合创始人,在加入 Conflux 之前任微软亚洲研究院系统组资深研究员,主要的研究方向为分布式事务处理系统、图计算引擎和人工智能平台,他在分布式系统的设计和实现上拥有丰富的专业知识。

Conflux 是使用树图结构的公有链,其团队成员大多拥有美国一流大学的留学背景和在硅谷、华尔街的多年工作经验,有着突出的科研能力与技术能力。姚期智院士是 Conflux 团队的首席科学家。

01

链、DAG、树图:结构不同能力不同

问:DAG、树图这些非链式的账本结构能被认为是区块链吗?

伍鸣:不管是链、DAG,还是树图,我们要通过它们解决的问题其实是一样的,我们可以用区块链技术这个词把它们概括起来。

问:链结构、DAG 结构、树图结构的本质区别是什么?为什么 Conflux 是树图而不是 DAG?

伍鸣:你可以认为在链结构里,每个区块只能有一个指针,这个指针是指向其父亲区块的,那么所有区块就会一个接一个连起来,形成一个链状的结构。

DAG 结构概括来讲是指每个区块有多于一个的指针,可以指向多于一个的其他区块,形成的是一个有向无环的图状结构。

Conflux 的树图结构不同于链或 DAG 只有一类指针,它的每个区块都有两种指针,一种指针指向父亲区块,且只能有一个父亲,与传统的链式结构一样;一种指针指向引用区块,需要引用多个区块,表达不同区块间的 happens-before(先行发生)关系。

所以,在 Conflux 里有两种类型的边,父边(父亲指针确定的边)和引用边(引用指针确定的边)。如果只看父边,账本的结构是一棵树;如果同时看父边和引用边,账本的结构是一个图。树图结构就是指在图中包含了一棵树的这样一种结构。

我们觉得如果继续叫 DAG 可能会让大家产生误解,因为目前其他基于 DAG 的区块链系统都只有一种类型的连接区块或交易的边,因此有了树图这个概念。树图它更接近于 Conflux 账本结构的本质。

问:Conflux 为什么要引入两种指针?三种不同账本结构的区块链系统会有何不同?

伍鸣:三种不同账本结构下的区块链系统最大的不同在于,它们对全序的支持或实现方式是不一样的。

链结构支持全序,DAG 结构天然形成的是偏序,树图结构支持全序。

链结构中舍弃了分叉上的区块,其主链上的区块都有着唯一的父子关系,天然形成一个确定的顺序,所有人都可以按照这个顺序执行区块里的交易,所有人最后都能够达到一个一致的状态。

DAG 结构中天然形成的是一个偏序。偏序的意思是说如果图中的两个区块之间没有直接的边,或者两个区块之间不存在一条路径,就没有办法确定这两个区块及它们所包含的交易间的顺序。

不过 DAG 可以通过设计为区块排出全序,现有的 DAG 有些支持全序有些不支持全序。

树图结构通过引入主链和 Epoch 的概念,实现了对区块全序的支持,这也是Conflux 有两种指针的原因。(如何实现全序将在下一节详细介绍)

问:为什么要排全序,偏序会带来什么问题?

伍鸣:一个区块链系统,如果只需要处理普通的转账交易,又能通过指针保证并发交易间没有因果关系,那它也许可以用偏序。

因为这种系统只需要处理加减操作,而加减操作是满足交换律和结合律的,交易的执行顺序对系统状态没有影响,系统最终的状态是一致的。

但偏序不能支持智能合约,因为智能合约是图灵完备的,它需要表达复杂的逻辑计算,它有乘法,一旦有乘法和加法就不会满足交换律了。

也就是说,两笔交易 A 和 B,先执行 A 后执行 B 得到的状态与先执行 B 后执行 A 得到的状态是不一样的。偏序下两笔交易有可能以任意的顺序执行,那么不同的矿工就会得到不同的系统状态,就无法取得共识。

如果一条链想要支持智能合约,就要支持全序。

问:既然为了实现全序要多做工作,为什么使用 DAG 或树图,而不是链结构?

伍鸣:区块链会产生很多分叉,链结构是无法定义分叉上的区块的执行顺序的,它只能选择丢掉分叉。

丢掉分叉会牺牲掉一些区块,不仅浪费了资源,还制约了吞吐率;丢掉分叉也会牺牲一些安全性,因为在最长链共识机制下,分叉上的区块是不能为最长链共识作出贡献的,比如有很多好人区块分叉的话,这些区块就不能用来贡献最长链,也就不能用来贡献链的安全,坏人可以用更少的算力攻击这条链。

树图和实现了全序的 DAG 把分叉区块加入到账本中,并定义了分叉上区块的执行顺序。

把所有的区块都算进来,也就让所有区块都贡献到系统的吞吐率上,这使得系统的瓶颈就不再是共识机制,而是网络本身。只要网络足够快,系统的性能就还能再高,从而使得整个系统在不牺牲安全性的同时获得更高的吞吐率。

02

Conflux 如何实现全序

问:Conflux 如何实现全序?

伍鸣:Conflux 是通过引入主链这个概念最终实现全序的。我们之前讲过每个区块都有两种指针,其中一种是指向父亲区块的,这种指针决定的账本结构是一棵树,通过这棵树可以确定一条主链。

具体实现上,Conflux 采用了 Ghost 和 Epoch 这两种规则。Ghost 规则用来确定主链,Epoch 规则用来确定区块的顺序,两者结合,就能实现区块的全序。

问:Ghost 如何确定主链?

伍鸣:Ghost 从创世区块开始,迭代的去从孩子区块中选择放在主链上的下一个区块,选择规则是挑选拥有最大子树的孩子区块为主链区块。

如下图所示,区块 A 和区块 B 是创世区块的两个孩子区块。A 子树有6个区块,B 子树有5个区块,所以选择区块 A 作为紧接着创世区块的主链上的区块。根据同样的规则,把区块 C,E,H 都选择进了主链。

(图中实线箭头指向父亲区块,虚线箭头指向引用区块)

问:Epoch 如何实现对区块的排序?

伍鸣:Conflux 中的每个新区块在产生时,除了选择主链(该区块观察到的主链)上的最后一个区块作为自己的父亲区块外,还必须把所有自己观察到的但还没有被其他区块引用的区块引用起来,表达不同区块之间的 happens-before 的关系。

如上图所示,如果一个机器节点在产生区块E的时候,发现系统中已经有了区块D,而且这个时候区块 D 还未被任何其他区块引用,那么区块 E 就把自己的引用指针指向区块 D,也就是说在区块E和区块 D 之间加上一个有向的引用边,表示 D 是在 E 之前产生的。

主链上的每一个区块确定一个 Epoch。在分叉上的区块属于哪个 Epoch,是由第一个产生在它之后的主链区块所在的 Epoch 决定的。比如区块 D 属于 Epoch E,因为 D 最先被 E 引用,所以产生在 E 之前,但是 D 并不产生在 C 之前。

问:在同一个 Epoch 内,区块间的顺序是如何确定的?

伍鸣:在每一个 Epoch 内部,Conflux 用拓扑排序确定区块间的顺序。如果出现平局,再根据区块的哈希值来排序。

如此一来,通过 Ghost 规则确定主链,通过 Epoch 规则确定区块的大体顺序,通过拓扑和哈希排序实现同一 Epoch 内区块的顺序,最终,Conflux 的树图结构账本提供了一个一致的区块全序。

03

DAG 和树图引发的思考

问:如果多个节点同时出块,这些区块又都有效,会不会同一时间段产生大量区块?这样一来,每个区块中引用指针占的空间会不会变得很大?

伍鸣:不会的,实际上整个系统的出块率是固定的,我们会动态的去调整出块难度,出块率很高,我们就增加难度把它降下来,出块率很低,我们就减少难度让它增上去。

问:如果多个节点同时出块,并发区块中应该会包含相同的交易,怎么解决重复打包交易的问题?

伍鸣:Conflux 采用的是混合策略(Mixed-Strategy,博弈论中的一种策略),矿工们根据交易费的选择权重随机地从交易等待池中选取交易。随机是比较抽象的一个描述,它实际上很复杂,矿工会跟随这种随机方法选取交易,让自己打包交易获得的回报最大化。

当然不可能完全避免重复,交易池的交易越多重复概率越小,在正常情况下可能有30%左右的交易重复。如果交易池里的交易很少,比如说最极端的情况,只有一个交易,那当然是会重复的,因为所有人都会打包这个交易。

问:如果多个节点同时出块,有没有可能发生交易冲突的问题?

伍鸣:一般我们说的交易冲突是指上一个交易把钱花光没有余额了,但后面还有交易。Conflux 通过区块全序保证了交易的执行顺序,就会避免这个问题,如果发生在前边的交易把钱花光了,就会让它后边的交易变为无效。

另一种情况是相同的交易有可能被打包到不同的区块里,在这种情况下,Conflux 只接受在区块全序中排在最开始位置的这笔交易,而把后面的交易变为无效。

问:因为账本结构的复杂性,会不会出现不同节点账本不一致的情况?

伍鸣:肯定是有的,但经过一段时间以后就能确定账本。有一个公式可以算出主链区块被统一的概率,大概五、六个 Epoch 后,账本就能一致。

问:树图在51%攻击上的安全性是怎么样的?

伍鸣:Conflux 中只要主链定了,交易的全序就定了,攻击者想发动51%攻击、想改变交易的顺序,就必须改变主链的顺序。

因此在51%攻击上,树图的安全性和 Ghost 链的安全性是差不多的。

Ghost 规则比最长链规则安全,Ghost 看的是子树的权重,把分叉上的区块也考虑到了,所有的区块、所有的算力都贡献到主链的选择上,能够严格地满足51%这个概念。但最长链规则没有考虑分叉链上算力的浪费。

问:在对矿工的激励机制上,树图跟链式结构有什么不同?

伍鸣:有一种情况是树图中才会出现的。树图需要区块去引用其他区块,表达不同区块之间的 happens-before 的关系,那有的区块可能不去正常引用其他区块,就是说看到其他区块也不引用。这是我们不希望看到的情况。

另一种发生在树图上的欺骗行为在传统的链上也会发生,就是产生区块但不广播,偷偷挖一个私有的链,等到某个时机再放出去。

在这两种情况下,这些不正常区块的并发区块会变得很多,因为它们和其他区块之间缺少 happens-before 关系。Conflux 以此为依据去惩罚这两种行为:并发区块的个数越多,矿工获得的奖励越少。

04

结束语

链式结构放弃了分叉上的区块,这样做虽然牺牲了一定的吞吐率,却保证了交易的全序。DAG 把分叉上的区块都纳入到账本中,这样做虽然不再浪费算力,却引入了一个如何对区块排序的难题。

有的 DAG 干脆不对区块排序,因为在一些应用场景下,交易的全序可能并不那么重要,比如 IOTA。其他 DAG 则需要设计一种方法,实现对区块的排序。比如 Byteball 、Hashgraph。

当我们深入地去了解不排全序的 DAG、排全序的 DAG、排全序 DAG 的不同排序方法,以及这些 DAG 采用的不同账本结构,就会发现它们是截然不同的。

或许正因如此,Conflux 不再把自己归类为 DAG,而具有两种不同类别指针的它也确实与 DAG 有着不小的区别,树图也许更接近其本质。

于是,这次带着弄清 DAG 与链的差别开始的采访,最后得出的结论是:不同DAG 项目的差别,比 DAG 与链的差别都大。

本文转载自碳链价值