在以太坊生态系统中,最大的挑战之一是在资源严重制约(如 CPU、带宽、内存、磁盘空间)的情况下,如何实现低延迟和高吞吐量。
系统的去中心化是由网络中最弱的节点验证系统规则的能力所决定的。可以在低资源硬件上运行的高性能协议,可以被称为「可伸缩」。
在这篇文章中,我们将深入探讨当前「2 层解决方案」的原理、它们对应的安全模型,以及它们如何解决以太坊的可伸缩性问题。
如果你有兴趣了解更多关于前沿的以太坊的可伸缩技术,想要知道如何构建和架构此类系统,那么这篇文章或许对你有帮助。
在整个文章中,重要的关键词或概念会用粗体突出显示,这些都是你在学习加密货币知识的过程中会遇到的单词 / 术语。这个话题很复杂。也许读的过程中会感觉有点困惑,但只要坚持看完,相信将有所收获。
区块链资源需求
有三个因素会影响去中心化网络(如比特币和以太坊)中运行节点的资源需求:
带宽:下载和广播任何与区块链相关的数据的成本。
计算:在脚本或智能合约中运行计算的成本。
存储:为编制索引而存储事务数据的成本,以及为继续处理新的事务块而存储「状态」的成本。值得注意的是,存储「状态」(帐户余额、合约字节码、nonce 值)比存储原始事务数据成本更高。
衡量性能的方法有 2 种:
吞吐量:系统每秒可以处理的事务数量。
延迟:事务处理所需的时间。
比特币和以太坊这类新兴加密网络的理想属性是去中心化,但是使网络去中心化的构成要素是什么呢?
低信任度:这个属性可以让任何个人验证比特币的数量不会超过 2,100 万,或者说他们的比特币不会被伪造。独立运行节点软件的人员会计算最新的状态,并验证在此过程中是否遵循了所有规则。
低成本:如果节点软件的操作成本很高,个人将依赖可信的第三方来验证状态。高成本意味着高信任需求,这是我们首先想要避免的。
另一个需要的属性是可伸缩性:将吞吐量和延迟以超线性的方式扩展到运行系统的成本的能力。这个定义很好,但没有包含「信任」。因此,我们明确了「去中心化的可伸缩性」:在不显著增加系统信任假设的情况下实现可伸缩性。
放大来看,以太坊的运行时环境是以太坊虚拟机(EVM)。通过 EVM 运行的事务以不同的成本执行各种操作,例如,存储操作的成本高于添加操作的成本。事务中的计算单元称为「gas」,系统的参数设置为每个区块最多处理 12.5m gas,平均每 12.5 秒产生一个事务区块。因此,以太坊的延迟为 12.5 秒,吞吐量为每秒 100 万 gas。
你可能会问:每秒 100 万 gas 能带来何种效益?
每秒 ~47 笔「简单转账」事务。这些事务消耗 21,000 gas, 负责将 ETH 从 A 转移到 B,是最简单的事务类型。
每秒 ~16 笔 ERC20 代币转账。与 ETH 转账相比,这些方法涉及更多的存储操作,因此每次的成本为 ~60k gas。
每秒 ~10 笔 Uniswap 资产交易。代币对代币交易的平均成本约为 102k gas。
…随便挑一个你喜欢的事务的 gas 成本,并将其除以 1m (12.5m / 12.5 /gas)
注意,随着事务的执行复杂度增加,系统的吞吐量会降低到很低的数值。还有改进的空间!
解决方案 1:使用一种中介
我们可以使用一个可信的第三方来促成所有的事务。这样一来,我们就能获得非常高的吞吐量,而且延迟可能只会是亚秒级的。太好了 ! 这不会改变任何系统范围内的参数,但我们将会选择加入第三方单方面设定的信任模式。他们可能会选择对我们进行审查,甚至没收我们的资产。这是不可取的。
解决方案 2:让区块更大,更频繁
我们可以通过减少两个区块之间的时间来减少延迟,也可以通过增加区块 gas 限制来增加吞吐量。这一改变将使运营节点的成本更高,使得个人难以运行节点(这一点已经在 EOS、Solana、Ripple 等平台出现了)。
在解决方案 1 中,对信任的需求增加了。在方案 2 中,成本增加。这就消除了它们作为可伸缩性选项的可能性。
从第一原则出发,重新发现 Optimistic Rollup
在下一节中,我们假设读者对哈希和默克尔树已经有所了解。
根据我们到目前为止学到的知识,让我们模拟一个苏格拉底对话,目标是发现一种既能增加以太坊有效吞吐量,同时又不增加用户和节点操作者负担的协议。
问:我们想在不显著改变信任和成本假设的情况下扩展以太坊。该怎么做呢?
答:我们想要降低现有操作对系统成本的要求(见上面的三种资源类型)。为了理解为什么要做到这一点并不容易,我们需要先看看以太坊的架构:
以太坊的每个节点目前都存储并执行用户提交给它的每笔事务。在执行过程中,事务通过 EVM 运行,并与 EVM 的状态(例如存储、余额等)交互——这种操作非常昂贵。常见的智能合约优化技术以最小化与状态的交互次数为核心,但它们只能提供较小的常量改进。
问:你是说有一种方法可以在不涉及状态的情况下进行交易,从而保持较低的资源成本?
答:在极限情况下,我们是否可以把所有的执行都移出链外,同时保留一些数据在链上?我们可以通过引入一个被称为「排序者」 (sequencer) 的第三方来实现这一点。他们负责本地存储和执行用户提交的事务。为了保持系统的活跃度,排序器需要定期提交他们接收到的事务的默克尔根以及以太坊上产生的状态根。这是朝着正确方向迈出的一步,因为我们只在以太坊的状态中存储 O (1) 数据,用于 O (N) 链下交易。
问:所以我们通过让排序者计算链下的一切,只发布默克尔根来实现伸缩?
答:是的。
问:好的,所以一旦你加入,排序器能保证你的转账费用很便宜。那么存款和提现会如何操作?
答:用户将通过在以太坊上存钱的方式进入系统,然后排序者将相应的金额记入用户的账户。用户可以在以太坊上提出这样的交易内容,比方说,「我想提现 3 个 ETH,我的账户目前有 >3 ETH,这是证明」。即使第 1 层没有实际的用户状态,用户也能拿出排序器发布的状态根显示相关的默克尔证明,表明他们在当前状态下有足够的资金。
问:现在我们知道了,用户需要默克尔证明来提取他们的资金。用户如何获得构建默克尔证明的数据?
答:他们可以要求排序者给他们提供数据!
问:万一排序者暂时或永久不可用,那该怎么办?
答:排序者可能是恶意的,也可能只是因为技术问题而离线,这将导致性能下降(或者更糟,偷走你的资产!)。因此,我们还必须要求排序者在链上提交完整的事务数据来进行存储,但不能执行。在这个问题上,目标是获得数据可用性。假设所有数据都永久存储在以太坊上,即使排序者消失了,新的排序者也可以从以太坊中检索所有第 2 层相关的数据,重建最新的第 2 层状态,并从他们的前任离开的地方继续。
问:如果排序者在线,但拒绝向我提供默克尔证明数据,我可以从以太坊下载吗?
答:没错,你可以自己同步一个以太坊节点,或者连接到众多托管节点服务中的一个。
问:有一点我还是不明白,你怎么能在以太坊存储东西而不执行它呢?不是每个事务都要通过 EVM 吗?
答:假设你提交了 10 个事务,将 ETH 从 A 转移到 B。执行每笔事务都将执行以下操作:增加 A 的 nonce,减少 A 的余额,增加 B 的余额。这得从以太坊的世界状态里进行相当多的写入和读取。相反,你可以将所有事务的编码发送到智能合约的 publish (bytes _transactions) public { } 函数中。注意,该函数的主体是空的!这意味着发布的交易数据不会被解释、执行,也不会在任何地方进行状态访问,它只是存储在区块链的历史日志中(写入的成本很低)。
问:我们能信任排序者吗?万一他们发布了一个无效的状态转换怎么办?
答:任何时候排序者在发布一批状态转换时,都会有一个「争议期」,在这期间任何一方可以发布「欺诈证明」以表明其中某个状态转换无效。这可以通过在链上重放导致状态转换的事务,并将产生的状态根与排序者发布的状态根进行比较来证明。如果状态根不匹配,则欺诈证明成功,并取消状态转换。如果在无效的状态转换之后还有更多的状态转换,它们也会被取消。但如果事务已经过了争议期,就没法再对其质疑了,它们会被视为最终交易。
问:等一下!你之前说过,如果 a)增加成本,或 b)引入新的信任假设,那么它就不属于可伸缩性。在你描述的方案中,我们不是又另外假设总是会有人举报欺诈吗?
答:是的。我们假设存在一个被称为「验证器」的实体,他们负责监视欺诈行为,如果第 1 层和第 2 层状态不匹配,他们就会发布欺诈证据。我们还假设验证器能够在争议期限内可靠地获得以太坊中包含的欺诈证据。我们认为验证器的存在是一个「弱」假设。想象一下,如果有一个应用程序有成千上万的用户,你只需要一个人来运行一个验证器。这听起来不算太离谱!另一方面,改变以太坊的信任模式,或增加以太坊节点的运营成本是我们不想做的「强」假设改变。这就是我们在定义去中心化的可伸缩性时所说的「显著改变底层系统的假设」。
问:我同意有人会运行一个验证器,因为各方都能从这个新解决方案的成功中获益。但当然这也取决于实际操作的成本。那么运行一个验证器和一个排序器的资源需求是什么?
答:排序者和验证者必须运行一个以太坊完整节点(不是存档节点),一个完整的第 2 层节点,才能生成第 2 层状态。验证者运行的软件负责创建欺诈证明,排序者运行的软件负责捆绑用户事务并予以发布。
问:就是这样吗?
答:是的!恭喜你!您已经重新发现了Optimistic Rollup(Optimistic Rollup 是「Optimistic 合约」和「链上数据可用性」(又名「数据汇总」)的组合),这是 2019-2021 年最令人期待的伸缩解决方案。原因很好理解,因为它是以太坊社区多年研究过程的最终产物,你应该已经在上面这个简短的对话中体会到了这一点。
Optimistic 的激励
第 2 层的扩展基于这样一个事实:我们试图最小化执行的链上事务的数量。我们使用欺诈证明来取消任何可能发生的无效状态转换。由于欺诈证明是链上交易,我们还希望将以太坊上发布的欺诈证明的数量最小化。在理想的情况下,欺诈从未发生过,因此,欺诈的证明也从未被发出。
我们通过引入忠诚债券(fidelity bond)来抑制欺诈行为。为了让用户成为排序者,他们必须首先在以太坊上发布一个债券,如果被证明存在欺诈,他们将丧失该债券。为了激励个人发现欺诈行为,排序者的债券在被削减后会分发给验证者。
忠诚债券和争议期
在设计欺诈证据的激励机制时,有两个参数需要调整:
忠诚债券规模:排序者必须公布分发给验证者的数量。规模越大,成为验证者的动机就越大,而作为排序者进行欺诈的动机就越小。
争议期期限:可以发布欺诈证明的时间窗口,在此时间窗口之后,第 2 层交易在第 1 层上被认为是安全的。争议期较长,可以为防止审查攻击提供更好的安全保障。争议期较短,则能为从第 2 层撤回到第 1 层的用户创造良好的用户体验,因为他们不需要等待很长时间就可以在第 1 层上重新使用他们的资金。
在我们看来,对于这两个参数都无法找到一个确切的静态值。也许 10 个 ETH 债券和 1 天的争议期足矣。但也许 1 个 ETH 和 7 天也够。真正的答案是,这取决于成为验证者的动机(这取决于运行成本),以及发布欺诈证明的难易程度(而这取决于第 1 层的拥塞程度)。这两者都应该是可调的,可以手动调,也可以自动调。
值得一提的是,EIP1559向以太坊引入了一个新的 BASEFEE 操作码,该操作码可用于估计链上的拥塞,并因此以编程方式调整争议期的持续时间。
如何正确实施这一惩罚机制至关重要,否则它将在实践中被人滥用。我来举个例子,说明什么是幼稚而没有实操性的实现:
Alice 贴出了一个 1 ETH 债券,她因此得以在系统中担任排序者
Alice 发布了一个欺诈状态更新
Bob 注意到了这一点,并发表了一项争议。如果成功,这将能把 Alice 债券中的 1 个 ETH 授予 Bob,并取消欺诈状态更新
Alice 注意到了这个争议 ,也发表了一个争议 (挑战她自己!)
ALice 得到了她的 1 ETH,即使她试图欺诈,实际上也没有受到任何惩罚。
Alice 可以通过「抢跑」的方式来发动这种攻击,即广播与 Bob 相同的交易,但 gas 价格更高,从而导致 Alice 的交易在 Bob 之前执行。这意味着 Alice 可以持续尝试以最小的成本(仅含以太坊交易费用)作弊。
解决这个问题很简单:不是将全部债券授予争论者,而是将 X% 的债券烧毁。在上面的例子中,如果我们烧掉 50%,那么 Alice 将只会得到 0.5 个 ETH,这就足以阻止其在步骤 2 中尝试作弊。当然,销毁债券减少了运行验证器的动机(因为支付变得更少了),因此需要确保债券在烧掉部分后依然足以激励用户成为验证者。
对 Optimistic Rollup 常见的批评和我们的回应
现在我们已经完成了 Optimistic Rollup 的构建模块,让我们探讨并解决对该机制的最流行的批评。
长时间的提款 / 争议期对于采用和可组合性是致命的
我们在上面提到过,长期的争议期对安全有好处。这里似乎存在一种固有的取舍:争议期过长对用户来说不好,因为用户如果想要提取资金的话需要等待很长时间。争议期较短,当然能带来流畅的用户体验,但这样你就会冒欺诈发生的风险。
我们认为这不成其不问题。由于存在漫长的提现延迟可能性,我们预计做市商将迅速介入并提供更快的提现服务。这是可能的,因为验证第 2 层状态的人可以正确判断一个提现是否存在欺诈的可能,从而会以较小的折扣来「购买」 他们的服务。举个例子:
参与者:
Alice:在第 2 层有 5 个 ETH。
Bob:在「做市商」智能合约中,第 1 层上有 4.95 ETH,并且在第 2 层上运行一个验证器
步骤:
Alice 让 Bob 知道她想要「快速」取款,并向他支付 0.05 ETH 的费用
Alice 向 Bob 的「做市商」智能合约发出取现要求
此时可能会发生两种情况:
Bob 在他的第 2 层验证器上检查提款是否有效,并批准快速取款。这将立即将 4.95 ETH 转移到 Alice 的第 1 层地址。在提款期结束后,鲍勃可以领取这 5 个 ETH,净赚一笔。
Bob 的验证者提醒他该交易无效。Bob 对该交易引起的状态转换提出异议,取消交易,并因排序者允许恶意交易发生而赚取其债券。
爱丽丝要么是诚实的,立即把钱拿出来,要么是不诚实的,会受到惩罚。我们希望支付给做市商的费用会随着时间的推移而压缩,如果有对这项服务的需求的话,最终让用户完全看不到这个过程。
该特性最重要的含义是,它可以实现与第 1 层合约的可组合性,而不必等待完整的争议期。
注意,这种技术最早在「Simple Fast Withdrawals」(简单快速提现)一文中描述过。
矿工可以通过贿赂来审查提现,破坏 Optimistic Rollup 的安全
在「Optimistic Rollup 的近零成本攻击场景」的帖子中,有人认为,矿工的激励过大,这会导致排序者与以太坊矿工勾结,不愿去审查任何有争议的交易。当然,考虑到系统安全对于解决争议的依赖,这对任何 Optimistic 体系都是致命的。
我们不同意这篇文章的论点。我们假设,诚实的一方总是愿意贿赂矿工,而且能提供比恶意方更多的资金。此外,每当矿工们因为帮助恶意方获胜而偏离「诚实」行为时,都会产生额外的成本。这种行为会破坏以太坊的价值,而这反过来会增加矿工从事这种行为的额外成本。
事实上,这种情况已经在学术文献中得到了研究,证明了「这种反击的威胁会诱导出一种不发生攻击的子博弈完美均衡」。
我们要感谢 Hasu 让我们注意到这篇论文的论证。
验证者的困境对操作验证器、破坏 Optimistic Rollup 产生了抑制
针对验证者的困境,Ed Felten撰写了一个出色的分析和解决方案,我们总结如下:
如果该体系的激励机制如预期那样发挥作用,就没有人会作弊
如果没有人作弊,那么运行一个验证程序就没有意义了,因为你从操作它中赚不到钱
因为没有人运行验证器,所以最终有机会让排序者作弊
排序者作弊,系统不再按预期运行
这听起来很重要,而且近乎自相矛盾的。在假设奖励规模固定的情况下,更多的验证者会减少单个验证者的预期报酬。此外,验证者多了,能分到的蛋糕似乎就会随之减少,发生的欺诈行为更少,这进一步加剧了这个问题。在后续分析中,Felten 还提供了一种解决验证者困境的方法。
我想在这里采取相反的立场,我认为验证者的困境并不像批评者说的那么重要。在实践中,作为一个验证者是存在非金钱激励的。比方说,你可能在一个汇总平台上构建大型应用程序,也可能持有代币,如果系统失败,那么你的应用程序将无法运行,或者你持有的代币将会贬值。除此之外,对快速提款的需求为做市商验证者创造了存在的动力(正如我们在上一节所看到的那样),这并不受欺诈行为的影响。说得更具体一点,比特币没有提供任何激励措施来存储整个区块链历史或向同行提供你的本地数据,但人们还是无私地这样做。
即使在真空环境中运行验证器并不符合激励机制,它也能保证系统的安全,这对于那些投资于系统成功的实体来说是最重要的事情。因此,我们认为在 Optimistic 系统的第 2 层中,不需要设计机制来绕过验证者的困境。
结论
我们分析了 2021 年对以太坊至关重要的技术之一: Optimistic Rollup。
总结其好处:Optimistic Rollup 是以太坊的扩展,它承载了以太坊的安全性、可组合性和开发人员护城河,同时提高了性能,不会对以太坊用户的成本或信任需求造成实质性的影响。我们探索了使 Optimistic Rollup 发挥作用的激励结构,并对常见的批评提出了回应。
我们想要强调的是,Optimistic Rollup 的性能上限是由第 1 层上发布的数据所决定的。因此,它的优点在于:1) 尽可能地压缩你发布的数据(例如通过BLS 签名聚合),2) 拥有一个大而廉价的数据层(例如 ETH2)。
作为补充阅读,我们推荐 Buterin 的关于 Rollup 和信任模型的不完整指南。我们还建议去研究 Optimistic Rollup 的近亲 ZK Rollup。最后,还有其他方法可以获得去中心化的可伸缩性,即分片和状态通道,它们各有优缺点。