干货 | 以太坊 Phase 2 进展

以太坊 2.0 Phase 2 的工作在不断推进。本文所讲的是截至当前的最新进展。Phase 2 的大部分工作都是以太坊基金会的 Ewasm 团队和 Quilt 团队合作完成。
本文不同部分所讲的内容往往指向不同领域,交集甚少,因此,就请挑自己喜欢的部分阅读吧。在阅读本文之前,我非常推荐大家通过下列材料先了解一下 Phase2 以及执行环境提议(EE)的背景知识:

影响 Phase2 的协议层变更

Vitalik Buterin
自今年 4 月以来已经写出了不少提案以及准提案。在这些观念上不断迭代之后,当前的方向应该说非常确定了。最先提出以太坊 2.0 执行环境(EE)的 初始提案
已经在社区中探讨多时了。

Vitalik 的 2 号提案
精炼了 1 号提案以及 Eth2 作为 无状态协议
的新理念( 这篇博文
有一个小节的标题是 “分片链不需要状态”,简要解读了什么是无状态性)。

当前 Phase 2 的设计没有大幅偏离 2 号提案的思想。从历史上来看,引入信标链负载均衡的概念之后, 提案的一部分确实有所改变
。这种负载均衡的思想提议将一条分片链理解为一个纯粹的计算进程,那么 EE 就可以在预先指定的分片链上动态运行。本质上,这种理念是通过在信标链上定义的负载均衡合约,将计算负载平衡到不同的分片链上。值得强调的是,这一设计理念非常有趣,可以 通过相互协作的中继者实现多种不同模式的跨分片同步交易
。它值得我们投入更多精力去研究,如果可靠的话,我们可以在未来把这一工具加到分片链上(也许是上线以后)。

最后,Vitalik 在 Devcon 5 期间公开了 一份提案
来简化 Phase 0 以及 Phase 1。这份提案没有改变 Phase 2 的根本方向,只是尝试改善围绕 Phase 2 的开发者体验。在 Devcon 5 上,有不少朋友都投诉 Eth2 没有跨分片的 产品可组合性
(Vitalik 也给出了自己的 回应
)。在新提案下,跨分片通信可以在一个区块内完成。而在以前的提案中,跨分片通信要等待交联数据得到确认才能完成(6 分钟)。结果就是,即使你的资金(或者说状态)分散在不同的分片中,也可以很容易地把它们都汇集到一个分片中(等 6 秒就够了)。该提议也恢复了 ETH 的神圣性,因为在这个 “操作系统” 中,分片、执行环境、验证者账户、区块生产者之间都可以自由传输 ETH,只需一个区块的时延即可完成。它也会生成一个更简单的手续费市场(Gas 市场),消除大家对 旧的手续费市场提案
的中心化担忧(更多内容请看另一个章节)。

执行环境提案

我们已经在搭建执行环境的原型和早期实现上取得了重大进展。首先,我们需要验证一种执行环境是否能在无状态模式下运作。这种执行环境所要求的 证明/见证 的数据量会太大吗?使用证据来执行状态转换的时间会太长吗?为了回答这些问题,我们做了很多种执行环境、用它们来研究这些问题,不过,首先我们需要一个搭建原型的引擎: Scout

Scout

Scout
是一款以太坊 2.0 Phase 2 执行过程原型搭建引擎(由 Alex Beregszaszi
原创开发),它开发了一个对 Ewasm API 的封装器,所以开发者可以用它搭建出执行环境的原型并开展基准测试(benchmarking)。而且它还有 assembly script
C++
端口。

与 Eth1 相关的诸 EE

为了支持 Eth1 能 切换
到 Eth2 中,我们要把 Eth1 的状态转换规则做成 Eth2 中的一个执行环境。这一切换的主要挑战在于,将 Eth1 转换成无状态模型,然后将 EVM 和 交易/账户 模式转成一个执行环境。下面要谈到的 EE 都是 Eth1 EE 的前身。最近有一个 工作组
成立,专门围绕 Eth1 EE 大力开发。他们汇总出了一份 初始工作计划
,并且很友善地在 eth research
论坛 介绍自己


无状态默克尔帕特里夏树(SMPT)token

主要资料
Github
Sina Mahmoodi 在 Devcon 5 上的演讲

