Vitalik:Rollup 不完全指南(精选)

Vitalik:Rollup 不完全指南(精选)

Created
Jan 7, 2021
作者
Vitalik
译者
Ashu Chan

🗞️ 字数:5349 | 🕥 阅读时间:18m 39s

💡

Rollup 作为二层扩容方案,有望在中短期成为以太坊核心的扩容方案。但 Rollup 依然存在不少问题和挑战(诸如用户体验、跨 Rollup 交互、安全性等问题),我们一起来看下 Vitalik 深入浅出地剖析 Rollup 现状和未来吧。

术语说明

NameDescription
Batch
批处理交易,指将 Layer2 交易批量打包并提交到 Layer1 的 Rollup 合约。
Sequencer
排序者,指在 Layer2 上打包排序交易的角色,类似 Layer1 的矿工。
State root
状态根,指 Layer2 上所有状态(账户余额、合约代码等)通过 Merkle Tree 生成的哈希值。

背景:什么是 Layer 1 和 Layer 2 扩容?

目前主要有两种区块链扩容方式。

首先,你可以直接提高区块链交易吞吐量,但这类技术主要挑战为「当区块容量越大时,区块链将更难以验证,而且很可能逐渐变得更中心化」。为了避免这样的风险,开发者可以提高客户端软件的效率(译者注:比如 Turbo Geth),或者使用 Sharding 技术让构建和验证工作分散到在许多节点上,目前 Ethereum 准备借助 ETH2 升级引入 Sharding 技术。

其次,你也可以改变使用区块链的方式。用户不必将所有交易放在区块链上,而是可以通过 Layer2 协议在链下执行大部分交易。比如链上通过一个智能合约执行两个任务:处理存款和取款,以及验证链下交易有效性。有许多方式可以验证链下交易有效性 ,但它们都有一个共同的特点,那就是链上验证证明要比链下执行计算便宜许多。

State channels vs plasma vs rollups

译者注:省略 State channels 和 Plasma 科普内容,主要讲述 Rollup 部分。

Rollup

Plasma 和 State Channels 是「完全」的 Layer2 方案,因为它们试图将数据和计算转移至链下。然而,考虑「数据可用性的博弈问题」,这意味着不可能安全地满足所有应用场景。Plasma 和 State Channels 通过依赖所属权的 owner(译者注:因为提交欺诈性证明需要证明资产所属权,这也是为什么 Plasma 采用 UTXO 方案,所以无法解决像 Uniswap 资产所属权场景。感谢 Chih Cheng Liang 指点)来解决该问题,但这使它们无法完全通用化。

另一方面,Rollups 是一种「混合」的 Layer2 方案。Rollups 将计算(以及状态存储)转移至链下,但同时将每笔交易的部分数据保留在链上。

为了提高效率,他们使用了不少 fancy 的压缩技巧,尽可能地使用「计算」代替「数据」。其结果是系统的扩容仍然受限于底层区块链的数据带宽,但效率是可观的:Ethereum ERC20 代币转账成本约为 45000 gas,而 Rollup 中的 ERC20 代币转账仅使用 16 bytes 的链上空间,成本低于 300 gas。

事实上,数据上链是关键(注意:将数据放在 IPFS 上是行不通的,因为 IPFS 不提供任何给定数据是否可用的共识,所以数据必须放到区块链上)。将数据放在链上并获得共识,如果任何人愿意,他们可以在本地处理 rollup 中的所有操作,从而允许他们监测欺诈交易,请求提款,或亲自生成 transaction batches。因为没有数据可用性问题,所以意味着恶意或离线运营者所造成的损失会更少(比如他们不能造成 1 周的延迟),从而为谁有权发布 batches 打开了更大的设计空间,并简化 rollups 系统。最重要的是,没有数据可用性问题也意味着不再需要将资产映射到 owners。

这是 Ethereum 社区对 rollups 比以往的 Layer2 扩容方案更兴奋的关键原因:Rollups 是完全通用的,我们甚至可以在 rollup 内运行一个 EVM,使得现有的 Ethereum 应用不必编写过多新的代码就可以迁移到 rollups 上。

