文章来源:scroll博文;翻译:金色财经xiaozou
1、前言
过去几年里,解决区块链可扩展性的三难困境一直是以太坊社区的首要任务,目标是在不牺牲去中心化或安全性的前提下实现更大的可扩展性。经过重重必要探索,以太坊社区一致采用以rollup为中心的方法来解决可扩展性问题,在以太坊发展路线图中优先考虑rollup需求。
大多数rollup所需要的唯一功能就是改进以太坊作为数据可用性层的可用性。EIP4844,也称为Proto-Danksharding,是以太坊对这一需求的快速回应,而同一EIP的高级版本正在研发中。EIP4844引入了新的交易格式,称为blob-carrying transactions(blob携带交易),允许用户在交易中包含数据blob;可确保这些数据在几周内可用。很快,以太坊网络将经进行Canun-Deneb硬分叉,其中便包括EIP4844等。
数据可用性长期以来一直是备受瞩目的话题,至少在区块链领域来说确是如此。然而,我们相信还有很多事情需要说明。本文,我们将探讨数据可用性(DA)层是什么,以及为什么rollup需要数据可用性层。此外,我们还将探讨EIP4844及其将如何提高以太坊作为数据可用性层的能力。最后,我们还将研究在电路中如何打开一个blob承诺,并提出一个简单的概念证明。
2、执行完整性是你的全部所需吗?
去中心化和无需许可的区块链会为用户带来很多颇具吸引力的保障,包括抗审查特性、不可篡改特性、活跃性,以及最重要的执行完整性。简单地说就是,状态转换是有效的,智能合约的执行总是正确无误的。这要归功于检验区块有效性的各节点以及网络的去中心化性质。Rollup试图提供同样的保障,而且成本更低!
Rollup的主要理念是将执行从L1转移到成本更低的环境中,同时采用一种机制来简洁地(ZK)或乐观地(OP)向L1 rollup合约证明这些执行是正确完成的,并且状态转换是有效的。重要的是要注意,所谓的rollup合约通常只能看到rollup链的完整状态承诺,例如其状态树的Merkle根。而状态转换更新承诺。
这两类机制如何运作?
OP:Optimistic机制基于欺诈证明。此想法是,如果一个rollup操作员向L1 rollup合约提交了一个无效的状态转换,人们就会受到激励去证明这种违约行为并因此获得奖励。所以,如果我们假设有人可以随时监视rollup链(尽管存在某种程度的延迟),就可以保证执行的完整性。只要没有无效的状态转换,L1就不必执行任何rollup交易;这就是用户节省成本的关键所在。相反,如果rollup操作员证明状态转换无效,则必须有人在指定的时间范围内构建并提供欺诈证明;否则,无效状态转换将不可撤销地被最终确定。注意,rollup链的完整状态必须对观察者可用(或可恢复),否则他们甚至无法识别无效的状态转换。
ZK:简洁的有效性证明更强大,因为它们不依赖于受激励的参与者来观察链的状态。ZK证明的内部机制非常复杂,借助了加密魔法,但它们能办到的事很简单直接,那就是使用数学方法证明rollup链的新状态是正确执行的结果。也就是说,即使rollup链的完整状态永远不可用,执行的完整性也能始终得以保证。
本文将重点介绍使用简洁证明的rollup。
不幸的是,执行完整性并不是你所需要的全部。为了提供抗审查性或活跃性等特性,rollup仍然需要保证其完整状态是可恢复的。如果rollup不能如此保证,那么用户就不能在rollup链中进行余额证明。反过来,如果没有rollup操作员的合作,将无法将资金提取到L1;显然,这是对L1保证的无法接受的偏离。
3、什么是数据可用性?
数据可用性(DA)是指在网络内公开并迅速发布数据的保证。换句话说,在这种情况下数据是可用的,也就是说它不会被发布者隐瞒。请注意,数据可用性与永久存储无关;数据的可用时间要足够长,让任何感兴趣的人都有机会获取。数据可用性层是发布数据的基础设施,确保数据可用。
(1)数据可用性问题的起源
数据可用性问题最初是在L1扩展解决方案的大背景下诞生的。一个自然而简单的扩展策略是增加各区块的容量。许多扩展解决方案都以这样或那样的方式做到了这一点。所有增加区块大小的扩展解决方案的主要问题是,网络中的每个人都必须下载并验证所有区块。因此,如果我们将区块大小增加太多,较弱的节点就会落后并被彻底淘汰。因此,我们慢慢就会迎来一个去中心化程度不高的网络。如果我们能够以某种方式在节点之间分配验证区块的任务,各节点只需下载和验证每个区块的一小部分,那么我们就可以拥有更大的区块。这一系列解决方案的一个挑战就是确保整个区块真正被发布。
(2)Rollup的数据可用性
在上文中,我们探讨了为什么需要rollup链完整状态的可恢复性来维护L1的保证。我们可以通过提供以下两种数据中的一种来保证完整状态是可恢复的:(1)交易数据或(2)状态差异数据。
Rollup继承其数据可用性层的所有安全假设。这就是为什么许多rollup使用它们运行其上的相同L1作为数据可用性层的原因:避免额外的安全性假设。使用以太坊作为数据可用性层的一种方法是将数据嵌入到交易中,并确保将其包含在L1区块中。只要以太坊区块可用,交易中的嵌入数据也将可用。以太坊区块是预期可用的,因为区块生产者受激励迅速广播他们的区块,以获得其他验证者的证明;否则他们的区块将被忽略。
目前,在包含EIP4844之前,在交易中嵌入数据的成本最低的方法是将数据作为calldata包含。Calldata是一个只读内存空间,存储所发送的智能合约函数调用参数。此内存空间仅在函数执行期间可访问,并且临时存储比长期存储更节省gas费。虽然在函数调用之后,在EVM环境中无法访问calldata的内容,但任何有权访问以太坊交易历史的人仍然可以将其恢复。
然而,calldata仍然比必要成本更昂贵,因为它提供了除数据可用性之外的其他特性;基本上,calldata可以从智能合约中读取。EIP4844引入了携带blob的交易(blob-carrying transactions),这些交易被设计为数据可用性效用。EVM中只有对blob数据的承诺可用,并且不可能直接在智能合约中读取这些数据。因此,预计以blob形式发布数据的成本将大大降低。然而,blob数据gas将通过类似EIP1559的机制单独定价。稍后会详细介绍。
需要注意的是,降低数据可用性成本直接降低了rollup运营成本,这意味着rollup用户的交易费用更低。如今,一个典型的rollup运营商所付gas费用中,大约有80%用于在L1上嵌入rollup链数据作为calldata,只有20%用于证明验证。
4、Scroll协议中的数据可用性
(1)ZKRollup合约:Commit及Finalize
Scroll的rollup过程有许多阶段,但出于本文目的,我们将只关注commit和finalize阶段,这两个阶段处理数据可用性和证明验证。
Commit:每隔几分钟,sequencer(排序器)就会以calldata的形式向rollup合约的commitBatch函数提交一批新交易。该函数计算并存储该批量交易的Keccak哈希值,当我们验证证明时,它将作为对snark验证者的承诺和输入。注意,L2交易数据嵌入在该L1交易中。虽然该数据不存入以太坊状态,但它却很好地成为了Scroll链的数据可用性解决方案。任何人都可以收集这些交易(从archive节点)并查看它们的有效负载。
Finalize:在对批量交易进行commit操作后,证明者开始为该批量交易的执行创建简洁的状态转换证明。finalizeBatchWithProof将证明作为输入,并验证如下语句:
注意,finalize步骤只将对所有已执行交易的承诺作为输入,而非所有交易。
(2)PI电路:解压缩公共输入
正如我们前面提到的,证明的语句只包括对已执行交易的承诺。这意味着链上验证者合约不必处理较大的公共输入多项式,从而有效地压缩公共输入。然而,证明者必须在电路中打开这个承诺,也就是说,它必须知道批处理的实际交易内容。在Scroll zkEVM上,PI电路是打开此承诺并为zkEVM的其余部分解压缩公共输入的子电路。
对交易包的承诺提供给PI电路作为公共输入,证明者必须提供原始交易批数据作为见证(witness)。PI电路的约束(constraints)检查所提供的见证确实与公共输入中的承诺相对应。跳过此一致性检查会让恶意证明者提交一批交易但却执行另一批交易,从而使rollup链的完整状态彻底无法恢复。
5、扩展以太坊作为数据可用性层的可用性
到目前为止,我们讨论了数据可用性的重要性以及今天如何将以太坊用作数据可用性层。现在让我们戴上协议设计师的帽子,快速了解一下提高以太坊作为数据可用性层性能的不同想法。
降低calldata gas成本:这是一个非常直观的想法,可以自动增强以太坊发布更多数据的能力,以实现数据可用性。事实上,在过去的EIP-2028中就已经这样做了。然而,这种方法有其局限性。Calldata的gas成本更低意味着更大的区块,也就意味着区块传播会有更大延迟。将区块传播延迟拉大会破坏L1的共识机制。
通过对区块中的calldata设置总上限来降低calldata gas成本:EIP4488提出的正是这一建议。虽然这听起来像是一笔不错的买卖,但以太坊核心开发人员认为这个提议太过复杂,实施起来风险太大,所以最终该提议还是被抛弃了。值得注意的是,这个EIP还有一个兄弟提案EIP4444。EIP4444的目标是减少节点操作员的数据存储需求,并建议执行客户端在一年后删减历史区块数据。EIP4444旨在通过减轻EIP4488引入的额外存储负载来完成EIP4488。
数据不可用性证明:假设我们有一种方法可以在网络中分配验证较大区块的任务,这样每个人都只需要下载和验证各区块的一小部分就可以了。如果一个节点试图下载较大区块的一部分却无法访问该区块怎么办?他们能进行数据不可用性证明并罚没区块生产者吗?很遗憾,答案是否定的。不发布数据并不是唯一可归因的错误。在此引用Al-Bassam等人的话:
在任何方案中,如果节点有能力对某些不可用的数据“发出警报”,如果发布者随后发布了剩余的数据,那么所有届时没有注意到该特定数据的节点都无法确定究竟是发布者恶意扣留数据还是渔夫(fisherman)恶意发出假警报。
6、Proto-Danksharing:携带blob的数据
可以将EIP4844看做是EIP4444和EIP4488的巧妙组合。它还部署了具有数据可用性采样建议的原始Danksharding所需的许多组件;因此,它在更易实现的同时,还为未来铺平了道路。
EIP引入了一种新的交易类型——携带blob的交易(blob-carrying transaction)。每个携带blob的交易都“携带”一系列blob。Blob是格式为BLS12-381标量字段中的212=4096个元素的数据包,大约为125千字节。使用这种特定格式的原因是为了简化对blob内容的KZG承诺的创建。
与calldata不同,blob内容在执行环境中不可用。实际上,携带blob的交易只携带对blob的承诺,并且只有这些承诺在执行环境中可用。实际数据由共识客户端共享、获取和验证。
这些blob只存储很短的时间,4096个epoch,也就是18天多一点。在此期间,共识节点应将这些数据提供给网络内的对等节点。在此之后,共识客户端可以删减旧的blob。这种删减机制旨在减轻存储blob的负担。请记住,数据可用性并不是指永久的数据存储;18天足够长了,所有感兴趣的人都有机会在此期间获取数据。
携带blob的交易看起来像带有两个额外字段(max_fee_per_blob_gas和blob_versioned_hashes)的常规EIP1559交易。我们将在下文解释这两个新字段的功能。
(1)Blob收费市场
Blob的收费市场与常规的收费市场是分开的,这意味着在EIP4844之后,我们将看到一个常规的(执行)gas价格和一个blob gas价格。一个类似EIP1559的机制用于blob gas价格,目标为3 blobs,每个区块最多允许6 blobs。字段max_fee_per_blob_gas表示用户愿意支付的blob gas价格;它必须大于或等于当前的blob gas价格才有效。
选择这种设计有一个很好的含义是,L2的数据可用性成本不受L1交易需求激增的影响。此外,这种二维收费市场设计是朝着采用多维EIP 1559提高收费市场效率的更雄心勃勃的愿景迈出的一步。
(2)Blob容量
各区块的blob目标容量并不很高,只有380 KB,在所有rollups情况下约为100 TPS。使用当前的参数存储blob数据为节点操作员引入了近50GB的额外存储需求。对于一个常规节点来说,50GB没什么好担心的,那么为什么不在每个区块中包含更多的blob呢?原因是每个共识节点仍然需要下载并验证所有blob。事实上,在包含EIP4844之后,共识客户端将不会认为一个区块是有效的,直到该区块的所有blob都被下载并验证。我们仍然没有很好的数据可用性抽样机制。因此,必须仔细限制blob带来的额外负载,以避免因将区块传播延迟拉长而破坏共识机制的风险(注:基本上,共识客户端的证明期限为4秒,所以各区块必须在4秒前很好地传播)。这就是为什么blob的目标设定相对较低的原因。
(3)KZG承诺和版本化哈希值
对各blob的承诺采用的是版本化哈希值的格式。它是一个32字节的值,其中第一个字节是版本,当前设置为0x01,然后是blob的KZG承诺的SHA256哈希值的最后31个字节,即version_byte + SHA256(KZG(blob))[1:]。其基本原理是保留在不破坏格式的情况下将承诺方案从KZG更改为其他功能的可能性,以防KZG承诺被认为不像期望的那样安全,例如,当量子计算机变得实用之后。
字段blob_versioned_hashes表示对交易中包含的blob的承诺列表。请注意,携带blob的交易可以携带多个blob。
(4)点评估预编译(Point Evaluation Precompile)
EIP4844引入了一个新的预编译,旨在允许用户打开对blob的承诺,并有效地从智能合约中访问blob数据。这在验证涉及blob数据的optimistic证明或简洁证明时非常方便。
point_evaluation_precompile ( versioned_hash, kzg_commitment, proof, z, y) 接收一个版本化的哈希值、对blob的KZG承诺,以及一个打开针对z点和y值证明的KZG作为输入。它验证kzg_commitment是否与提供的versioned_hash相对应,并且验证打开的证明是否有效。
这个预编译通过简洁的有效性证明很好地满足了rollup的需求。EVM中不需要完全打开对blob的承诺,只需检查作为见证的电路中提供的数据是否与blob一致即可。稍后会详细介绍。
7、EIP4844后Scroll协议的数据可用性
(1)Commit
在EIP4844之后,rollup提交交易将是一个携带blob的交易tx。该rollup交易包将被编码写入blob。这样,rollup合约就不再需要计算对交易批数据的承诺;我们只是将txt.blob_versioned_hashes复制到存储中,以便在finalization(最终确定)阶段使用。
(2)PI电路中的blob一致性验证
前面我们讨论了PI电路的功能是验证所提供的交易包是否确实与commit阶段提供的交易包的承诺相对应。当我们将交易包置入blob中时,我们仍然需要这样做,但是完成的方式略有不同。
(3)非原生字段的挑战
以太坊只有一个对配对友好的椭圆曲线BN254的预编译。我们的zkEVM使用该曲线进行算术运算,这意味着我们在曲线BN254的标量场上定义了电路的值和约束。然而,EIP4844使用另一个曲线BLS12-381进行KZG承诺。这让事情变得有点复杂。
这样的选择可能是出于安全性和效率的考量。共识客户端已经使用BL12-381曲线进行证明,因此它已经被所有客户团队实施和审计过了。此外,BN254只提供100 bits的安全性,而BLS12-381提供大约120 bits的安全性。
如果这两条曲线是相同的,我们可以在zkEVM电路中添加一个advice column(列),专门用于存储填充了0的blob数据。KZG对所有电路列的承诺是最终snark证明的一部分(注意:为了简单起见,假设我们没有进行任何批处理聚合),我们可以将对blob列的KZG承诺与从携带blob的交易中获得的版本化哈希值进行比较。
遗憾的是,情况并非如此,我们不能直接用blob版本的哈希值交叉验证对advice列的承诺。幸运的是,还有另一种可行方法。设p(X)为BLS12-381标量场上blob的拉格朗日多项式(Lagrange polynomial)。我们可以在合约中和在电路中在一个随机点z上对这个多项式求值,并查验这些求值是否相等。然后著名的Schwartz-Zippel引理表明,如果等式在高概率下成立,那么两个多项式是相同的。这里具有挑战性的部分是在电路中评估p(X),因为这个评估必须在BLS12-381上完成,而非BN254。非原生字段操作被认为相对昂贵。使用重心公式(barycentric formula),我们可以通过2×4096非原生乘法和除法来实现。对证明者施加的额外成本相对较小。
(4)概念证明
我们已经部署了一个用于电路内blob一致性检查的PoC。电路将对交易包batch_commit的承诺、挑战点z和估值y作为公共输入。证明者必须提供blob作为证人。我们应用Fiat-Shamir来获取匿名随机挑战点z,因此电路强制执行z = hash(batch_commit+blob)。并且,电路约束p(z)=y,其中p(X)为blob的拉格朗日插值多项式。
这个小工具使用28,083,027个advice单元格和3,393,116个查找advice单元格。在M1 MacBook Pro(10个CPU内核,16GB RAM)上,生成证明平均需要138.97秒。
8、结论
数据可用性是区块链可扩展性难题的一个重要部分。EIP4844是朝着提高以太坊作为数据可用性层的效用迈出的一大步。然而,以其目前的参数设置,还无法提供足够大的容量来满足所有rollup的需求。希望Danksharding凭借其出色的数据可用性抽样能够显著改善这种情况。在此之前,rollup需要依赖于calldata和blob存储,或者接收额外的安全假设并采用以太坊以外的数据可用性层。