无状态 token EE 的第一个原型旨在模仿 Eth 1.0 的架构。它使用 parity 的代码库来实现 Eth1 状态树(Hexary Merkle-Patricia Trie)以及 RLP 编码规则。它也纳入了一个基本的 中继者实现
,让中继者为一组交易生成多种证明。
基准测试:70 笔交易以及 5000 个账户/叶子节点
用时:5 秒
证据大小:235 kb
执行执行和证据大小仍需要重大改进,但进展也从这些早期结果中展现了出来。其中一个问题涉及到将 Parity 的 rust 库编译成 wasm 代码,结果出现了很多 memcopy(内存复制)操作以及其它效率低下的操作。总的来说,把 rust 编译到 web assembly 已经被证明会遇到很多困难。此外,签名验证一项用去了 4 秒(总用时才 5 秒)。


Turbo Token

主要资料: Turboproof 概览
(编者注:中译本见文末超链接)、 Turboproof Rust Github
Turbo Token Github
Guillaume Ballet
Devcon 5 演讲
Sina Mahmoodi 的 Devcon 5 演讲

Turbo Token 模型用到的 turboproofs
技术一开始是 Alexey Akhunov
为实现 Eth1 无状态轻客户端所做的研究,它能够高效地生成、合并及序列化 Eth1 数据树的 multiproof,也支持单次操作(single pass)高效更新数据树。 Casey Detrio
和 Sina 用 assembly script
rust
语言开发出了一个初始的单分支原型,以验证 turboproof 的效率是否够高。在单分支原型上初步得出了令人满意的结果后,Casey 用 assembly 脚本实现了一个简单、最基本可用的 turbo proof token EE
。Sina Mahmoodi 复制了这一实现
,然后将 Guillaume 的 turbo proof 完整 rust 代码库
和生成器移植到了 typescript
中。
基准测试:70 笔交易以及 5000 个账户/叶子节点
用时:140 毫秒
证据大小:50 kb
执行时间和证据大小相比起 SMPT 原型都有了很大的提升。此外,在整个基准测试中,签名验证花去了 105 毫秒。来自 Casey Detrio 的基准测试证明还可借助进一步的优化将签名验证的时间削减 1/3。当然,5000 远远小于 Eth1 数据树上的实际账户数量,Sina 正在拓宽基准测试,以测试 turboproof 在实际负载下的表现。


EVM 解释器 EE

主要资料: Github
Devcon 5 演讲

我们需要在一个执行引擎中开发出一个(web assembly 可用的) EVM 解释器,好支持 Eth1 EE。 Hugo
做了一个原型,而且围绕一个 add and mul256 合约
做了测试。未来还需要引入更多合约和基准测试来改进这个原型。

总结

上述所有的实验性工作都是为了做出 Eth1 执行环境的一种实现。我们已经开始制作构造原型了,但还是有很多性能问题需要审议。如上文所述,近期有一个 工作组
开始一门心思开发 Eth1 EE 并打造 Eth1 无状态模式。

以 Eth2 为中心的诸 EE

这一部分要向大家介绍那些不完全是为实现 Eth1 -> Eth2 迁徙而开发的 EE。Eth2 要使用一种新的基于账户的执行环境,不同于 Eth1 的账户和交易模型,因为 Eth1 所用的交易、账户和累加器模型都不是最优的。此外,诸如 optimistic rollups、ZK rollups 之类的模型也要研究。Eth2 EE 的设计空间是完全开放的,而下列就是早期的想法和原型。


C Merkle Token

主要资料: Github
Devcon 5 Presentation

Paul Dworzanski 对无状态 Merkle token 的 C 语言实现,他使用了二叉默克尔树(而不是稀疏默克尔树)。数据树的验证和更新都用到了最优内存分布,而且安排了独特的 multiproof 格式。该模型的验证、更新数据树操作都是一次完成的(single pass)(因此避免了内存复制操作(memcopy and duplication)),而且很有可能可以用在 Eth1 的十六叉数据树上。但是,尚不清楚数据树更新算法能不能用在 Eth1 的数据树上(因为基于 Eth1 的模型一般都用到了多步操作(multiple passes))。

基准测试:证明中涉及到了 2 22
个账户中的 40 个
用时:20 毫秒(不包含签名验证)
证据大小:25 kb