那么 Rollup 到底是如何工作的呢?

链上会有一个智能合约维护着 state root:rollup 状态的 Merkle root(即 rollup 内部的账户余额、合约代码等信息的 Merkle 化)。

image

任何人都可以发布一笔 batch 交易,这是一个高度压缩的交易集合,包含旧的 state root 和新的 state root。合约会检查 batch 中的旧的 state root 是否匹配当前的 state root,如果匹配,则将 state root 更新到新的 state root。

image

为了支持存款和提款,我们增加了交易的能力,其输入或输出是 「外部」的 rollup 状态。如果一个 batch 来自外部的输入,那么提交该 batch 的交易也需要将这些资产转移到 rollup 合约中。如果一个 batch 有对外的输出,那么在处理该 batch 时,智能合约将会执行「提现」操作。

这一切就这么简单! 除了一个主要的细节:如何知道 batch 中的 post-state roots 是正确的呢? 如果有人可以用任意 post-state root 提交一个 batch,但没有任何惩罚,他们就可以直接将 rollup 内的全部资产转给自己。这个问题导致两种截然不同的解决思路,从而衍生出两种「口味」的 rollup 方案。

Optimistic rollups VS ZK rollups

以下是这两种「口味」的 rollups 方案描述:

  1. Optimistic rollups,采用欺诈性证明:rollup 合约会跟踪历史的 state roots 和每一个 batch 的哈希值。如果有人发现某个 batch 的 post-state root 不正确,那么他们可以向合约提交证明,证明该 batch 计算错误。合约验证该证明有效后,会对该 batch 和之后的所有 batch 进行回滚。
  2. ZK rollups,采用有效性证明:每一个 batch 都包含一个称为 ZK-SNARK 的密码学证明(例如采用 PLONK 协议),它可以证明 post-state root 是执行该 batch 的正确结果。无论计算量有多大,合约都可以迅速地在链上验证证明。

但两种「口味」的 rollup 之间有着复杂的权衡:

方案权衡

PropertyOptimistic rollupsZK rollups
提款周期
~1 week(提款需要留出时间提交欺诈性证明,以便取消有问题的提款)
Very Fast(等待下一次 batch 提交即可。译者注:可以理解为下一个区块就能完成该操作)
技术复杂度
Low
High(ZK-SNARKs 是一种非常新颖的技术,而且具有一定数学复杂度)
通用性
Easier(通用的 EVM rollups 即将准备上主网了)
Harder(使用 ZK-SNARK 证明「通用的 EVM 执行」要比「简单的计算」难得多,尽管目前有方案 (例如 Cairo) 努力改善这一点)
每笔 batch 固定成本
~40,000 (轻量级的交易:主要更新 state root)
~500,000 (验证 ZK-SNARK 所需计算量较大)
每笔交易上链成本
Higher
Lower(如果交易中的数据仅用于验证而更新状态,那么该数据可以省略。而在 Optimistic rollup 中,由于需要通过欺诈性证明进行检查,则不得不提交这些数据)
链下计算成本
Lower(尽管需要许多全节点重新执行计算)
Higher(专门针对通用计算的 ZK-SNARK 证明会很昂贵,相比直接执行计算要贵数千倍)

总的来说,我自己的观点:

短期内,Optimitic roolups 很可能在通用的 EVM 计算中胜出,而 ZK rollups 则可能在简单的支付、交易和其他特定应用场景中胜出,但最终从中长期来看,随着 ZK-SNARK 技术的改进,ZK rollups 将在所有场景中胜出。

欺诈性证明剖析

Optimitic rollup 的安全性主要取决于:如果有人将一个无效 batch 发布到 rollup 合约中,那么保持跟踪链上信息并发现欺诈的任何人都可以发布欺诈性证明,向合约证明该 batch 无效并回滚。

image

如图所示,如果声称某 batch 无效的欺诈性证明将会包含这些绿色数据:这是通过 batch 本身(对照存储在链上的哈希值核对)和 Merkle tree 的部分内容,从而证明该 batch 读取或修改特定账户。

