

以太坊社区引入了EIP4844,一种新的blob-carrying transactions交易格式,以提供数据可用性,降低rollup的运营成本,并降低用户的交易费用。Scroll协议的ZKRollup合约提供了将rollup链数据嵌入到L1上的calldata,Danksharding将采用纠删码对数据进行编码,以确保数据有效性,并引入blob-carrying transaction类型交易,每个blob-carrying transaction类型交易都可以携带一个blob列表。
在过去的几年里,解决区块链的扩容难题一直是以太坊社区的重中之重,其目标是在不牺牲去中心化或安全性的情况下实现更高的可扩展性。经过大量的探索,以太坊社区一致决定采用以 rollup 为中心的方案来解决可扩展性问题,因此在以太坊路线图中始终优先考虑 rollup 的需求。
大多数 rollup 唯一的需求点是改进以太坊作为数据可用性层。EIP4844,也称为 Proto-Danksharding,是以太坊对这一需求的快速响应,当然改进的版本正在开发中。EIP4844 引入了一种新的交易格式,称为 blob-carrying transactions,它允许用户在交易中包含存储数据的二进制字段( 以下简称 blob ) ,保证这些数据在几周内是可用的。很快以太坊网络将经历一个名为坎昆升级( Cancun-Deneb)的硬分叉,其中就包括 EIP4844 等。
虽然区块链的叙事周期起起落落,围绕数据可用性的讨论一直在话题中心,然而,大家对数据可用性的理解仍然没有那么深入。所以在这篇文章中,我们将讨论什么是数据可用性层,以及为什么 rollup 需要使用数据可用性层。此外,我们还讨论了 EIP4844 以及它将如何提高以太坊作为数据可用性层的能力。最后,我们研究了如何在电路中打开 blob 承诺,并展示了一个简单的概念验证。
去中心化和无需许可的区块链为用户提供了许多保障,包括抗审查性、不可变性、活性,以及最重要的执行正确性。简单地说,状态转换是有效的,即智能合约的执行总是正确的。这一切都归功于去中心化网络中,每个节点都将检查区块的有效性。而 rollups 试图在更便宜的成本下提供相同的保障!
Rollup 的核心思路是将执行从 L1 转移到更便宜的环境中,同时采用一种机制简洁地(ZK) 或乐观地 (OP) 向 L1 rollup 合约证明这些执行是正确完成的,并且状态转换是有效的。需要注意的是,所谓的 rollup 合约通常接受的是对 rollup 链完整状态的承诺,例如其状态树的默克尔树的根。状态转换将不断更新此承诺。
如果你对这些机制不是很了解,以下是这两个分类的工作原理:
本文将重点介绍具有简洁证明的 rollup。
不幸的是,仅仅确保执行的正确性是不够的。 为了提供抗审查性或活性等属性,rollup 仍然需要保证其完整状态是可还原的。如果 rollup 不能保证其完整状态是可还原的,则用户无法在 rollup 链中生成其账户余额的证明。这样的话,如果没有 rollup 运营者的合作,他们将无法将资金提取到 L1;显然,这是对 L1 保障安全性的严重偏离。
数据可用性 (DA) 指的是保证数据在网络内公开及时地发布。 换言之,我们这里指的数据可用,意味着假设发布者不会隐瞒数据。请注意,数据可用性与永久存储无关;数据会存在足够长的时间,在这段时间内任何利益相关的人都可以获取到它。数据可用性层 是用于发布数据的基础结构,可以保证数据可用。
有很多人会觉得 “数据可用性” 不是很好理解或者具有误导性。事后看来,像数据发布这样的替代术语可能是更好的选择。
详见:https://twitter.com/dankrad/status/1699598362851287459
确保数据可用性的问题最初是在 Layer 1 扩容解决方案的背景下引入的。一个简单直接的扩容策略是增加每个区块的容量。许多扩容解决方案都或多或少通过不同方式来实现此目的。任何增加区块大小的扩容解决方案的主要问题是,网络中的每个人都必须下载并验证所有区块。因此,如果我们过多地增加区块大小,性能较差的节点就会落后并被淘汰。因此,我们逐渐将得到一个不那么去中心化的网络。如果我们能以某种方式在节点之间分配验证区块的任务,这样每个人都只需要下载和验证每个区块的一小部分,那么我们就可以拥有更大的区块。这一系列解决方案的一个挑战是确保整个区块确实被发布。
在上一章节中,我们讨论了为什么 rollup 链完整状态的可恢复性对于继承 L1 的安全性是必要的。我们可以通过提供如下的任一可用数据来确保完整状态是可恢复的:(1) 交易数据或 (2) 状态差异数据。
Rollup 将继承其数据可用性层的所有安全假设。这就是为什么许多 rollup 使用它们所基于的 L1 作为数据可用性层的原因:以避免额外的安全假设。使用以太坊作为数据可用性层的一种方法是简单地将数据嵌入到交易中,并确保它包含在 L1 区块中。只要以太坊区块可用,交易中嵌入的数据也将可用。以太坊区块一直是可用的,因为区块生产者被激励及时广播他们的区块以获得其他验证者的证明;否则,他们的区块将被忽略。
目前,在包含 EIP4844 之前,在交易中嵌入数据的最便宜的方案是将数据作为 calldata 字段。 calldata 是一个只读内存空间,用于存储你调用智能合约函数时一起发送的参数。此内存空间只能在函数执行期间访问,并且比存储更省 gas 费。虽然函数调用后无法在 EVM 环境中访问 calldata 的内容 ,但任何可以访问以太坊交易历史记录的人仍然可以恢复它。
但是,calldata 仍然很昂贵, 因为它除了数据可用性还提供了其他功能;一般来说,智能合约中可以读取 calldata 数据。而 EIP4844 引入了 blob-carrying transactions 交易后,旨在单独服务于数据可用性,将仅提供对 blob 数据的承诺,并且无法在智能合约中直接读取此数据。因此,预计在 blob 中发布数据的成本会低得多。然而,blob 数据的 gas 费用将采用类似 EIP1559 的机制单独定价。稍后会做更详细的介绍。
需要注意的是,降低数据可用性成本可以直接降低 rollup 的运营成本,这也意味着 rollup 用户的交易费用会变得更低。如今,常见的 rollup 运营商支付的 gas 费用中,大约有 80% 用于将 rollup 链数据嵌入到 L1 上的 calldata ,而只有 20% 用于证明验证。
Scroll 的 rollup 过程有很多阶段,但出于本文的目的,我们将只关注提交和最终确认,这两个阶段分别处理数据可用性和证明验证。
给定 prevStateRoot , 在commitment(txBatch)中执行提交的交易批次,将更新状态根为 postStateRoot 。
请注意,最终确认步骤仅将所有已执行交易的承诺作为输入,而不是所有交易。
如我们之前所说,证明声明仅包括对已执行交易的承诺。这是为了节省链上验证器合约的开销,使其不必处理大量的公共输入多项式,从而有效地压缩公共输入。然而,证明者必须在电路中打开这个承诺,即它必须知道批次中的实际交易。在 Scroll 的 zkEVM 上,PI 电路就是打开此承诺并解压缩 zkEVM 其余部分的公共输入的子电路。
PI 电路将对交易批次的承诺作为公共输入,证明者必须提供原始交易批次数据作为见证。PI 电路的约束条件将检查,所提供的见证确实与公共输入中的承诺所对应。跳过该一致性检查会使得恶意证明者提交一批次交易却执行另一批次交易,从而使 rollup 链的完整状态无法恢复。
到目前为止,我们讨论了数据可用性的重要性,以及以太坊今天如何被用作DA层。现在让我们转变为协议设计者的身份,快速浏览一下增加以太坊作为 DA 层容量的不同思路。
在任何方案中,如果节点能够对某些数据不可用“发出警报”,如果发布者随后发布剩余数据,则所有在当时没有关注该特定数据的节点都无法确定是发布者恶意隐瞒数据,还是 fisherman 恶意进行误报。
看待 EIP4844 的一种视角,是将 EIP4444 和 EIP4488 巧妙地结合在一起。除此之外,EIP4844 还实现了原始的 Danksharding 所需的许多组件,其中包含数据可用性抽样提案;因此,虽然它更容易实现,但它也同样为接下来的路线图铺平了道路。
EIP4844 引入了一种新的交易类型,称为 blob-carrying transaction。每个 blob-carrying transaction 类型交易都可以“携带”一个 blob 列表。blob 是格式化为 个 BLS12-381 椭圆曲线标量场(_Scalar field_)元素的数据包,大约 125 KB。采用此特定格式的原因是为了简化创建对 blob 内容的 KZG 承诺。
与 calldata 不同,blob 的内容在执行环境中不可用。事实上,blob-carrying transaction 交易只携带对 blob 数据的承诺,并且只有这些承诺在执行环境中可用。实际数据由共识层客户端共享、获取和验证。
blob 只存储很短的时间,即 4096 个 epoch,大约是 18 天多一点。在此期间,共识节点应将此数据提供给网络中的节点。之后,共识客户端可以修剪旧的 blob。此修剪机制旨在减轻 blob 数据存储的负担。请记住,数据可用性与永久数据存储无关;18 天已经足够任何利益相关方,在这段时间内获取数据。
blob-carrying transaction 看起来像一个普通的 EIP1559 交易,包含了两个附加字段 max_fee_per_blob_gas 和 blob_versioned_hashes 。我们将在下面章节中解释这两个新字段的功能。
Blob 的费用市场与正常的收费市场是分开的,这意味着在 EIP4844 之后,我们将有一个正常的(执行)gas 价格和一个 blob gas 价格。Blobs gas 的费用机制类似于 EIP1559 ,目标是每个区块包含 3 个 blob ,最多允许 6 个 blob。max_fee_per_blob_gas 字段表示用户愿意支付的 blob gas 价格;它必须大于或等于当前的 blob gas 价格才有效。
这样的设计选择意味着,Layer 2 的数据可用性成本不受 Layer 1 交易需求激增的影响。此外,这种二维的费用市场设计是向更远大的愿景迈出的一步,即通过采用多个维度的 EIP1559 来提高收费市场的效率。
每个区块的 blob 的目标容量并不高。它只有 380 KB,这意味着所有 rollup 加总起来大约能达到 100 TPS。在当前参数下,存储 blob 数据会给节点运营者带来近 50GB 的额外存储要求。对于一个常规的节点来说,50GB 不是太大的额外开销,那么为什么不在每个区块中包含更多的 blob 呢?原因是每个共识节点仍然需要下载和验证所有 blob。事实上, EIP4844 之后,直到区块的所有 blob 都被下载和验证,共识客户端不会认为区块是有效的。目前,我们仍然没有巧妙的数据可用性抽样机制。因此,必须严格限制 blob 引入后带来的额外开销,以避免因为区块通信延迟过高,而破坏共识机制的稳定。[注意:基本上,共识客户端的证明时间限制是 4 秒,因此每个区块必须在 4 秒之前充分广播]。这就是为什么 blob 的目标设置相对较低的原因。
事实是,我们还没有对 blob 目标容量和区块传播延迟之间的关系有很深入的认知。以太坊的网络拓扑非常复杂,几乎不可能在测试网上模拟[注:最近的一项研究调查了主网上大区块的传播延迟,然而,区块和 blob 在传播方面表现非常不同。区块的来源单一,而 blob 来源多样化,它们可以从传播过程的并行化中受益。] 因此,参数设置需要非常谨慎,当然未来可能会调整至更高的参数。
对每个 blob 的承诺采用版本化哈希的格式。它是一个 32 个字节的值,其中第一个字节是版本号,当前设置为 ,跟随 blob 的 KZG 承诺的 SHA256 哈希值的最后 31 个字节,即 version_byte + SHA256(KZG(blob))[1:] 。其基本原理是在不破坏格式的情况下保留将承诺方案从 KZG 更改为其他方案的可能性,以防万一 KZG 承诺不如我们所预期的那样安全,例如,如果量子计算机变得可行。
blob_versioned_hashes 字段表示对交易中包含的 blob 的承诺列表。请注意,一笔 blob-carrying transaction 交易可以携带多个 blob。
EIP4844 引入了一种新的预编译,允许用户打开对 blob 的承诺,并有效地从智能合约访问 blob 数据。这在验证涉及 blob 数据的乐观或简洁证明时非常方便。
point_evaluation_precompile(versioned_hash, kzg_commitment, proof, z, y) 将接受版本化哈希、对 blob 的 KZG 承诺,以及在点 和值 的 KZG 打开证明作为输入。它将验证 kzg_commitment 是否与所提供的 versioned_hash 一致,以及 proof 打开是否有效,也就是说对于 blob 的拉格朗日插值多项式p(X) ,我们可以验证 p(z) = y 。
该预编译很好地满足了 rollup 的需要,并提供了简洁的有效性证明。无需在 EVM 中完全打开对 blob 的承诺,只需检查电路中作为见证提供的数据是否与 blob 一致即可,我们稍后会对其做详细介绍。
EIP4844后,rollup 提交的交易将是一个携带 blob 的交易 tx 。Rollup 的交易批次将被编码进入 blob。那么 rollup 合约就无需再计算对交易批次数据的承诺了;我们只需将 tx.blob_versioned_hashes 复制到存储中,以便在最终确认阶段使用。
前面我们讨论过,PI 电路的功能是检查所提供的交易批次是否确实对应于提交阶段提供的交易批次的承诺。当我们将交易批次放入 blob 中时,我们仍然需要做一致性价检查,但实现的方式有所不同。
以太坊只有一条适合配对的 BN254 椭圆曲线的预编译。Scroll 的 zkEVM 使用了此曲线进行算术运算,这意味着我们在曲线 BN254 的标量场上定义了电路的值和约束。然而,EIP4844 使用了另一条 BLS12-381 曲线用作 KZG 承诺。这让事情变得有些复杂。
选择 BLS12-381 曲线可能是出于安全性和效率的考虑。共识客户端已经使用了 BL12-381 曲线进行证明,因此它已经被所有客户端团队实现和审计。此外,BN254 曲线仅提供 100 位的安全性,而 BLS12-381 曲线提供大约 120 位的安全性。
如果两条曲线相同,我们可以在 zkEVM 电路中添加一个 advice 列,专门用于存储用零填充的 blob 数据。对所有电路列的 KZG 承诺是最终的 snark 证明的一部分(注意:为了简单起见,假设我们不在批次级别进行任何聚合),我们可以将 KZG 对 blob 列的承诺与从 blob-carrying transaction 获得的版本化哈希进行比较。
遗憾的是,事实并非如此,我们不能直接使用 blob 的版本化哈希交叉检验对 advice 列的承诺。幸运的是,我们还有另一种可行的方法。假设 p(X) 为 BLS12-381 标量场上 blob 的拉格朗日多项式。我们可以在合约和电路中,同时在随机点 z 上计算这个多项式,并检查计算结果是否相等。然后根据著名的 Schwartz-Zippel 引理,如果等式以极高的概率成立,那么两个多项式是相同的。这里有挑战性的部分是在电路中对 p(X) 求值,因为必须在 BLS12-381 曲线上完成,而不是 BN254 曲线,而非原生域的运算通常成本都较高。使用重心公式,我们可以通过 次非原生的乘除法来做到这一点,并且对证明者带来的额外成本相对较小。
我们已实现用于电路中 blob 一致性检查的 PoC。该电路将对交易批次 batch_commit 、挑战点 z 和求值 y 的承诺作为公共输入。证明人必须提供 blob 作为见证。我们应用 Fiat-Shamir 来获得伪随机的挑战点 z ,随后电路约束 z = hash(batch_commit+blob) 。此外,电路还将约束 p(z)=y ,其中 p(X) 是 blob 的拉格朗日插值多项式。
实现中,该 gadget 使用了 28,083,027 个 advice 单元格和 3,393,116 个 lookup advice 单元格。在 M1 MacBook Pro(CPU 10 核,内存 16 GB)上,生成证明平均需要 138.97 秒。
数据可用性是区块链扩容难题的核心部分。EIP4844 是提高以太坊作为数据可用性层容量的一大步。但是,按照目前的参数设置,它无法提供足够大的容量来满足 rollup 的所有需求。希望未来 Danksharding 凭借其出色的数据可用性抽样功能,可以显著改善这种情况。在此之前,rollup 需要依赖 calldata 和 blob 存储的组合,并开发更好的压缩方案;或者接受额外的安全假设,采用以太坊以外的数据可用性层。