当前,测试用到的这个实现已经是最高效率的了。基准测试中没有包括验签的部分,但我们估计只需多花 30 毫秒即可。而且还有很多进一步优化的方案,比如通过缓存哈希和证据来减低运算时间和大小。 适应性哈希长度方案
(哈希值的长度会随着网络的扩大而增加)也可以进一步降低证据的大小。最后,更好的哈希函数实现就能带来更短的运算时间。


ZK Rollup

主要资料: General ZK Rollup Overview
(编者注:中译本见文末超链接《ZK rolup vs. Optimistic rollup》)、 Devcon 5 演讲
EE stark 验证者示例
WASM proof 验证者
web snarks

ZK rollups
是一种 Layer-2 扩展方案,因为不会用到复杂的退出挑战机制和锁定机制,所以能够避免现有的 Layer-2 方案常见的用户体验问题。与这里列出的其它 token 转移方案相比,ZK Rollup 大幅降级了对数据可用性(data availability)的要求。这里列出的实现使用了 web snark
—— 一个用 wasm 实现的生成器,可用于 snark 验证或其它配对函数。为了开发该 EE,Jared 改编 websnark、开发了一个验证 Groth16
证据的独立 wasm 库。这个 EE 还是个早期原型,还得继续开发。


Shard Ether (Sheth)

主要资料: Github
Matt Garnett
Devcon 5 演讲
Internal Quilt 演讲
(内容更为详尽)、 SSZ 概览

Sheth 是 Eth2 合约 EE 的一个先驱(以 Eth1 为原型,但加以迭代使之更契合 wasm/Eth2)。Sheth 基于 Eth2 中用到的 简单序列化编码规范(SSZ)
,它用到了稀疏默克尔树方案、借用 turboproof 的操作码但使用了 不同的形式
来管理读取、写入和更新需求。 Diederik Loerakker
设计思路
是,通过 存储一个 offset 的列表
来决定如何遍历整棵数据树。稀疏默克尔树证明的长处在于,你可以在编译时静态地定义你正在引用的数据的总体索引。它也极大地简化了更新状态所需的逻辑,因为数据树永不删除或者插入节点;不过,为此也付出了一些牺牲(高强度的哈希计算)。Sheth 还包括了 一个命令行客户端
,可以作为中继者或者状态提供者。
基准测试: 50 个账户以及 50 笔交易
证据大小:517 kb

当前的实现产生的证明大小实在是太大了(517 kb 可不是一个小数字),而且也比我们期望的要慢。证据可以通过移除补位的 0 或者消除 0 哈希值的数量而大幅减小;运算速度则可以通过引入 host 函数来管理 256 比特的操作(下一节将详述)还有必要的代码优化来提升。 Diederik Loerakker
已经提交了一个 issue
,论述了如何提交这个设计的效率。总的来说,使用稀疏默克尔树就会比较依赖哈希计算,而这个效果已经从初始的基准测试表现出来了。

SimpleUmbrella — Eth2 智能合约 EE

主要材料: Eth Research 论坛中的提案
execute code host function PR

该 Eth2 EE 是一个无状态的智能合约执行环境,运行合约的方式与 Eth1 执行环境相似,但合约是 wasm 形式的。此外,它未来有可能会转用累加器,而不是使用 eth1所用的十六叉默克尔树。稀疏默克尔树看起来不错,不过也还需要进一步的基准测试来作出可靠的决策。Matt Garnett 汇总了一个 Eth2 EE spawn runtimes 以及在子合约中分享 调用者/被调用者数据的 早期规范
。因为近期的一些 争议
我们开发了一个 host 函数的原型
,可用于在 Eht2 EE 中 spawn 或者运行子合约。 一个新的代码库
已经开放,很快我们就能运行基本的智能合约了。

Ewasm —— 解释器、编译器以及计算量度量

这部分内容涵盖了 Ewasm 团队在过去几年中的大量工作。在 Devcon 5 期间, Ewasm 团队给出了一个清楚的
、数据翔实的 Ewasm 相关工作现状和进展说明。如果这部分内容勾起了你的兴趣,我非常推荐你看看 完整的视频
。下面我会给出一个简单的总结。此外,Maksym 也为 Ewasm 团队在 Wasm in the Blockchain 大会上的分享内容
做了一份非常全面的概览。

编译器