而该树中的黄色节点可以从绿色的节点重建,所以不必提供。这些数据足以执行该 batch 并计算 post-state root(Note:类似 stateless clients 验证单个区块的方式)。如果计算出的 post-state root 和该 batch 中提供的 post-state root 不一样,那么说明该 batch 具有欺诈性。

如果一个 batch 存在错误,但之前所有的 batches 都是正确的,那么就可以创建一个欺诈性证明以表示该 batch 是错误的。

请注意对旧的 batches 声称无效的处理:如果存在多笔无效 batch 提交到 rollup 中,那么最好尽量证明最早无效的 batch。当然,如果一个 batch 是正确的,那么永远不可能创建一个欺诈性证明以表示其无效。

压缩是如何工作的?

一笔简单的 Ethereum 交易(比如发送 ETH )通常消耗约 110 bytes。然而,在 Rollup 上的发送 ETH 仅仅消耗约 12 bytes

字节消耗对比

ParameterEthereumRollup
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 (recovered from sig)
4
Total
~112
~12

有效压缩的部分原因是采用更简单高级编码,而目前 Ethereum 的 RLP 在每个值的长度上是浪费了 1 byte,同时还有一些巧妙的压缩技巧在运用:

  • Nonce:该参数的目的是为了防止「重放」。如果账户的当前 nonce 是 5,那么该账户的下一笔交易必须使用 nonce 5,但一旦交易被处理,那么该账户中的 nonce 就会被递增到 6,这样采用 nonce 5 的交易就不会被执行。在 rollup 中,我们可以完全省略 nonce,因为我们只是从 pre-state 中恢复 nonce。因为签名会采用最新的 nonce 进行检查,如果有人试图使用旧的 nonce 重放交易,那么签名将无法通过验证。
  • Gasprice:我们可以允许用户使用固定范围的 gasprices 进行支付,例如 2 的 16 次幂(译者注:主要为了节省字节)。或者,我们也可以在每笔 batch 中收取固定费用,甚至可以将 gas 支付完全移到 rollup 协议之外,让交易者通过特定渠道向 batch 创建者支付费用。
  • Gas:我们同样也可以将 gas 设置为 2 的多次幂。另外,我们也可以在 batch 层面设置 gas 限制。
  • To:我们可以使用「索引」来代替 20 byte 的地址(例如:一个地址是「树」中的第 4527 个地址,我们就可以用索引 4527 来表示它,同时我们也会在状态中添加一个子树来存储索引到地址的映射)
  • Value:我们可以用科学计数法存储 value。在大多数情况下,转账仅需 1~3 有效位。
  • Signature:我们可以使用 BLS 聚合签名,它允许许多签名聚合成一个约 32-96 字节的签名(取决于协议)。然后,这个签名可以一次性对整个消息集和发送者进行 batch 检查。表中的 ~0.5 表示一个区块中可验证的聚合签名的数量是有限制的,因为它需要在一次欺诈证明中可以验证签名。

ZK rollups 特有的一个重要压缩技巧:如果交易的一部分仅用于验证,并与计算状态更新无关,那么这部分可以省略。这在 Optmistic rollup 中是做不到的,因为该数据仍然需要包含在链上,以防将来欺诈性证明检查所需,而在 ZK rollup 中,证明数据正确性的 SNARK 已经提供了任何验证所需的数据。

一个重要的例子是隐私保护 rollups:在 Optimistic rollup 中,每笔交易中 ~500 byte 用于隐私的 ZK-SNARK 需要上链,而在 ZK rollup 中,覆盖整个 batch 的 ZK-SNARK 已经无疑使「内部」的 ZK-SNARK 是有效的。

这些压缩技巧是 rollup 扩容的关键,如果没有这些技巧,rollup 或许只能在基础链的扩容上有大约 10 倍的提升(在一些特定的计算量大的应用中,简单的 rollup 也已经很强大),但有了这些压缩技巧,几乎所有应用的扩容系数都可以超过 100 倍。

谁可以提交 batch?

