摘要: 将数据存储在主链并进行共识,使得任何人可以在本地复现 Rollup 中的所有操作
译者注:
原文中 Rollup 同时以单复数形式出现多次,在译文中统一确定为首字母大写的 Rollup。
Rollup 在当前的以太坊社区已经十分著名。在可预见的未来,Rollup 是以太坊实现扩容的关键解决方案 。但 Rollup 到底是什么?你能从这项技术身上得到什么,又该如何使用它?这篇文章将尝试回答一些关键问题。
想象一下,Alice 向 Bob 提供了网络连接服务。作为交换,Bob 为上网产生的流量支付 0.001 美元/MB 的费用给 Alice。Bob 不需要在一层主链支付每笔费用,双方使用如下二层方案。
首先,Bob 将 1 美元(稳定币,或是等值的 ETH)存入一个智能合约中。为了向 Alice 支付第一笔款项,Bob签署了一张 "票据"(一条链外消息),“票据”上写着 “0.001 美元”,并将其发送给Alice。为了支付第二笔款项,Bob 签署另一张写着 “$0.002” 的票据,并将其发送给 Alice。以此类推,每次付款都重复这个过程(译者注:状态通道参与方只需保留一个最新的状态变更,因此新的票据签署后,前一张票据作废)。当 Alice 和 Bob 完成交易后,Alice 可以将价值最高的票据包裹上自己的签名后,发布到主链上。智能合约会验证 Alice 和 Bob 的签名,验证通过后,将 Bob 的票据上标注的金额支付给 Alice,剩下的金额(译者注:1 美元减去前者)返还给 Bob。如果 Alice (出于恶意或技术故障)不愿意关闭通道,Bob可以发起一个提现挑战期(例如7天)——如果 Alice 在这段时间内无法提供 Bob 支付的票据,那么 Bob 就可以拿回之前存在智能合约里的所有钱。
状态通道技术很强大:广义的状态通道可以支持双向支付、实现智能合约(例如 Alice 和 Bob 在通道中签订金融合约),并具有可组合性(如果 Alice 和 Bob 之间有一个开放的通道,Bob 和 Charlie 之间也有一个开放的通道,那么 Alice 就可以和 Charlie 进行免信任的交互)。但是通道的作用是有限制的:不能向还没有加入通道的用户在链下发送资金;不能用于没有明确逻辑所有者的对象(比如 Uniswap智能合约)。此外,如果使用通道处理的事务比小额支付场景更复杂,需要锁定大量的资金在通道中。
X
的叶子节点处,如果资产 ID 为X
的资产在这一批次中发生了交易,则叶子节点上存有对应交易,否则该叶子节点为零。操作者将这棵树的 Merkle 根发布到主链上。操作者还需要将每个索引X
的 Merkle 分支发送给该资产的当前所有者。如果需要将资产从 Plasma 链提取至主链上,用户需要给主链的智能合约发送该资产最近一次交易对应的 Merkle 分支。智能合约随即开始了一个挑战期(例如7天),在此期间,任何人都可以尝试使用其他 Merkle 分支来证明:(i)用户在提取资产时并不拥有该资产,或者(ii)用户在某个时间点将资产发送给了其他人,从而使退出申请无效。如果在 7 天内没有人证明退出是欺诈性的,用户便可以成功取回资产。Plasma 提供了比状态通道更强的功能:你可以将资产发送给从未加入二层的用户,锁定的资金也低得多。但这是有代价的:状态通道在 “正常运行” 时不需要将任何数据存入主链,但 Plasma 要求每条链每隔一段时间在主链发布一次哈希值。此外,Plasma 链中的交易没有即时性,即必须等待一批交易(也可称为 Plasma 区块)的证据(即那个 Merkle 根值)发到主链上。
此外,Plasma 和状态通道都有一个重要缺陷:其安全模型所对应的博弈论依赖于这样的想法:两个系统所控制的资产在逻辑层面都要有 "所有者"。只要资产所有者在乎自己的资产,那么当涉及该资产的状态变更 “无效” 时,资产所有者就会想办法出示变更 “无效” 的证明。这对一些应用来说无关紧要,但对不少其他应用来说这是个问题(例如 Uniswap)(译者注:对于 Uniswap 这样的 DEX 交易应用来说,其智能合约不属于任何人,与上述安全假设依赖的想法矛盾)。即使系统中一个对象的状态可以在未经系统所有者同意的情况下被改变(例如在基于账户的系统中,可以在未经所有者同意的情况下 增加其余额),也不能很好地与 Plasma 兼容。这意味着,在现实中部署 plasma 或状态通道时,都需要推演 “特定应用” 的潜在逻辑设计定制化方案,不太可能做出一个能完整模拟以太坊运行环境(即 “EVM”)的 plasma 或状态通道系统。接下来让我们看看 rollup 是如何解决这个问题的。
任何人都可以在主链上对该智能合约发起一个批处理事务(transaction),这个批处理是对一批 Rollup 内部事务的高度压缩,还包括旧的状态根和新的状态根(在旧状态根基础上执行批处理交易之后生成的新状态根)。主链合约会检验旧的状态根与新的状态根是否匹配(译者注:即新的状态根是否可以由这一批交易集触发状态转换生成)。如果检验通过,主链上的旧状态根会更新为新状态根。
为了支持存款(译者注:将资产从主链的其他地方存入 Rollup 合约)和取款(译者注:解除 Rollup 合约对自己资产的控制,使之返回到链上其他地方),批处理中的事务的输入或输出可以是 Rollup “外部”(译者注:即主链其他地方)的状态。如果批处理中有交易的输入来自 Rollup 之外,那么这个批处理操作会将主链其他地方的资产转移至 Rollup 合约中。如果批处理中有交易的输出来自 Rollup 之外,那么这个批处理会触发智能合约中的取款操作,将资产从 Rollup 取回主链。
整个过程就这么简单!不过还有一个细节。如何知道批处理执行完成之后的状态根是正确的? 如果有人可以提交一个伪造的状态根,而不产生任何后果,他们就可以把所有的资产转移给自己。这个问题很关键,因为这个问题有两种截然不同的解决办法,从而形成了两种类型的 Rollup。
Rollup 的两种类型包括:
这两种 Rollup 之间的设计权衡比较复杂
性质 | Optimistic Rollup | ZK Rollup |
---|---|---|
每个批处理在主链上的固定 gas 开销 | 约 40,000(开销相对轻量,主要操作是改变状态根的值) | 约 500,000(对于 ZK-SNARK 的验证开销相对较大) |
提现周期 | 约 1 周 (需要留出时间,看是否有人提出欺诈证明,从而取消无效提现申请) | 非常快(在提交提现申请后的下个批处理即可完成) |
技术复杂度 | 低 | 高 (ZK-SNARKs 技术较新,在数学层面相对更复杂) |
实现通用性的难度 | 相对更容易(很快就可以将实现通用性 EVM 的 Rollup 部署在主网中) | 相对更难(使用 ZK-SNARK 证明具有通用性的 EVM 执行操作比证明简单的计算操作难得多,当然(例如 Cairo)等工作正在努力简化该过程) |
Rollup 中每笔事务的成本 | 相对更高 | 相对更低(如果事务数据中的某些部分只用来验证该事务的有效性,而不涉及状态变更,这部分数据就可以不存储在主链上,而在 Optimisitc Rollup 中需要存储所有数据,用于后续欺诈证明的生成和校验) |
链下计算的开销 | 相对更低(虽然需要更多的全节点进行重计算) | 相对更高 (生成 ZK-SNARK 证明,特别是生成通用计算的证明开销可能很大,比直接计算要大好几千倍) |
总的来说我自己的观点是,短期内 Optimisitc Rollup 很可能在实现具有通用性的 EVM 中胜出,ZK Rollup 很可能在简单的支付、转账和其他特定应用中胜出。但从中长期来看,随着 ZK-SNARK 技术的改进,ZK Rollup 将在所有应用场景中胜出。
一个断言某个批处理无效的欺诈证明需要包括上图中以绿色标识的数据:该批处理本身(可与存储在链上的哈希值进行核对)以及证明该批处理读取或修改了特定账户的默克尔树路径。黄色的节点可以通过绿色的节点重建,所以无需包含在证明中。这些数据足以执行批处理并计算新的状态根(请注意,这与无状态客户端验证单个区块的方式完全相同)。如果计算出的新状态根和批处理中提供的新状态根不一样,那么就证明了该批处理是欺诈的。
可以确保的是,如果一个批处理中存在错误,而在此之前的所有批处理都是正确的,那么就可以创建一个欺诈证明,证明该批处理的构造是错误的。注意如果在 Rollup 中有多个无效的批处理,那么最好尽量证明最早的那个批处理无效。当然可以确保的是,如果一个批处理是正确的,那么永远不可能创建一个欺诈证明,证明该批处理是无效的。
一笔最简单的以太坊转账(发送 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 |
总计 | ~112 | ~12 |
这其中的部分原因是 Rollup 可以采用更简单的高级编码技巧,而目前以太坊的 RLP 在每个值的长度上浪费了1个字节。同时 Rollup 还运用了一些非常聪明的压缩技巧。
ZK Rollup 有一个特殊的重要压缩技巧:如果交易的一部分只用于验证,与计算状态更新无关,那么这部分数据可以不存储在主链上。这在 Optimisitc Rollup 中是做不到的,因为该数据仍然需要存储在链上,以备后续欺诈证明校验的不时之需,而在ZK Rollup 中,证明某批处理数据正确性的 SNARK 证明,已经证明了相关方提供了所有验证所需的数据。一个重要的例子是实现具有隐私保护性质的 Rollup:在 Optimisitc Rollup 中实现隐私保护,每笔交易中用于保护隐私的约 500 字节的 ZK-SNARK 需要上链,而在 ZK Rollup 中实现隐私保护,覆盖整个批处理的 ZK-SNARK 已经可以证明 "内部 "的 ZK-SNARK 是有效的。(译者注:由于 SNARK 可以嵌套,故在 ZK Rollup 中实现隐私保护,只需将最终生成的最外层的 SNARK 提交上链即可,在验证外层 SNARK 时,内层的 SNARK 的有效性同时可以得到验证。)
这些压缩技巧是 Rollup 实现扩容的关键,如果没有这些技巧,Rollup 或许只能在主链的扩容基础上实现大约 10 倍的扩容(尽管在一些特定的大计算量的应用中,简单的 Rollup 实现的扩容已经很强大),但在使用了压缩技巧之后,几乎所有应用的扩容系数都可以超过 100 倍。
对于哪些人可以在 Optimistic Rollup 或 ZK Rollup 中提交批处理这个问题,已经存在许多流派。一般来说,大家都认为提交批处理的用户必须质押一大笔押金,如果某用户曾经提交过一个具有欺诈性的批处理(例如提交一个无效的状态根),那么这笔押金的一部分将被燃烧销毁,另一部分奖励给提交欺诈证明的用户。但除此之外,还存在许多可能:
(译者注,可以将批处理发布到主链上的用户称为 sequencer(排序者),该术语得名原因是该角色需要对批处理中的交易进行排序)
目前正在开发的一些 Rollup 采用的是 “分割-批处理”("split batch")模式,即提交一批二层交易批处理的行为和提交一个状态根的行为是分开进行的。这其中有一些关键的优势。
你可以允许许多排序者并行发布批次,以提高抗审查能力,减轻对于某些批处理会因为其他一些批处理提前打包而无效的担心。
如果一个状态根存在欺诈,无需回滚整个批处理,可以只回滚状态根,并等待有人为同一批处理提供新的状态根。这样可以更好地确保交易发送者的交易不会被还回滚。
总的来说,这是一个相当复杂的技术组合,还在涉及效率,简单性,抗审查性和其他目标的复杂权衡中找到平衡。现在说这哪种组合最有效还为时过早,时间会证明一切。
在现有的以太坊主链上,每个区块的 Gas 上线是 1250 万,而交易的每个字节存储在链上花费 16 Gas。这意味着,如果一个区块中只包含一个批处理(这里假设使用 ZK Rollup,校验证明花费 50 万 Gas),那么这个批处理可以包含 1200 万 / 16 = 75 万字节的数据。而如上文所述,Rollup 中的每一笔 ETH 转账只需要 12 字节的存储空间,这意味着每个批处理中可以包含 62500 笔交易。目前以太坊主链的区块间隔是 13 秒,也就是说实现的 TPS 约为 4807(相比之下,以太坊主链上实现 ETH 转账的 TPS 约为 1250000 / 21000 / 13 = 45)。
下表中包含了其他一些应用场景的扩容效率。
应用场景 | Rollup 内单笔对应操作需上链的字节数 | 以太坊主链对应操作的 Gas 消耗 | 最大扩容倍数 |
---|---|---|---|
ETH 转账 | 12 | 21,000 | 105x |
ERC20 转账 | 16(多出的 4 个字节用于表示 token) | ~50,000 | 187x |
Uniswap 交易 | ~14(发送者 4 个字节 + 接收者 4 个字节 + 交易金额 3 个字节 + 最大价格 1 个字节 + 1 个字节杂项) | ~100,000 | 428x |
具有隐私保护性的提现操作(Optimisic Rollup) | 296(根索引 4 个字节 + ifier 4 个字节 + 接收者 4 个字节 + ZK-SNARK 证明 256 个字节) | ~380,000 | 77x |
具有隐私保护性的提现操作(ZK Rollup) | 40(根索引 4 个字节+ ifier 32 个字节 + 接收者 4 个字节) | ~380,000 | 570x |
最大扩容倍数计算方法:以太坊主链对应操作的 Gas 消耗 / (Rollup 中对应操作需上链的字节数 * 16) * 1200万 / 1250 万需要说明的是,出于某些原因,这些数字其实是过于乐观的。最重要的原因是,一个区块中几乎不可能只包含一个批处理,因为到时会有多个不同的 Rollup 系统。第二个原因是,存款和提现操作始终将会存在。第三个原因是,短期内Rollup 的使用量可能较低,因此固定成本的收费模式会占据主导。不过即使考虑了这些因素,超过 100 倍的扩容应该不难实现。
那如果我们想要实现 1000-4000 TPS(取决于具体的应用场景)呢?这就需要 eth2 数据分片了。在这个提案中,每 12 秒开辟一个 16MB 的存储空间,这个存储空间可以被任何数据填满,系统将确保对这些数据的可用性达成共识。这个数据空间可以被 Rollup 使用。这个约 1398kB/秒的数据吞吐量比当前以太坊主链的约 60 kB/秒提高了 23 倍,从长远来看,数据容量有望进一步增长。因此,使用 eth2 数据分片实现的 Rollup 的 TPS 可以高达 10万,在未来甚至会更大。
虽然现在 Rollup 的基本概念已经被人们所熟知,我们也很确定 Rollup 从本质上说上是可行的、安全的,而且已经有多个 Rollup 在以太坊主网部署,但 Rollup 在设计层面仍有许多地方没有被很好地探索,如果要将以太坊生态系统的大部分都完全引入 Rollup 从而利用其扩容性,这方面仍存在不少挑战。一些关键的挑战包括:
Rollup 是一种新的强大的二层扩容范式,预计将成为以太坊未来短期和中期(也可能是长期)实现扩容的基石。以太坊社区对于 Rollup 非常兴奋,因为与之前的二层扩容尝试不同,Rollup 可以支持通用的 EVM 代码,允许现有的应用程序轻松迁移过来。Rollup 通过做出一个关键的妥协来实现这一目标:不试图完全搬到链下,而是将每笔交易的少量数据保留在链上。(译者注:即上文所说的没有数据可得性问题)
Rollup 有很多种,设计上也有很多选择:使用欺诈证明的 Optimisitc Rollup,使用有效性证明的ZK Rollup。排序者可以是一个中心化的角色,也可以是一个去中心化的自由角色,或者是介于两者之间的许多其他选择。Rollup 仍然是一项早期阶段的技术,开发正在快速地继续,但它们是有效的,一些(特别是 Loopring、ZKSync 和DeversiFi)已经运行了几个月。期待在未来的几年里,Rollup 领域会有更多令人兴奋的成果出现。
(完)
(文内有许多超链接,可点击左下 ”阅读原文“ 从 EthFans 网站上获取)
原文链接:
https://vitalik.ca/general/2021/01/05/rollup.html
https://twitter.com/VitalikButerin/status/1346267282771623936
作者:Fulvia
翻译&校对: Shengchao & 阿剑
作者:以太坊爱好者;来自链得得内容开放平台“得得号”,本文仅代表作者观点,不代表链得得官方立场凡“得得号”文章,原创性和内容的真实性由投稿人保证,如果稿件因抄袭、作假等行为导致的法律后果,由投稿人本人负责得得号平台发布文章,如有侵权、违规及其他不当言论内容,请广大读者监督,一经证实,平台会立即下线。如遇文章内容问题,请发送至邮箱:linggeqi@chaindd.com