如果我们想让 Eth2 能尽快发布,那么继续编译器路线可能会有更高的风险。其中一个困难或者说难以弄清楚的事项是管理 JIT bombs
(这是通过 fuzzing 测试方法发现的)。单操作(single pass)的编译器也许也可以避免 JIT bombs,但现在大家都比较担心当前的单操作编译器实现的稳定性和安全性。在未来将编译器作为 Eth2 的一部分也许不无道理,但如果我们想尽快启动,解释器可能是个更安全的选择。

解释器

Casey Detrio
以及 Alex Beregszaszi
Devcon 5 演讲
给出了对解释器性能的非常全面的分析。更有意思的是,优化后的解释器以及精心编写的代码被证明可以实现接近原生编译器的性能。在一次测试中,Casey 将一个 wasm 解释器和用于 256 位数学操作的 host 函数(Bignum library)相结合,评估了多种配对函数和哈希函数的性能。结果令人印象深刻,性能很接近原生且优化后的编译器。在他的一系列基准测试中,他还发现最快的解释器是 wabt

计算量度量

Paul Dworzanski 在他的 Devcon 5 演讲
中深入探讨了这个领域。为了度量计算量, use_gas
调用会在 wasm 合约部署及验证之时注入 wasm 字节码(无论它是运行在 EE 还是 umbrella EE 中)。注入及验证的复杂性无疑会影响合约部署的费用。当前的基准测试显示,注入计算量度量组件后,wasm 代码运行的速度会变慢 1.04~2.4 倍。对注入流程及注册器 assembly 的更优模式基准测试将指明进一步优化的方向。

在 Lighthouse 客户端或者 Phase 2 模拟中的 Phase 1 和 2 原型

我们希望模拟 Phase 1 和 2 的客户端最终是如何构建的,以及如何支持开发实现的团队。我们也希望使用这些工作来模拟及测试 EE 在实际环境中跨多个分片运行时的情形。在 Devcon 5 期间, 我做了一场关于我们所构建的模拟程序的演讲
。我们 在 Lighthouse 客户端中 开发/ 加入了一个非常简单的 Phase 1 原型
(没有加联网组件)并在该客户端中加入了 phase 2 Ewasm runtime
。我们与 Sheth
交互(Sheth 作为一个中继者和状态提供者),而且能够在 Lighthouse 中模拟基本的 EE 或者代币转移。

因为 Lighthouse 客户端
还在踊跃开发中,我们意识到维护 Lighthouse 客户端的一个分支并在上面开发很可能会比我们一开始设想的要难。所以,我们决定吸取初始原型的养分,在 Scout
里面开发 一个抽象的存根版本
。我们将继续模拟信标链和分片链的运行,不过我们可以大幅简化其中的逻辑,因为我们的重心在执行环境的研究以及跨分片基准测试上。这部分工作正由 Quilt 团队的两位新成员管理着。

中继者、状态提供者以及手续费市场

John Adler
针对这一主题写了一份 非常全面的概览
。他的文章也讲述了 Eth2 提案的有趣演化历程。总结一下,Vitalik 最新的分片简化提案
消除了一开始我们在中继者模型中遇到的 许多问题
。不过,关于状态提供者如何向区块生产者发送交易,以及区块生产者如何将交易包合并到一个合适的 multiproof 中,仍有不少问题悬而未决。其中一种建议是部署一个带有证明合并脚本的新执行环境。

接下来,围绕着状态提供者的激励机制也要确定下来。Zsolt 在 第一次轻客户端小分队视频会议
中分享了他对激励机制的研究( 录像在此
)。 Eth1 EE 工作组
正在评估一个状态提供者网络
,他们拿 Beam Sync
上先前的工作作为模型。

最终,中继者或者状态提供者将继承 web3.js 或者 ethers.js 所连接的 RPC 端点
。为这些跨多个 EE 的操作提出一系列标准是至关重要的。

跨分片交易

异步跨分片交易