关于哪些人可以在 Optimistic 或 ZK rollup 中提交 batch 的问题存在许多流派。一般来说,大家都认为提交 batch 的用户必须交纳一大笔押金,如果该用户曾经提交过一个具有欺诈性的 batch(例如采用一个无效的 state root),那么这笔押金的一部分将被烧掉,另一部分作为奖励给提交欺诈性证明的用户。但除此之外,还存在许多可能:

  • Total anarchy:任何人都可以在任何时候提交 batch。这是最简单的方法,但它有一些严重的缺点,比如存在这样的问题:多个参与者同时生成并试图提交 batch,而其中仅有一个 batch 可以成功被收录。这将导致大量的浪费,比如没有意义的生成 batch 证明或者提交 batch 到链上。
  • 中心化的 Sequencer:通过 Sequencer 这样的角色提交 batch(除了提现操作:首先由用户自己提交提现请求,如果 Sequencer 在下一个 batch 中没有处理该提现交易,那么用户可以亲自提交一个 batch 处理提现)。这是最「高效」的,但它依赖于一个中心化的角色。
  • Sequencer 拍卖:通过拍卖(比如每天)来决定谁有权利成为第二天的 Sequencer。这种方案的优点是可以筹集资金,而这些资金可以通过 rollup 的 DAO 来分配(参考:MEV 拍卖)。
  • 从 PoS 集合中随机选择:任何人都可以将 ETH(或者 rollup 协议的代币)存入 rollup 合约中,每一个 batch 的 sequencer 都会从其中一个存款人中随机选中,被选中的概率与存款金额成正比。这种方案的主要缺点是大量资产被锁定,从而导致资金效率低,。
  • DPoS 投票:Sequencers 通过拍卖选中,但如果他们表现不佳,那么代币持有者可以投票将其踢出,并举行新的拍卖来替代他们。

Split batching and state root provision

目前正在开发的一些 rollup 方案采用的是 “split batch” 模式,即提交 Layer2 batch 的动作和提交一个 state root 的动作是分开执行。这会有一些关键优势:

  1. 你可以允许许多 sequencers 并行发布 batch,以提高抗审查能力,而不用担心一些 batch 会因为其他 batch 已经被打包而无效。
  2. 如果一个 state root 存在欺诈,你不需要回滚所有 batch,你可以仅恢复该 state root 即可,并等待有人为该 batch 提供新的 state root。这样可以更好的保障交易发送者的交易不会被回滚。

总的来说,这是一个相当复杂的技术组合,它们试图在涉及效率、简单性、抗审查和其他目标的复杂权衡中获得平衡。但现在谈哪种组合最有效还为时过早,而时间会证明一切。

Rollups 将会带来多大的扩容?

目前 Ethereum 的 gas limit 是 1250 万,交易中每个字节的数据需要消耗 16 gas。那么如果一个区块仅包含一个 batch(我们假设使用 ZK rollup,将会消耗 50 万 gas 用于验证证明),那么该 batch 会有(1200 万 / 16)= 75 万 bytes。如上图所示,每一位用户转账 ETH 仅消耗 12 bytes,那么也就是说,该 batch 最多可以包含 62500 笔交易。

在平均区块时间为 13 秒的情况下,这相当于达到约 4807 TPS(对比 Ethereum 目前 ETH 转账的 1250万 / 21000 / 13 约为 45 TPS)。

部分用例扩容提升规模

ApplicationBytes in rollupGas cost on layer 1Max scalability gain
ETH transfer
12
21,000
105x
ERC20 transfer
16 (4 more bytes to specify which token)
~50,000
187x
Uniswap trade
~14 (4 bytes sender + 4 bytes recipient + 3 bytes value + 1 byte max price + 1 byte misc)
~100,000
428x
Privacy-preserving withdrawal (Optimistic rollup)
296 (4 bytes index of root + 32 bytes nullifier + 4 bytes recipient + 256 bytes ZK-SNARK proof)
77x
Privacy-preserving withdrawal (ZK rollup)
40 (4 bytes index of root + 32 bytes nullifier + 4 bytes recipient)
570x

那么扩容上限可以这么计算:

💡

现在值得注意的是这些数字还是过于乐观,原因有几个:

