来自 Vitalik 博客的文章:简析二层扩容方案状态通道 、 Plasma 、 Rollups 各自的技术优缺点,着重分析了 Optimistic rollup 和 ZK rollup 的可行性、安全性及应用前景?
原文链接: https://vitalik.ca/general/2021/01/05/rollup.html
Rollups解决方案在以太坊社区中正风靡一时,并有望在将来成为以太坊的关键扩容解决方案。但是这项技术究竟是怎样的呢?它能给我们带来什么?我们将如何使用这项技术呢?本文将尽量回答其中一些关键问题。
区块链扩容方式有两种。第一种,提高区块链本身的交易容量。这种技术的主要挑战就是:当区块容量越来越大时,区块链将越来越难验证,且中心化程度越来越高。为了避免此类风险,开发者可以提高客户端软件的效率。或者选择另一种更为可持续的方式:利用诸如分片技术,使得区块链上的构建区块和验证工作可以分散至许多节点 (Eth2升级正在尝试将此技术引入以太坊)。
第二种:改变使用区块链的方式。即用户不是将所有交易都直接在区块链上进行,而是通过二层协议在链下执行大部分交易。例如链上有一个智能合约,该合约只有两个任务:处理存款和提款、以及验证所有链下交易的有效性。对链下交易进行验证的方法有多种,但他们都具有同一个特性:在链上验证证明比在链下进行原始计算的成本要低得多。
二层扩容方案的三种主要类型是:状态通道、Plasma 和 rollups。他们是三种不同的范式,具有不同的优劣势。我们可以把所有二层扩容解决方案大致地归为这三类 (尽管有的方案因分类模糊而存在命名争议,如 validium)
假设 Alice 正给 Bob 提供互联网连接,作为交换,Bob 每兆字节向她支付 0.001 美元。他们不需要每一次支付都执行交易,而是使用下面的二层解决方案。
首先,Bob 向一个智能合约中存入 1 美元 (或等值的 ETH 或稳定币)。Bob 在一张写着 “0.001美元” 的票上进行签名 (一条链下信息),然后发给 Alice,这样就完成了对 Alice 的第一笔支付。而第二次支付时,Bob 在另一张写着 “0.002美元” 的票上进行签名,然后发给 Alice。以此类推,可以根据需要进行多次付款。当他们完成交易了,Alice 可以将面额最高的签名票单并加上自己的签名提交到链上。链上的智能合约将验证 Alice 和 Bob 的签名,然后向 Alice 支付 票据上的金额,并将剩余的钱退还给 Bob。如果 Alice 不愿意关闭他们之间的状态通道 (出于恶意行为或由于技术故障),则 Bob 可以启动提款期 (withdrawal period),如果 Alice 在这段期间内 (比如7天) 还是没有向 Bob 提供票据,那么 Bob 就可以在到期后拿回他的所有钱。
状态通道功能强大:可以对其进行调整,以进行双向支付、处理智能合约 (如,Alice 和 Bob 在通道中签订金融合约)、以及对通道进行组合 (比如,当 Alice 和 Bob、Bob 和 Charlie 之间有一条开放通道时,Alice 和 Charlie 也可以进行去信任交易)。
但状态通道的作用是有限的:无法在链外将资金发送给没有参与进来的用户;通道不能代表那些逻辑上没有明确所有者的对象 (如 Uniswap);并且如果要进行更为复杂的交易,需要在通道内锁定大量资金。
更多资料请参考:https://www.jeffcoleman.ca/state-channels 和 statechannels.org
用户向某个 Plasma 链的智能合约中发送一笔资产以完成存款。Plasma 链给该资产分配一个唯一的 ID (如 537)。每条 Plasma 链都有一名运营者 “operator” (他可以是一个中心化的角色、一个多签名者、或诸如 PoS/DPoS 此类更为复杂的东西)。每隔一段时间 (可以是15秒至1小时),运营者便会生成一个“打包”交易 (由在链下收集到的所有 Plasma 交易组成)。
Plasma 会生成一个默克尔树,树中每个索引 X
处,如有存在交易的话,会显示某笔转移交易资产 ID X
,如果没有交易,叶子值为零。随后他们将该默克尔树的默克尔根发送到链上,同时还会将每个索引 X
的默克尔分支发送给其资产的当前所有者。如果用户想要进行提款,那么就要把最近向其发送资产的交易的默克尔分支提交到链上。然后智能合约就将启动挑战期,在此期间,任何人都可以尝试使用其他默克尔分支来证明该提款无效。需要至少证明其中一项:(i) 发送方在发送资产时并不是该资产的所有者;(ii) 发送方在后来将资产发给了其他人。如果在某个时间段内 (如七天) 没有人证明该提款是欺诈性的,用户便可以取出他的资产。
Plasma 比状态通道拥有更加强大的性能:使用 Plasma,用户可以将资产发送给从未加入其系统的参与者;对资本的要求也低许多。但 Plasma 也是有缺点的:相比之下,在“正常操作”期间,通道不需要在链上进行任何数据传输,而 Plasma 要求每条链定期发布一个哈希。此外,在 Plasma 上转账不是即时确认的:用户需要等待周期结束并且等到区块被发布之后才能确认。
再者,Plasma 和状态通道都有一个关键弱点:它们背后的安全博弈是基于这样一个思想,即由两个系统控制的每个对象都有逻辑上的“所有者”。 如果该所有者不关心其资产,则可能涉及资产“无效”的结果。这对许多应用程序来说是可以接受的,但是对于许多其他应用来说 (如 Uniswap) 来说是破坏交易的因素。甚至在一些系统中对象的状态不经其所有者的同意就可以被改变 (如基于账户的系统,你可以不经某人的同意就可以提升其余额),这些系统也不适用 Plasma。这意味着,当部署任何实际 Plasma 或状态通道时,都需要大量的“针对某个特定应用程序的推理”,并且不可能创建一个完全模拟以太坊环境 (或“EVM”) 的 Plasma 或者状态通道系统。为了解决此问题,各种 rollup 方案出现了。
更多资料请参考:最初的 Plasma 论文,以及 Plasma Cash。
Plasma 和状态通道是“完全”的二层方案,因为其将数据和计算都移至链下。然而,围绕“数据可用性”的基本博弈论问题意味着这些方案不一定对于所有应用来说都是安全的。Plasma 和通道方案的解决方式是依靠所有者完全知晓状态,但这使得此类方案无法完全通用化。Rollups,则是一种“混合型”二层方案。Rollups 将计算 (以及状态存储) 移至链下,但将每笔交易的一些数据放在链上。为了提高效率,这类方案借助了许多复杂的压缩技巧以尽可能使用计算替代数据。结果是系统的扩容性仍然受到底层区块链的数据带宽限制,但比较来看仍十分有利:以太坊基础层 ERC20 代币的转移成本约为 45000 gas,而 rollup 中的 ERC20 代币仅转移占用 16 字节的链上空间,成本不到 300 gas。
数据在链上这一点很关键 (请注意:将数据“放在 IPFS 上”是行不通的,因为 IPFS 不能为任何给定的数据是否可用提供共识;数据必须被记录在链上)。将数据放在链上并对此达成共识,使得任何人都可以根据需要在本地处理 rollup 中的所有操作(如果他们想的话),从而允许其对欺诈进行监测、发起提款或亲自开始批量生成交易。缺乏数据可用性意味着一名恶意的或是离线的运营者能够产生的影响甚至会更小 (例如他们无法造成一周的延迟),从而为有权发布批量交易的人打开更大的设计空间,并使 rollup 更容易有理可循。更重要的是,缺乏数据可用性意味着不再需要映射资产到所有者,从而我们能得出以太坊社区相较之前的二层扩容方案对 rollups 更加期待的关键原因之一:rollups 是完全通用的,我们甚至还可以在 rollup 内部运行 EVM,使得既有的以太坊应用几乎不需要编写新代码就能迁移到 rollups 上。
其他资源参考:EthHub on optimistic rollups和ZK rollups
Rollup在链上有一份智能合约用来维护状态根,即 rollup 状态的默克尔根 (也就是 rollup 内部的账户余额、合约代码等等)。
任何人都可以发布一个汇总交易 (batch),这是一个高度压缩的交易集合,其中包含之前的状态根和新状态根 (处理交易之后的新默克尔根)。该合约会检查汇总交易中的旧状态根是否匹配其当前的状态根,如果匹配的话,合约会对状态根进行更新。
为了支持存款和提款,我们增加了输入和输出在 rollup 状态“外部”的交易的功能。如果一个 batch 中包含来自外部的输入,则提交到该 batch 的交易也需要将资产转移到 rollup 合约。如果一个 batch 中包含来自外部的输出,则智能合约在处理该 batch 时会发起提款。
这就是 rollup 的工作原理了。但还有一个重要细节:如何得知 batches 里的后状态根 (post-state root) 是正确的呢?如果某人能够提交一个具备任意后状态根的 batch,而无需承担任何后果,他们完全可以将 rollup 中的所有代币都转移给自己。这个问题很关键,因为由此诞生了两种不同的解决方案,这两种解决方案又衍生出了两种不同的 rollups。
这两种 rollups 为:
这两种 rollup 之间存在复杂的权衡:
特性 | Optimistic rollups | ZK rollups |
---|---|---|
每 batch 的固定 gas 消耗 | 约 40,000 (轻量交易,主要只是改变状态根的值) | 约 500,000 (验证 ZK-SNARK 所需计算量较大) |
提款期 | 约一周 (提款存在延迟,需要留出时间提交欺诈证明,如果发生欺诈需要取消提款) | 极快 (只需要等到下一个 batch) |
技术复杂度 | 低 | 高 (ZK-SNARK 是一种非常新的技术,并且数理复杂) |
通用性 | 易达成 (通用的 EVM rollups 即将登陆主网) | 较难达成 (使用 ZK-SNARK 证明的通用 EVM 执行相较简单计算证明难度更大) |
每笔链上交易的 gas 消耗 | 较高 | 较低 (如果一笔交易中的数据只用作验证,不引发状态改变,那么能够省去该数据,在 optimistic rollup 中则需要发布,因为有可能在欺诈证明中需要对其进行查验) |
链下计算成本 | 较低 (尽管需要大量全节点重新进行计算) | 较高 (专门针对通用计算的 ZK-SNARK 证明可能会很昂贵,比直接运行计算可能要贵数千倍) |
总的来说,我个人的观点是,在短期内,optimistic rollup 的显著优势在于其通用的 EVM 计算,而 ZK rollup 更可能被用于支付、交易和其他特定用例。但中长期来看,随着 ZK-SNARK 技术的成熟,ZK rollup 会在所有用例中发挥出优势。
Optimistic rollup 的安全性保障主要来自于:如果有人在 rollup 中发布了一个无效的 batch,其他任何跟进该链的用户监测到欺诈行为都可以发布欺诈证明,向合约证明该 batch 的无效性,并进行回滚。
在上图中,声称某 batch 无效的欺诈证明会包含绿色的数据:如果要证明特定账户被该 batch 读取和/或被修改,则需要提供 batch 本身 (可以对照存储在链上的哈希值进行检查) 和 Merkle 树的各个部分。而图中黄色的节点,能够被绿色的节点重构,因此不需要提供。该数据已经足够执行 batch 并计算后状态根 (这与 无状态客户端 验证单个区块的方式几乎相同)。如果经计算的后状态根以及获得的 batch 中的后状态根不一致,那么该 batch 就是无效的。
可以保证如果某个 batch 不正确,但之前所有的 batches 都是正确的,那么就能够创建一个欺诈证明以表示该 batch 是不正确的。请注意对之前 batch 的声明:如果有超过一个无效的 batch 被发布到 rollup 中,那么最好尝试证明最早的无效 batch。也可以说,如果某个 batch 是正确的,那么永远都无法创建一个欺诈证明表示其无效。
一笔简单的以太坊交易 (发送 ETH) 大小约为 110 字节。而在 rollup 上进行 ETH 转账,大小仅为约 12 字节:
参数 | 以太坊 | Rollup |
---|---|---|
Nonce | ~3 | 0 |
Gasprice | ~8 | 0-0.5 |
Gas | 3 | 0-0.5 |
To | 21 | 4 |
Value | ~9 | ~3 |
Signature | ~68 (2 + 33 + 33) | ~0.5 |
From | 0 (从签名中恢复) | 4 |
Total | ~112 | ~12 |
其中一部分只是简单的高级编码:以太坊的 RLP 编码方式在每个值上会浪费 1 字节。但是其中还包括一些机智的压缩技巧:
ZK rollups 特有的一个重要压缩技巧是:如果交易的一部分信息仅用于验证,并且不用于计算状态更新,那么该部分可以移至链下。Optimistic rollup 无法做到这一点,因为该数据仍然需要存在链上,以备需要在欺诈证明中进行检查的不时之需。而在 ZK rollup 中,SNARK 已经证明了 batch 的正确性,也就是说验证所需的数据已经齐全。具备隐私保护功能的 rollups 是一个重要例子:在 optimistic rollup 中,每笔交易中用于隐私保护的 ZK-SNARK 证明需要在链上,需要占据约 500 字节。而在 ZK rollup 中,包含整个 batch 的 ZK-SNARK 已经在“内部”证明了 ZK-SNARK 的有效性。
这些压缩技巧是 rollups 扩容性的关键,否则 rollups 扩容性相较底层链只能提高约 10 倍 (虽然对于某些特定的计算密集型应用来说,简单的 rollups 方案已经足够),而对数据进行压缩后,几乎对所有应用来说,扩容性都可以实现 100 倍以上的提升。
对于 optimistic rollups 和 ZK rollups 中交易的打包权有许多说法。一般来说,任何想要参与打包交易并提交交易的用户,需要先锁定大量存款。如果用户提交了包含欺诈/无效交易的 batch (例如包含无效状态根),那么该用户的存款的一部分会被销毁,另一部分则作为欺诈证明者的奖励。不过,也存在其他可能方式:
目前正在开发的一些 rollup 项目采用了“分离-打包”的方式,也就是将提交二层交易的 batch 和提交状态根的过程是分离的。这种做法的优势在于:
总之,在效率、简洁性和抗审查性等方面的权衡十分复杂,许多方案也在进行探索。目前要判断哪些概念是最佳组合还为时尚早,时间会证明一切。
在现有的以太坊链上,gas上限是1250万,一笔交易里,每个字节的数据消耗16 gas。这意味着如果一个区块只包含一个batch (假设使用 zk rollup,在证明验证上花费50万gas),那一个batch可以包含 (1200 万 / 16) =750,000 字节的数据。如上文所示,对于一个以太坊转账的rollup,每一次用户操作只需 12 个字节,也就是说该批交易可以包含高达6.25万笔交易。现在平均出块时间为13秒,即相当于大约每秒4807笔交易 (相比之下,现在直接在以太坊上转账是每秒 1250万/21000/13~=45笔交易 )
其他用例的扩容表现表格如下:
场景 | rollup 所占的字节 | 一层的gas消耗 | 扩容的最高水平 |
---|---|---|---|
ETH 转账 | 12 | 21,000 | 105x |
ERC20转账 | 16 (需要额外 4 个字节来指定代币) | ~50,000 | 187x |
Uniswap 上的交易 | ~14 ( 发送者 4 个字节+接收者 4 个字节+交易值 3 个字节+最高价格 1 个字节+其他杂项 1 字节) | ~100,000 | 428x |
保护隐私的取款 (Optimistic rollup) | 296 (根索引 4 个字节+nullifier 32 个 字节+接收者 4 个字节+ZK-SNARK 证明 256 个字节) | ~380,000 | 77x |
保护隐私的取款 (ZK rollup) | 40 ( 根索引 4 个字节+nullifier 32 个字节+接收者 4 个字节) | ~380,000 | 570x |
扩容的效果上限是这样计算的:(一层的 gas消耗)/(rollup所占的字节 *16)* 1200万 / 1250千万
现在,值得注意的是这些数据都过于乐观了,原因有几个。最重要的是,一个区块几乎不可能只包含一批交易,因为最起码会有多个rollup。第二,存款和取款行为会一直存在。第三,在短期,使用率会比较低,所以固定消耗会占主导。但即使这些因素都考虑到了,超过100倍的扩容水平也有望成为常态。
如果我们想每秒交易量达到 1000-4000 呢 (取决于特定的用例)?这就是eth2 数据分片发挥作用的时候了。分片协议为每 12 秒提供 16MB 的空间来容纳任何数据,且系统确保数据可用性的共识。数据空间可以被rollup使用。这大约每秒 1398kb 的空间比现在以太坊链上每秒大约 60kb 提高了23倍,且在更长期来看,数据容量有望继续增加。因此,使用 eth2 分片数据的rollup可以以每秒约 10 万笔交易的吞吐量批量处理,在未来可能更多。
尽管 rollup 的基本概念现在你已经有所了解,我们十分确信它们是可行且安全的,现在多种 rollup 已经部署到主网上,但 rollup 设计还有很多领域未被充分探索,以及在如何把以太坊生态上的大部分活动引入到 rollup 上,以利用它们的可扩容性这件事上,还存在不少困难。一些关键的困难包括:
Rollup是一个强大、新颖的二层扩容范式,并有望成为以太坊在中短期未来 (也可能是长期) 扩容的基石。以太坊社区已经表现出对 rollup 的强烈兴趣,因为不像之前在二层扩容的尝试,它们可以支持通用的EVM代码,使得现有的应用可以轻易迁移。Rollup 有一个重要的妥协:交易处理不是完全在链下进行,而是每笔交易留下一小部分数据在链上。
rollup 有很多种,在设计空间上有很多选择:可以是使用欺诈证明的Optimistic Rollup,也可以是使用有效性证明 (即 ZK-SNARKs) 的 ZK Rollup。排序者 (可以发布汇总交易到链上的用户)可以是中心化的角色、自由个体、或两者间的很多其他可能性。rollup还是早期的技术,其开发在不断快速地进行中,但它们是可行的,且其中有些 (比较有名的是路印、ZKSync、和DeversiFi) 已经运行数月了。期待今年 rollup 会有更多令人振奋的成果。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!