原文标题:Vitalik:Rollups 不完全指南
Rollups解决方案在以太坊社区中正风靡一时,并有望在将来成为以太坊的关键扩容解决方案。但是这项技术究竟是怎样的呢?它能给我们带来什么?我们将如何使用这项技术呢?本文将尽量回答其中一些关键问题。
背景:何为一层、二层扩容?
区块链扩容方式有两种。第一种,可以提高区块链本身的交易容量。这种技术的主要挑战就是:当区块容量越来越大时,区块链将越来越难验证,且中心化程度越来越高。为了避免此类风险,开发者可以提高客户端软件的效率。或者选择另一种更为可持续的方式:利用诸如分片这类技术,使得区块链上的构建区块和验证工作可以分散至许多节点 (Eth2 升级中就会将此技术引入以太坊)。
第二种,可以改变使用区块链的方式。即用户不是将所有交易都直接在区块链上进行,而是通过二层协议在链下执行大部分交易。好比链上有一个智能合约,该合约只有两个任务:处理存款和提款交易、以及验证所有链下交易的有效性。对链下交易进行验证的方法有多种,但他们都具有同一个特性:在链上验证证明比在链下进行原始计算的成本要低得多。
状态通道 vs Plasma vs Rollups
二层扩容方案的三种主要类型是:状态通道、Plasma 和 rollups。他们是三种不同的范式,具有不同的优劣势。我们可以把所有二层扩容解决方案大致地归为这三类 (尽管有的方案因分类模糊而存在命名争议,如 validium)。
状态通道的原理
更多资料请参考:
https://www.jeffcoleman.ca/state-channels and statechannels.org
假设 Alice 正给 Bob 提供互联网连接,作为交换,Bob 每兆字节向她支付 0.001 美元。他们不需要每一次支付都执行交易,而是使用下面的二层解决方案。
首先,Bob 向一个智能合约中存入 1 美元 (或等值的 ETH 或稳定币)。Bob 在一张写着 “0.001美元” 的票上进行签名 (一条链下信息),然后发给 Alice,这样就完成了对 Alice 的第一笔支付。而第二次支付时,Bob 在另一张写着 “0.002美元” 的票上进行签名,然后发给 Alice。以此类推,可以根据需要进行多次付款。当他们完成交易了,Alice 可以将数值最高的票单发布到链上,并对其进行签名。链上的智能合约将验证 Alice 和 Bob 的签名,然后向 Alice 支付 Bob 票据上的金额,并将剩余的钱退还给 Bob。
如果 Alice 不愿意关闭他们之间的状态通道 (出于恶意行为或由于技术故障),则 Bob 可以启动提款期 (withdrawal period),如果 Alice 在这段期间内 (比如7天) 还是没有向 Bob 提供票据,那么 Bob 就可以拿回他的所有钱。
该技术功能强大:可以对其进行调整,以进行双向支付、处理智能合约关系 (如,Alice 和 Bob 在通道中签订金融合约)、以及对通道进行组合 (比如,当 Alice 和 Bob、Bob 和 Charlie 之间有一条开放通道时,Alice 和 Charlie 也可以进行去信任交易)。
但状态通道的作用是有限的:无法将资金在链外发送给没有参与进来的用户;通道不能代表那些逻辑上没有明确所有者的对象 (如 Uniswap);并且如果要进行更为复杂的交易,需要在通道内锁定大量资金。
Plasma 的原理
更多资料请参考?
最早的 Plasma 论文 :
http://plasma.io/plasma-deprecated.pdf
Plasma Cash:
https://ethresear.ch/t/plasma-cash-plasma-with-much-less-per-user-data-checking/1298
用户向某个 Plasma 链的智能合约中发送一笔资产以完成存款。Plasma 链给该资产分配一个唯一的 ID (如 537)。每条 Plasma 链都有一名运营者 “operator” (他可以是一个中心化的角色、一个多签名者、或诸如 PoS/DPoS 此类更为复杂的东西)。每隔一段时间 (可以是15秒至1小时),运营者便会生成一个等待批量处理的汇总交易 (由他们在链下收集到的所有 Plasma 交易组成)。
这些运营者会生成一个默克尔树,树中每个索引 X 处,如有存在交易的话,会显示某笔转移交易资产 ID X,如果没有交易,叶子值为零。随后他们将该默克尔树的默克尔根发送到链上,同时还会将每个索引 X 的默克尔分支发送给其资产的当前所有者。
如果用户想要进行提款,那么就要公布其最近向其发送资产的交易的默克尔分支。然后智能合约就将启动挑战期,在此期间,任何人都可以尝试使用其他默克尔分支来证明该提款无效。需要至少证明其中一项:(i) 发送方在发送资产时并不是该资产的所有者;(ii) 发送方在后来将资产发给了其他人。如果在某个时间段内 (如七天) 没有人证明该提款是欺诈性的,用户便可以取出他的资产。
Plasma 比状态通道拥有更加强大的性能:使用 Plasma,用户可以将资产发送给从未加入其系统的参与者;对资本的要求也低许多。但 Plasma 也是有缺点的:在“正常操作”期间,通道不需要任何数据就可以在链上进行传输,而 Plasma 要求每条链定期发布一个哈希。此外,在 Plasma 上转账不是即时的:用户需要等一段时间并且等到区块被发布之后。
再者,Plasma 和通道都有一个关键弱点:确保这两种方案安全的前提是,这两种系统所控制的对象都有逻辑上的“所有者”。如果该资产的所有者不关心其资产,那么可能会导致证明其资产无效的结果。这对许多应用程序来说是可以接受的,但是对于许多其他应用来说 (如 Uniswap) 来说是破坏交易原则的。甚至在一些系统中如果对象的状态不经其所有者的同意就可以被改变 (如基于账户的系统,你可以不经某人的同意就可以提升其余额),这些系统也不适用 Plasma。
这意味着,当部署任何实际 Plasma 或通道时,都需要大量的“某个特定应用程序的推理”,并且不可能创建一个模拟完全的以太坊环境 (或“EVM”) 的 Plasma 或者状态通道系统。为了解决此问题,各种 rollup 方案出现了。
Rollups
其他资源参见?
EthHub on optimistic rollups:
https://docs.ethhub.io/ethereum-roadmap/layer-2-scaling/optimistic_rollups/
ZK rollups:
https://docs.ethhub.io/ethereum-roadmap/layer-2-scaling/zk-rollups/
Plasma 和通道类是“纯粹”的二层方案,因为其将数据和计算都移至链下。然而,围绕“数据可用性”的基本博弈论问题意味着这些方案不一定对于所有应用来说都是安全的。Plasma 和通道方案的解决方式是依靠所有者完全知晓状态,但这使得此类方案无法完全通用化。Rollups,则是一种“混合型”二层方案。Rollups 将计算 (以及状态存储) 移至链下,但将每笔交易的一些数据放在链上。
为了提高效率,这类方案借助了许多复杂的压缩技巧以尽可能使用计算替代数据。结果是系统的扩容性仍然受到底层区块链的数据带宽限制,但比较来看仍十分有利:以太坊基础层 ERC20 通证的转移成本约为 45000 gas,而 rollup 中的 ERC20 通证仅转移占用 16 字节的链上空间,成本不到 300 gas。
数据在链上这一点很关键 (请注意:将数据“放在 IPFS 上”是行不通的,因为 IPFS 不能就任何给定的数据是否可用提供共识;数据必须被记录在链上)。将数据放在链上并对此达成共识,使得任何人都可以根据需要在本地处理 rollup 中的所有操作,从而允许其对欺诈进行监测、发起提款或亲自开始批量生成交易。缺乏数据可用性意味着一名恶意的或是离线的运营者能够产生的影响甚至会更小 (例如他们无法造成一周的延迟),从而为有权发布批量交易的人打开更大的设计空间,并使 rollup 更容易有理可循。
更重要的是,缺乏数据可用性意味着不再需要映射资产到所有者,从而我们能得出以太坊社区相较之前的二层扩容方案对 rollups 更加期待的关键原因之一:rollups 是完全通用的,我们甚至还可以在 rollup 内部运行 EVM,使得既有的以太坊应用几乎不需要编写新代码就能迁移到 rollups 上。
Rollup 的原理到底是什么?
在链上存在一份智能合约,其中包含一个状态根,即 rollup 状态的默克尔根 (也就是 rollup 内部的账户余额、合约代码等等)。
任何人都可以发布一批汇总交易 (batch),这是一个经由高度压缩的交易集合,其中包含之前的状态根和新状态根 (处理交易之后的新默克尔根)。该合约会检查 batch 中的旧状态根是否匹配其当前的状态根,如果匹配的话,合约会对状态根进行更新。
为了支持存款和提款,我们增加了输入和输出在 rollup 状态“外部”的交易的功能。如果一个 batch 中包含来自外部的输入,则提交到该 batch 的交易也需要将资产转移到 rollup 合约。如果一个 batch 中包含来自外部的输出,则智能合约在处理该 batch 时会发起提款。
这就是 rollup 的工作原理了。但还有一个重要细节:如何得知 batches 里的后状态根 (post-state root) 是正确的呢?如果某人能够提交一个具备任意后状态根的 batch,而无需承担任何后果,他们完全可以将 rollup 中的所有代币都转移给自己。这个问题很关键,因为由此诞生了两种不同的解决方案,这两种解决方案又衍生出了两种不同的 rollups。
Optimistic rollups 与 ZK rollups
这两种 rollups 为:
1. Optimistic rollups,其解决方案为欺诈证明 (fraud proofs):这类 rollup 会追踪所有历史状态根以及每个 batch 的哈希值。如果任何人发现某个 batch 的后状态根不正确,他可以向区块链发布一个证明,证明该 batch 计算错误。合约会对证明进行验证,并且对该 batch 及其之后的 batches 进行回滚。
2. ZK rollups,其解决方案为有效性证明 (validity proofs):每个 batch 都包含一个称作 ZK-SNARK 的密码学证明 (例如使用 PLONK 协议),以证明后状态根是正确执行 batch 的结果。无论计算量有多大,该证明都能在链上得到极速验证。
这两种 rollup 之间存在复杂的权衡:
总的来说,我个人的观点是,在短期内,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 字节:
其中一部分只是简单的高级编码:以太坊的 RLP 编码方式在每个值上会浪费 1 字节。但是其中还包括一些机智的压缩技巧:
Nonce:这个参数的主要目的是预防重放攻击。如果帐户的当前随机数为 5,则该帐户的下一个交易记录必须包含随机数 5,但是交易一经处理,该帐户中的随机数将增加为 6,因此无法再次处理该交易。在 rollup 中,我们可以完全省去随机数,因为我们可以直接从前状态中恢复随机数;如果有人尝试使用先前的随机数重放交易,签名将无法验证,因为会依据包含较高随机数的数据来对签名进行检查。
Gasprice:我们可以允许用户按固定 gas 价格范围进行支付,例如 2 的 16 次幂。或者我们可以在每个 batch 中收取固定的 gas 费用,甚至可以将 gas 费的支付完全移出 rollup 协议,让交易者使用通道向 batch 创建者支付相应费用。
Gas:同样地,我们可以将总 gas 设定为 2 的多次幂形式。或者我们也将 gas 限制在 batch 的水平。
To:可以用 index 来替换 20 字节的地址 (例如,如果某地址是被添加到默克尔树中的第4527个地址,我们只需使用 index 4527 来表示即可。然后向状态添加一个“子树” (subtree) 来存储index和地址本身的映射关系)。
Value:我们可以用科学记数法储存值。在大多数情况下,交易只需要 1-3 个有效位。
Signature:我们可以使用 BLS 聚合签名将大量签名聚合成一个约为 32-96 字节 (取决于协议) 的签名。该聚合签名可以依据消息集和 batch 的发送者集一次性进行检检查。表中的 “~0.5” 表示一个聚合签名中可以包含的签名数量是有限制的,因为需要能够在一个欺诈证明中对聚合签名进行验证。
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 (例如包含无效状态根),那么该用户的存款的一部分会被销毁,另一部分则作为欺诈证明者的奖励。除此之外,还存在其他可能性:
完全“无政府状态”:任何人都可以在任何时候批量打包交易并提交。这是最简单的方式,当然也存在缺陷。尤其是多个参与者同时尝试提交但最终只有一个 batch 能被成功打包。这会导致大量生成证明的工作和/或发布 batches 的 gas 被白白浪费。
中心化处理:存在一个行为者即排序者 (sequencer) 提交 batches (但提款存在例外:通常来说一个用户可以首先提交提款请求,如果排序这没有在下个 batch 中处理该提款,那么该用户能够自己提交一个 batch)。这是最“高效”的方式,但是依赖于一个中心化的角色。
排序者拍卖:通过定期举行拍卖的形式来确定谁有权成为下一个周期的排序者。其优点在于它可以筹集资金,并通过例如由 rollup 控制的机制 (例如 DAO) 来进行分配。(参见 MEV 拍卖)
PoS 集随机选择:任何人都可以将 ETH (或是 rollup 协议的代币) 存入 rollup 合约,然后在存款人中随机选择每个 batch 的排序者,被选中的可能性与锁定资产成一定比例。这个方式的主要缺点在于会有大量资本被锁定,而这是不必要的。
DPoS 投票:通过拍卖确定一个排序者,如果该行为人表现不佳,那么代币持有者可以通过投票将其驱逐,并发起新的拍卖。
将批量打包和状态根处理相独立
目前正在开发的一些 rollup 项目采用了“独立批量打包”的方式,也就是将提交二层交易的 batch 和提交状态根的过程分离。这种做法的优势在于:
1. 使得多个排序者能够同时发布 batches,以提高扛审查性,而避免了因为一些 batches 被首先打包而导致其他 batches 无效的问题。
2.如果某个状态根是无效的,我们不需要回滚整个 batch,可以只回滚状态根,并等待他人提供该 batch 的新状态根。这保障了交易发送方的交易不会被回滚。
总之,在效率、简洁性和抗审查性等方面的权衡十分复杂,许多方案也在进行探索。目前要判断哪些概念是最佳组合还为时尚早,时间会证明一切。
rollup能在多大程度上实现扩容?
在现有的以太坊链上,gas 上限是1250万,一笔交易里,每个字节的数据花费 16 gas。这意味着如果一个区块只包含一个batch (我们说相当于打包了一个 zk rollup,在证明验证上花费 50 万 gas),那一个 batch 可以包含 (1200 万 / 16) 750,000 字节的数据。如上文所示,对于一个以太坊转账的rollup,每一次用户操作只需 12 个字节,也就是说该批交易可以包含高达 6.25 万笔交易。现在平均出块时间为 13 秒,即相当于大约每秒 4807 笔交易 (相比之下,现在直接在以太坊上转账是每秒 1250万/21000/13~=45笔交易 )
以下表格是其他用例的例子:
扩容的最高水平是这样计算的:(一层的 gas消耗)/(rollup所占的字节 *16)*1200万/1250千万
现在,值得注意的是这些数据都过于乐观了,原因有几个。最重要的是,一个区块几乎不可能只包含一个 batch,因为最起码会有多个 rollup。第二,存款和提款行为会一直存在。第三,在短期,使用率会比较低,所以固定成本会占主导。但即使这些因素都考虑到了,超过 100 倍的扩容水平也有望成为常态。
如果我们想每秒交易量达到 1000-4000 呢 (取决于特定的用例)?这就是eth2 数据分片发挥作用的时候了。分片协议为每 12 秒提供 16MB 的空间来容纳任何数据,且系统确保数据可用性的共识。数据空间可以被 rollup 使用。这大约每秒 1398kb 的空间比现在以太坊链上每秒大约 60kb 提高了23倍,且在更长期来看,数据容量有望继续增加。因此,使用 eth2 分片数据的rollup可以以每秒约 10 万笔交易的吞吐量批量处理,在未来可能更多。
Rollup上还有哪些未解决的困难?
尽管 rollup 的基本概念现在已为人所了解,我们确信它们是完全可行且安全的,现在多种 rollup 已经部署到主网上,但 rollup 设计还有很多领域未被充分探索,以及在实现桥接以太坊生态上大部分的活动到 rollup 上,以利用它们的可扩容性这件事上,还存在不少困难。一些关键的困难包括:
用户和生态的入驻——使用 rollup 的应用不多,用户也不熟悉 rollup,只有少数钱包开始集成 rollup。商家与慈善机构也还不支持这种支付方式。
跨 rollup 交易——高效地从一个 rollup 移动资产与数据 (例如:预言机输出) 到另一个,而无须产生经由基础层的费用。
审计激励——如何最大程度提高至少有一个诚实节点完整验证一个 optimistic rollup 的机会,使得出现问题时他们会发布欺诈证明?对于小规模 rollup (高至每秒几百笔交易),这个问题不大,因为对矿工来说只是举手之劳,但对于大规模的 rollup 来说,还需要更充分的理由以说服矿工去做验证。
探索 plasma 和 rollup 之间的设计空间——是否有技术可以放一些 状态更新相关数据到链上而不是全部的数据,且这些数据会产生有用的东西?
最大程度提高提前确认的安全性——很多 rollup 都会为了更快的用户体验 (UX) 提供“提前确认 (pre-confirmation)”,这里排序者 (sequencer) 会马上承诺某笔交易会被打包到下一个batch里,而如果此承诺没有被兑现,该排序者将损失其保证金。但这个方案的经济安全性是有限的,因为排序者可以同时对非常多的人作出非常多的承诺。这个机制可以改善吗?
提高缺席排序者的回应速度——如果一个 rollup 的排序者突然离线了,在最短的时间内以最低的成本从这种情况恢复过来是很重要的,方法不是快速且低成本地大规模退出到另一个 rollup,就是换一个排序者。
高效 ZK-VM——生成一个 ZK-SNARK 证明,证明通用的 EVM 代码 (或一些现有的智能合约可以编译成的不同 VM) 已被正确执行和有一个给定结果的。
结论
Rollup 是一个强大、新颖的二层扩容范式,并有望成为以太坊在中短期未来 (也可能是长期) 扩容的基石。以太坊社区已经表现出对 rollup 的强烈兴趣,因为不像之前在二层扩容的尝试,它们可以支持通用的EVM代码,使得现有的应用可以轻易迁移。Rollup 有一个重要的妥协:交易处理不是完全在链下进行,而是每笔交易留下一小部分数据在链上。
Rollup 有很多种,在设计空间上有很多选择:可以是使用欺诈证明的 optimistic rollup,也可以是使用有效性证明 (即 ZK-SNARKs) 的 ZK rollup。排序者 (可以发布打包好的 batch 到链上的用户) 可以是中心化的行动者、自由放任者、或两者间的很多可能性。Rollup 还是早期的技术,其开发在不断快速地进行中,但它们是可行的,且其中有些 (比较有名的是路印、ZKSync、和DeversiFi) 已经运行数月了。期待今年 rollup 会有更多令人振奋的成果。
来源 | vitalik.ca
作者 | Vitalik Buterin
原文链接:
https://vitalik.ca/general/2021/01/05/rollup.html