原文标题:《The roads not taken》
原文作者:Vitalik Buterin
原文来源:Vitalik Buterin 官网
原文编译:Kxp,律动 BlockBeats
Ethereum 协议开发社区在 Ethereum 的早期阶段做出了很多决定,对项目的发展轨迹产生了重大影响。在有些情况下,Ethereum 开发者做出了理智的决定,解决了 Bitcoin 遇到的一些问题。而在其它一些情况中,我们也在创造全新的东西,利用诸多选择填补过往的空白。还有些时候,我们需要在复杂与简易之间做出权衡,因为二者分别适用于不同的情景。
本篇文章我将介绍一些分叉功能,其中很多都在核心开发者的圈子当中认真讨论过;但剩下没有讨论的功能此时此刻也应该被提上日程。同时,我们也期待看到一个不同的 Ethereum,并从中学到新的东西。
我们是否应该采用一个简易版的权益证明
Ethereum 很快将合并到的 Gasper 权益证明系统虽然复杂,但却功能强大,具有以下特性:
强大的单区块确认——一旦交易被纳入区块,通常在几秒钟内,该区块就会被固化。除非有很大一部分节点诚信度低,或者存在极端的网络延迟,否则它无法被逆转。
经济确定性——一旦区块最终确定下来,在攻击者没有损失数百万 ETH 的情况下,它也不可逆转。
可预测性高的回报——验证者在每个周期(6.4 分钟)都能获得可靠奖励,减少了对资金池的激励。
支持较多数量验证者——与其他大多数具有上述特性的链不同,Ethereum 信标链支持数十万的验证者(例如,Tendermint 提供比 Ethereum 更快的确定性,但它只支持数百个验证者)。
但制作一个具有这些特性的系统相当困难,需要进行多年的研究,经历无数次的失败,并花费大量的精力,而且最终结果也会非常复杂。
如果我们的研究人员不需要太考虑共识,并且有足够多的精力的话,那么也许 rollup 在 2016 年就已经被发明出来了。这就让我们不禁反思:我们的权益证明真的应该有这么高的标准吗,因为即使是一个简单弱化版本的权益证明就会比我们目前的工作证明要好得多。
很多人都存在一个误解,认为权益证明本身就相当复杂,但实际上有很多权益证明算法几乎和 Nakamoto PoW 一样简单。NXT 的权益证明在 2013 年就出现了,是一个天然的候选方案;虽然它也有问题,但这些问题很容易被修补,而且我们本可以从 2017 年,甚至从一开始就有一个运作良好的权益证明。Gasper 之所以比这些算法更复杂,只是因为它尝试完成的任务比它们多得多。但是,如果我们在一开始就加以谨慎,我们本可以先集中精力实现一些更可能完成的目标。
在我看来,从一开始就采用权益证明并不是一个正确的做法;PoW 有助于扩大最初的发行分布,改善 Ethereum 的可访问性,并促进业余爱好者社区的发展。但在 2017 年,甚至 2020 年,改用更简单的权益证明却可以更好的保护环境(以及因环境破坏而产生的反 Crypto 思潮),同时也能让研究人员更好地专注于扩展问题。我们最终还是需要耗费大量资源来制作一个更好的权益证明,从目前情况来看这会是一个必然结果。
分片的去复杂化
自 2014 年开始研究 Ethereum 分片以来,我们一直在着手解决去复杂化的问题。之前的复杂分片具有内置执行和跨分片交易功能,而之后我们简化了协议,将更多的责任转移到用户身上(例如,在跨分片交易中,用户必须在两个分片上分别支付 Gas 费)。然后,我们转向了以 rollup 为中心的路线图,从协议的角度来看,分片只是数据的集合体。最后,通过danksharding,我们可以将分片收费市场合二为一。这样一来,最终设计虽然看起来像是一个非分片链,但其背后进行的数据可用性采样却能使分片验证成为现实。
但如果我们选择了一条与之相反的路径呢?实际上 Ethereum 的研究人员曾花大量时间探索了一个更复杂的分片系统:分片将成为链,在分叉选择规则中子链依赖于主链,跨分片消息会被协议路由,验证者会在分片之间轮换,甚至应用程序也会在分片之间自动完成负载平衡。
这种方法的问题在于:这类形式的分片基本还只是一些想法和数学模型,而 Danksharding 则是一个完整且可供实施的规范。因此,鉴于 Ethereum 的种种限制因素,在我看来,分片的简化和去歧义化绝对是正确之举。尽管如此,我们还是应该投入更多精力开展研究,因为它可以帮我们确定有前景的研究方向。一般来说,即使是非常复杂的想法也其简易的版本,且依然能为我们带来很多帮助,同时还很有可能在未来几年内左右 Ethereum 的协议发展方向(甚至是 Layer2 协议)。
我们应增加还是减少 EVM 中的功能
除了安全审计功能之外,EVM 的规范在 2014 年中之前就可以推出。不过,在之后的几个月里,我们一直在积极探索对去中心化应用区块链有用的新功能,具体如下:
1. 我们之前想增加一个 POST 操作码,但后来还是决定放弃了。POST 操作码会进行异步调用,而该调用在交易完成后才会执行。
2. 我们之前还想添加一个 ALARM 操作码,但后来也放弃了。ALARM 的功能类似于 POST,只是它能在在未来的某个区块中执行异步调用,让合约能提前规划操作。
3. 我们添加了日志,它可以让合约输出不涉及状态,但可以被 DApp 接口和钱包读取的记录。不过,我们也考虑过让 ETH 转账发出日志,但还是放弃了,因为我们觉得「反正人们很快就会转到智能合约钱包」。
4. 我们考虑过扩大 SSTORE 以支持字节数组,但后来由于担心其复杂性过高和安全性不足而选择了放弃。
5. 我们增加了预编译合约,它们可以用比 EVM 更低的 Gas 费,用原生方式执行特定的 Crypto 操作。
6. 在发布后的几个月里,我们反复考虑了状态租用问题,但囿于它的复杂程度我们并未把它包括在内。如今,人们正在积极探索更好的状态过期方案,尽管无状态验证和提议者/构建者分离比它重要的多。
今天来看,我们基本上都做出了正确的决定,我们也确实不需要增加 POST 操作码,也很难保证 ALARM 操作码的安全性(如果每个人在 1 到 99999 个区块中都设置了一个 ALARM,那么在第 100000 个区块中执行大量代码,会发生什么?那个区块会不会花几个小时来处理这些代码?一些预定的操作会被推到后面的区块吗?如果这种情况发生了,那么 ALARM 还能保留什么安全保证呢?)字节数组 SSTORE 的安全性也很难实现,而且会扩大最坏情况下的见证规模。
状态租用问题更具挑战性:如果我们从第一天起就真正实现了某种状态租用,那么我们就会有任何能够围绕持续状态的规范化假设进行演化的智能合约生态系统。Ethereum 会变得更难构建,虽然它可能会更具扩展性和可持续性。同时,我们当时的状态过期计划确实比我们现在的要差得多。有时候,好的想法就是要花上几年的时间才能达成,并无捷径可言。
LOG 的替代路径
LOG 可以用两种不同的方式来完成:
1. 我们可以让 ETH 转账自动发出一个 LOG。这将为交易所和许多其他用户节省大量的时间,并减少和软件错误的发生。人们将更加依赖 LOG,同时智能合约钱包也会得到更大规模的使用。
2. 我们完全可以不用 LOG 操作码,而把它变成一个 ERC:会有一个配置 submitLog 函数的标准合约,它可以使用 Ethereum 存款合约技术来计算该区块中所有日志的 Merkle 根。无论是 EIP-2929 还是区块上的存储(相当于 TSTORE,但在之后会被清空)都将降低它的成本。
我们曾认真考虑过第一种方式,但最后还是没有采用,主要原因还是它的简易性不足:使用 LOG 操作码直接生成日志会更为便捷。我们还做了错误的估计,认为大多数用户会迅速迁移到智能合约钱包,并使用操作码来记录转账。
我们之前没有好好考虑过第二种方法,但现在回想起来,它其实也很不错。它的主要缺点在于,它缺乏一个快速扫描日志的 Bloom 过滤器机制。但事实证明,Bloom 过滤器机制速度太慢,对 DApp 并不友好,所以现在越来越多的人开始使用 TheGraph 来进行查询。
总的来说,采用任何一个方法都会使情况变得更好。将 LOG 保留在协议之外会使事情变得更简单,但如果它在协议之内,它自动记录所有 ETH 转移的功能也非常实用。
时至今日,我会赞成取消 EVM 中的 LOG 操作码。
如果 EVM 完全与众不同呢
EVM 可以选择两条截然不同的路径:
1. 让 EVM 成为一种更高级的语言,有内置的变量、if 语句、循环等结构。
2. 让 EVM 成为某些现有虚拟机(LLVM、WASM 等)的副本。
我们从未好好考虑过第一条路径,而它的优势在于,它可以简化编译器,并允许更多的开发者直接在 EVM 中编码。同时,它还可以使 ZK-EVM 的结构更加简单。不过,这条路径的弱点是,它会使 EVM 代码在结构上更加复杂:它不再是一排简单的操作码列表,而是一个更复杂的数据结构,必须以某种特定方式进行存储。也就是说,我们错过了一个两全其美的机会:在保持 EVM 基本结构不变的同时,对其做出一些改变可以给我们带来很多好处,包括禁用动态跳转、增加一些旨在支持子程序的操作码(另见:EIP-2315)、只允许在 32 字节的词汇边界上访问存储器,等等。
第二条路径好坏参半,支持的人认为它可以让程序从现有语言(C、Rust 等)编译到 EVM 中,而反对的人则认为,鉴于 Ethereum 特殊的限制因素,它实际上不会提供任何好处:
1. 现有的高级语言编译器往往不关心总的代码大小,而区块链代码必须大量优化以减少每一个字节的代码大小。
2. 我们需要实现虚拟机的多项功能,并严格要求两个功能不能以不同方式处理相同的代码,但这也会给在不是我们写的代码上进行安全审计和验证造成困难。
3. 如果虚拟机规范发生变化,Ethereum 将不得不一直随着它进行更新,否则将很难同步。
因此,尽管当初一些细节得到改善可能会产出更好的结果,但和现在情况不同的是,EVM 在以前可能还是从来没有过一个可行的路径。
ETH 供应是否应该以不同的方式进行分配
我们可以从下面这张来自 Etherscan 的图表看到目前 ETH 的供应量:
今天大约一半的 ETH 是在公开的 Ethereum 销售中售出的,任何人都可以向一个标准化的 Bitcoin 地址发送 BTC,而最初的 ETH 供应分布是由一个开源脚本计算得出的,该脚本通过扫描 Bitcoin 区块链上的交易获得地址。其余的 ETH 基本都是靠挖矿得到的,其中标有「其他」的 1200 万 ETH,是「预挖矿」的部分——即在 Ethereum 基金会和约 100 个 Ethereum 协议的早期贡献者之间分配的部分。
人们对该过程提出了两点批评意见:
1. 预挖矿,以及 Ethereum 基金会收到销售资金的事实,并不是可信的中立。一些收件人地址是在闭环中人工挑选出来的,而且我们必须相信 Ethereum 基金不会通过贷款将销售中收到的资金重新放到销售环节当中来为自己提供更多的 ETH。
2. 预挖矿过度地奖励了早期的贡献者,这让后来的贡献者只能分得较少的奖励。75% 的预挖矿用于奖励贡献者在启动前的工作,而启动后,Ethereum 基金会只剩下 300 万 ETH。在之后的半年时间内,由于财务上的需要,该数字又下降到约 100 万 ETH。
在某种程度上,这些问题是相互关联的:人们为了最大限度地减少中心化,缩小了预挖矿的规模,而这也会让它更快耗尽。
Zcash 采取了另一种不同的方法:协议中一组硬编码的接收地址将收到恒定的 20% 区块奖励,并这一名单每 4 年就会重新协商一次(到目前为止已经做了一次调整)。虽然这种方法具有更高的可持续性,但也会因为中心化而受到更多的批评(Zcash 社区似乎比 Ethereum 社区更愿意接受技术专家的领导)。
我们可以采用如今在一些 defi 项目中流行的「DAO from day 1」作为替代路线,草案提议如下:
1. 我们同意在 2 年内,拿出每个区块 2 个 ETH 的奖励放入开发基金当中。
2. 任何在 Ethereum 销售中购买 ETH 的人都可以指定投票给他们青睐的发展基金,以进行 ETH 分配(例如:「每个区块 1ETH 给 Ethereum 基金会,0.4ETH 给 Consensys 研究团队,0.2ETH 给 Vlad Zamfir 等等」)
3. 得到投票的接受者从开发基金中获得的份额将等于每个人投票的中位数,并将按按比例进行计算,从而保证其总数等于每个区块 2 个 ETH(设置中位数是为了防止自我交易:为自己投票毫无用处,除非你让其他购买者中至少有一半人为你投票)。
这一销售可以由法律实体运作完成,该实体承诺将销售期间收到的 Bitcoin 按照与 ETH 开发基金相同的比例进行分配(或销毁,如果我们想让 Bitcoin 玩家高兴的话)。这可能会导致 Ethereum 基金会和其他团体在不破坏可信中立性的情况下得到大量的资金,加快生态系统去中心化的进程。当然,这一做法的缺点在于,投币投票真的很糟糕,但务实地说,2014 年仍然是一个较早和理想化的阶段,投币投票最严重的缺点在销售结束很久以后才会开始显现。
这也许会是一个更好的想法,并树立一个更好的先例。尽管从现实的角度来看,即使开发基金是完全可信中立的,今天那些对 Ethereum 矿工感到不满的人,很可能会将矛头转向 DAO 分叉。
启发
总的来说,有时我觉得 Ethereum 最大的挑战在于保持两个愿景之间的平衡——一个重视安全性和简洁性,纯粹简单的区块链,以及一个用于构建先进应用程序的高性能平台。上面的诸多例子只是这个问题的一个方面:我们是减少功能数量从而更类似 Bitcoin,还是创造更多功能以方便开发者?我们应该担心让开发资金更加可信中立会使其更像 Bitcoin,还是应该先关心如何确保开发者得到足够的奖励,从而让 Ethereum 变得更好?
在我个人看来,我们可以同时实现这两个愿景——一个规格逐渐缩小的基础层,以及一个以 Layer2 协议为中心,功能强大的开发者友好型高级应用生态系统。即便如此,要达到这样一个理想的状态还是需要很长的时间。所以说,我们只有一步步地考虑如何制定路线图,才能取得一定的成果。
虽然我们现在已经无法改变很多事情,但也并不是全部,而且我们依然可以着手提高功能性和简易性。不过,在这个过程中我们有时也会遇到一些困难:为了提高分片上 Layer2 的可扩展性,我们需要先增加一些复杂性以实现分片。但即便如此,复杂性的降低也是可能的,Ethereum 的历史已经证明了这一点:
1.EIP-150 使得调用堆栈深度限制不再适用,从而减少了合约开发者对于安全性的担忧。
2.EIP-161 让「空账户」不再与字段为零的账户区分开。
3.EIP-3529 删除了部分退款机制,使得 Gas Token 不再可行。
有了 Verkle 树等还在酝酿中的想法以后,我们甚至可以进一步降低复杂性。但如何在未来更好地平衡这两种愿景,是我们应该开始好好思考的问题。