Vitalik 的 最新 Phase 0 &1 提案
对于跨分片交易和可组合性来说都是好消息。在新提案中,一次跨分片调用只需 1 个时隙(6 秒)的时延就能完成,而在过去的提案中,一次调用要等待 12~18 分钟的时延才能确定下来。因此,在分片间转移你的状态(或者说 eth)会变得很快。此前,我们想用 optimistic roots
来加快调用速度,但发现这些方案都非常复杂。
从一个 dApp 开发者的角度来看,跨分片调用只需遵循多线程编程中的异步范式和方法。在编写智能合约时,HLL(Slodity)和 DSL(Vyper)需要提供必要的工具将跨分片行为抽象成异步范式。整个模式很有可能就像下面这样:

  • 简单的异步调用(async await,callback,等等)
  • 消息驱动型方法(Actor 模式)
  • 两阶段确认(原子性)
  • 锁 —— 读/写( Contract Yanking

如何在 EE 或者在合约的底层中支持这些模式还需要进一步的研究。上文提到的模拟(以及下文提到的编排工具)应该能为我们对这些模型的实验提供基础,不过,我们真的要说,这是一个重要的研究领域,如果人们愿意参与进来,我们会非常高兴。像在 此贴
中描述的那样,在更底层规定进程前和进程后的行为分别,可能会为在合约内暂停执行及后续继续执行提供一个合理的框架。

同步跨分片交易

之前,Vitalik 发表了一篇论述 状态方案
的帖子。这些方案实质就是链上 Layer-2 模式,而分片仅作为数据可用性层。这些模型(就是之前传说的 “ 延迟状态执行
” 模型、“ 懒惰执行
” 模型 或者 “ 影子链
”)其实都是现在所谓的 optimistic rollups
的前身。将多分片用作一个 optimistic rollup 方案的数据可用性层使同步跨分片交易成为可能。我们可能在不远的将来根据这个概念开发出一款原型。
此外,如果信标链引入负载均衡机制,我们可以通过相互合作的中继市场实现同步跨分片交易。请看上文 “影响 Phase 2 的协议层变更” 部分了解更多细节。

我们真的需要跨分片调用吗?

另一种值得进一步研究的观点是,Eth2 的主体应该要向状态通道、 optimistic rollups 以及 zk rollups
倾斜(在这些方案都成熟之后)。在这种思路下,Eth2 本身就是一个数据可用性层,而跨分片调用只有在桥接这些方案或者在 退出挑战/错误性证明 过程中才会用到。Rollups 仍要在 Eth1 或者 Eth2 执行环境的边界内定义好,不过,只有需要提交错误性证明的时候,才需要在链上执行计算。

Phase 2 工具链

为推进我们的研究, 我们提议了一套开发者需要用到的工具链
。正如上文 “Lighthouse 中的 Phase 1 和 Phase 2 原型” 章节中说的那样,我们正在积极开发一套模拟来测试及运行跨分片的执行环境。不过,为使智能合约运行模式最优化,我们还得添加很多编排工具。 这个帖子
对这些工具做了更深入的说明。

  • Phase 1 & 2 模拟
  • 类似于 Truffle 这样的测试工具,用于在一个 EE 中运行 wasm 合约(无论是 Eth1 EE 还是 Eth2 EE)
  • 插入 Phase 1 客户端的运行时环境(runtime environment)
  • 可靠的 muilti-proof 后端(让客户端可以生成、合并及管理 multiproof)
  • 中继者、状态提供者工具,用于与 web3.js 交互(请看 “中继者、状态提供者与手续费市场” 部分)

Vitalik 对 Phase2 的其他贡献

Vitalik 最近还在其它帖子中讨论了与 Phase 2 相关的主题,但我在上文中没有直接引用,特此指出:

行动起来!

如果你有兴趣帮助我们,请联系我们并参与进来。请 加入这个 telegram 频道
来获取新知或提问。我们已经有了进步,但仍有很多工作要做。

最后,我们将开始每月一次的视频会议。第一次会议 计划在
美国东部时间的 12 月 3 号,周二,上午 10 点举行。

结论

在 Phase 2 上我们已经取得了很多进展,但毫无疑问需要做更多工作。这些早期的数据显出前景不错,而近期的大力投入(尤其是无状态客户端)也是非常有用的。我们需要围绕跨分片搭建原型并加以测试,我们也要开始构思如何在 Eth2 EE 里面开发合约。无状态系统的累加器方案需要更多关注,因为它将让当前的 EE 原型性能更高、更适应生产环境。我们还需要为 EE 开发打造更好的工具。最后,不能漏掉,我们还需要中继者、状态提供者的经济激励机制。
感谢 Danny Ryan 和 Joseph C。

原文链接: https://medium.com/@william.j.villanueva/ethereum-2-0-phase-2-progress-7673b57eabff

作者:Will Villanueva

翻译:阿剑