首先,最重要的是一个区块几乎永远不会仅包含一个 batch,因为将可能会存在多个 rollup 方案同时运作。第二,存款和提款将持续存在。第三,短期内使用量会很低,所以固定成本成为主要消耗。但即使考虑到这些因素,预计扩容规模超过 100 倍。

现在,如果我们想要超过 ~1000 - 4000 TPS,该怎么办呢?这就是 ETH 数据分片的意义所在,sharding 建议每 12 秒开辟一个 16MB 的空间,这个空间可以被任何数据填满,系统保证对这些数据的可用性达成共识,而这些数据空间可以被 rollup 使用。

这个约 1398k bytes/s 的数据量比当前 Ethereum 60 kB/s 提高了 23 倍,从长远来看,数据容量有望进一步增长。因此,使用 ETH2 分片数据的 rollup 可以处理高达约 100k TPS,未来甚至会更多。

Rollup 还有哪些尚未解决的挑战?

虽然现在 Rollup 的基本概念已经被大家所熟知,我们也很确认它们从根本上是可行的、安全的,以及已有多个 rollup 方案被部署到主网上,但 rollup 的设计仍然存在许多地方没有被很好地探索,当将 Ethereum 生态系统的大部分内容完全迁移到 rollup 上以利用其扩容能力也存在不少挑战。比如一些关键的挑战:

  • User and ecosystem onboarding - 使用 rollups 的应用不多,用户对rollups 也不熟悉,目前很少有钱包开始整合 rollups,而商家和慈善机构还不接受它们用于支付。
  • Cross-rollup transactions - 有效地将资产和数据 (例如 oracle 输出) 从一个 rollup 转移到另一个 rollup 中,而不会产生经过 Layer1 的费用。
  • Auditing incentives - 如何最大限度地提高至少一个诚实节点会真正全面验证一个 Optimistic rollup 的概率,以便出错时他们会发布欺诈性证明?对于小规模的 rollup(几百个 TPS 以下)来说,这不是一个重要的问题,可以简单地借助利他主义,但对于更大规模的 rollup 来说,这需要更明确地推理这个问题。
  • Exploring the design space in between plasma and rollups - 是否存在一些方法可以将状态更新的相关的数据放在链上,而不是所有的数据。
  • Maximizing security of pre-confirmations - 许多 rollup 为了更快的用户体验,提供了一个「预确认」的概念,即 sequencer 立即给予一个承诺,交易将被包含在下一个 batch 中,如果他们食言,sequencer 的押金将被销毁。但这种方案的经济安全性是有限的,因为可能同时向许多用户做出承诺,这种机制能否获得改进?
  • Improving speed of response to absent sequencers - 如果一个 rollup 的 sequencer 突然下线,那么最快速和便宜地从这种情况中恢复过来将是非常有价值的,要么快速和普安一地大规模退出到另一个 rollup,要么更换 sequencer。
  • Efficient ZK-VM - 生成通用 EVM 代码的 ZK-SNARK 证明(或者将现有的智能合约编译适配到其他 VM)可以被正确执行,并且有一个明确结果。

结论

Rollup 是一种强大的 Layer2 扩容范式,预计将成为 Ethereum 短期和中期(或许长期)扩容的基石。我们已经看到了 Ethereum 社区的对此感到大大的兴奋,因为这与之前的 Layer2 扩容方案不同,它们可以支持通用的 EVM 代码,允许现有的智能合约轻松迁移。

这是通过一个关键的妥协来实现该目标:放弃将数据和计算完全放在链下,而是将每笔交易的少量数据留在链上。

Rollup 方案有很多种,在设计空间上会有很多选择:可以采用欺诈性证明的 Optimistic rollup,或者采用有效性证明的 ZK rollup(又名 ZK-SNARKs)。Sequencer(可以将交易 batch 发布到链上的用户)可以是一个中心化的角色,也可以是一个去中心化的角色,或者是介于两者之间的其他选择。

总的来说 Rollup 仍然是一项早期阶段的技术,一切仍在迅速发展,特别是 Loopring,ZKSync 和 DeversiFi 已经运作了几个月。

期待在未来的几年内,Rollup 领域会出现更多令人兴奋的工作成果。