原文标题:《 引介 | Rollup 不完全指南 》
原文来源:以太坊爱好者
译者注:原文中 Rollup 同时以单复数形式出现多次,在译文中统一确定为首字母大写的 Rollup。
Rollup 在当前的以太坊社区已经十分著名。在可预见的未来,Rollup 是以太坊实现扩容的关键解决方案 。但 Rollup 到底是什么?你能从这项技术身上得到什么,又该如何使用它?这篇文章将尝试回答一些关键问题。
实现区块链生态系统扩容有两种方式。第一种扩容的方式是让区块链本身拥有更高的事务处理容量 。比如让区块变得 “更大”,但 “大区块” 会让区块链的验证过程变得更为困难,而且可能会使节点更加中心化。为了避免这样的风险,开发者可以提高客户端软件的效率。更加具有可持续性的扩容方式是,使用分片等技术,让构建和验证区块链的工作分摊到许多不同的节点上—— “ eth4 ” 就在尝试使用这种方式升级以太坊。
第二种扩容的方式是改变使用区块链的方法 。用户不需要直接把所有的活动都直接放在区块链主链上,而是在主链外的 “二层” 协议中执行大部分活动,并生成一个证明,证明链外发生的这一切活动都遵循规则。主链上部署一个智能合约,它只有两个任务:处理存取款,以及对上述证明进行验证。有多种方法实现证明和验证,但它们都有一个共同的特性,那就是在链上验证证明比在链下做原始计算的开销要小得多。
二层扩容主要有三种方案:状态通道,Plasma 和 rollup。三种方案代表了三种不同的范式,每种方案有自己的优缺点。所有的二层扩容大致都属于这三类(对于一些折衷的方案如何分类存在争议,例如 “ validium ”)(编者注:中文译本)。
状态通道如何工作?
另请参阅 https://www.jeffcoleman.ca/state-channels ,statechannels.org
想象一下,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 智能合约)。此外,如果使用通道处理的事务比小额支付场景更复杂,需要锁定大量的资金在通道中。
Plasma 如何工作
另请参阅 Plasma原始白皮书,Plasma Cash
要将资产从主链存入 Plasma 链,用户需要在主链将资产发送至管理 Plasma 链的智能合约。Plasma 链会给该资产分配一个新的唯一 ID(例如 537)。每条 Plasma 链都有一个操作者(这可能是一个中心化的角色,或者由多签控制,也可以是更复杂的东西,例如一条 PoS 链或 DPoS 链)。每隔一段时间(可以是 15 秒,也可以是一小时,或者介于两者之间的任何时长),操作者就会生成一个 “批处理”(batch),包含这段时间内所收到的所有 Plasma 链的交易。操作者生成一棵 Merkle 树,在索引为 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 是如何解决这个问题的。
Rollup
另请参阅:EthHub 关于 optimistic rollup 的介绍,EthHub 关于 ZK rollup 的介绍
Plasma 和状态通道方案都是 “完全的” layer 2 方案,因为它们将数据和计算都转移到链下(即自己的二层系统中)。然而,数据可得性的基本博弈论原理意味着这样的系统不可能安全地实现所有应用。Plasma 和状态通道通过明确资产对象和所有者之间的关系来解决这个问题,但这使它们无法完全通用。Rollup 则与前两者不同,是一种具有 “混合性质” 的二层方案。 Rollup 将计算(和完整的状态存储)转移到链下,但在链上保存了每笔交易的部分数据信息 。为了提高效率,Rollup 使用了一系列花哨的压缩技巧,并尽可能地 用计算替代数据 。其结果是,这个系统的可扩展性仍然受限于底层区块链的数据带宽,但在此基础上实现的扩容倍数非常可观:在以太坊主链执行一笔 ERC-20 代币的转账大约消耗 45000 gas,但在 Rollup 中,每笔交易仅需要在主链上存储 16 字节数据,消耗的 gas 小于 300。
数据存储在主链是 Rollup 的关键因素(请注意:这同将数据存储在 “IPFS” 上不同,因为 IPFS 不会对存储的数据进行共识,Rollup 的数据则 必须 存储在区块链上)。将数据存储在主链并进行共识,使得任何人可以在本地处理 Rollup 中的所有操作,包括欺诈检测,发起提款,生成批处理等。因为不存在数据可得性问题,所以运营者如果作恶或者离线所造成的损失相对更少(比如他们无法造成长达 1 周的退出延迟),也在谁有权发布批处理这个问题上提供了更多的可能性,同时也使 Rollup 更易于理解。更为重要的是,不存在数据可得性问题意味着,资产无需和所有者有明确的逻辑映射关系。相比其他二层扩容方案,这是以太坊社区对 Rollup 感到更加激动的重要因素:Rollup 是具有通用性的,比如可以在 Rollup 中运行 EVM,从而使现有的以太坊应用可以在不写新代码的情况下迁移至 Rollup。
在主链上有一个智能合约,存有一个 状态根 —— 表征 Rollup 状态的 Merkle 根。(状态内容包括 Rollup 中的账户余额,合约代码等)
任何人都可以在主链上对该智能合约发起一个 批处理 事务(transaction),这个批处理是对一批 Rollup 内部事务的高度压缩,还包括旧的状态根和新的状态根(在旧状态根基础上执行批处理交易之后生成的新状态根)。主链合约会检验旧的状态根与新的状态根是否匹配(译者注:即新的状态根是否可以由这一批交易集触发状态转换生成)。如果检验通过,主链上的旧状态根会更新为新状态根。
为了支持存款(译者注:将资产从主链的其他地方存入 Rollup 合约)和取款(译者注:解除 Rollup 合约对自己资产的控制,使之返回到链上其他地方),批处理中的事务的输入或输出可以是 Rollup “外部”(译者注:即主链其他地方)的状态。如果批处理中有交易的输入来自 Rollup 之外,那么这个批处理操作会将主链其他地方的资产转移至 Rollup 合约中。如果批处理中有交易的输出来自 Rollup 之外,那么这个批处理会触发智能合约中的取款操作,将资产从 Rollup 取回主链。
整个过程就这么简单!不过还有一个细节。 如何知道批处理执行完成之后的状态根是正确的? 如果有人可以提交一个伪造的状态根,而不产生任何后果,他们就可以把所有的资产转移给自己。这个问题很关键,因为这个问题有两种截然不同的解决办法,从而形成了两种类型的 Rollup。
Optimistic rollups vs ZK rollups
Rollup 的两种类型包括:
这两种 Rollup 之间的设计权衡比较复杂
总的来说我自己的观点是,短期内 Optimisitc Rollup 很可能在实现具有通用性的 EVM 中胜出,ZK Rollup 很可能在简单的支付、转账和其他特定应用中胜出。但从中长期来看,随着 ZK-SNARK 技术的改进,ZK Rollup 将在所有应用场景中胜出。
剖析欺诈证明
Optimistic Rollup 的安全性取决于这样的想法:如果有人将一个无效的批处理发布到 Rollup 中,任何 同步了该链的人只要发现欺诈行为便可以向主链上的合约发布欺诈证明,证明该批处理是无效的,应该被回滚(译者注:不清楚作者这里的 “该链(the chain)” 到底是指主链,还是指 Rollup,虽然都是对的)。
一个断言某个批处理无效的欺诈证明需要包括上图中以绿色标识的数据:该批处理本身(可与存储在链上的哈希值进行核对)以及证明该批处理读取或修改了特定账户的默克尔树路径。黄色的节点可以通过绿色的节点重建,所以无需包含在证明中。这些数据足以执行批处理并计算新的状态根(请注意,这与无状态客户端验证单个区块的方式完全相同)。如果计算出的新状态根和批处理中提供的新状态根不一样,那么就证明了该批处理是欺诈的。
可以确保的是,如果一个批处理中存在错误,而在此之前的所有批处理都是正确的,那么就可以创建一个欺诈证明,证明该批处理的构造是错误的。注意如果在 Rollup 中有多个无效的批处理,那么最好尽量证明最早的那个批处理无效。当然可以确保的是,如果一个批处理是正确的,那么永远不可能创建一个欺诈证明,证明该批处理是无效的。
压缩是如何实现的?
一笔最简单的以太坊转账(发送 ETH)大约需要 110 字节,但是在 Rollup 中实现 ETH 转账只需要大约 12 字节:
参数(单位:字节数)以太坊主链Rollup 合约Nonce (流水号)~30Gasprice~80-0.5Gas30-0.5To (目标地址)214Value (转移价值)~9~3Signature (签名)~68(2 + 33 + 33)~0.5From (发起地址)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)。
下表中包含了其他一些应用场景的扩容效率。
最大扩容倍数计算方法:以太坊主链对应操作的 Gas 消耗 / (Rollup 中对应操作需上链的字节数 * 16) * 1200万 / 1250 万
需要说明的是,出于某些原因,这些数字其实是过于乐观的。最重要的原因是,一个区块中几乎不可能只包含一个批处理,因为到时会有多个不同的 Rollup 系统。第二个原因是,存款和提现操作始终将会存在。第三个原因是,短期内 Rollup 的使用量可能较低,因此固定成本的收费模式会占据主导。不过即使考虑了这些因素,超过 100 倍的扩容应该不难实现。
那如果我们想要实现 1000-4000 TPS(取决于具体的应用场景)呢?这就需要 eth4 数据分片了。在这个提案中,每 12 秒开辟一个 16MB 的存储空间,这个存储空间可以被任何数据填满,系统将确保对这些数据的可用性达成共识。这个数据空间可以被 Rollup 使用。这个约 1398kB/秒的数据吞吐量比当前以太坊主链的约 60 kB/秒提高了 23 倍,从长远来看,数据容量有望进一步增长。因此,使用 eth4 数据分片实现的 Rollup 的 TPS 可以高达 10万,在未来甚至会更大。
虽然现在 Rollup 的基本概念已经被人们所熟知,我们也很确定 Rollup 从本质上说上是可行的、安全的,而且已经有多个 Rollup 在以太坊主网部署,但 Rollup 在设计层面仍有许多地方没有被很好地探索,如果要将以太坊生态系统的大部分都完全引入 Rollup 从而利用其扩容性,这方面仍存在不少挑战。一些关键的挑战包括:
Rollup 是一种新的强大的二层扩容范式,预计将成为以太坊未来短期和中期(也可能是长期)实现扩容的基石。以太坊社区对于 Rollup 非常兴奋,因为与之前的二层扩容尝试不同,Rollup 可以支持通用的 EVM 代码,允许现有的应用程序轻松迁移过来。Rollup 通过做出一个关键的妥协来实现这一目标:不试图完全搬到链下,而是将每笔交易的少量数据保留在链上。(译者注:即上文所说的没有数据可得性问题)
Rollup 有很多种,设计上也有很多选择:使用欺诈证明的 Optimisitc Rollup,使用有效性证明的ZK Rollup。排序者可以是一个中心化的角色,也可以是一个去中心化的自由角色,或者是介于两者之间的许多其他选择。Rollup 仍然是一项早期阶段的技术,开发正在快速地继续,但它们是有效的,一些(特别是 Loopring、ZKSync 和 DeversiFi)已经运行了几个月。期待在未来的几年里,Rollup 领域会有更多令人兴奋的成果出现。
原文链接
欢迎加入律动 BlockBeats 官方社群:
Telegram 订阅群:https://t.me/theblockbeats
Telegram 交流群:https://t.me/BlockBeats_App
Twitter 官方账号:https://twitter.com/BlockBeatsAsia