跨域论文第二部分:存储证明、计算与膨胀

  • maven11
  • 发布于 2023-10-07 14:13
  • 阅读 33

本文探讨了在多链和Rollup的世界中实现信任最小化的状态互操作性的重要性,重点介绍了存储证明在跨域应用程序中的作用。文中详细分析了存储证明的原理及其在各种链和应用中的应用,提供了技术深度和案例分析,阐明了这一领域的前沿进展和潜在挑战。

如果你有兴趣传播本文信息,可以考虑与这条推文互动:https://x.com/0xRainandCoffee/status/1709989330280992798?s=20


正如我们在跨域论文的第一部分中所阐明的,我们正处于朝着多个链和 Rollups 世界发展的早期阶段。一些链可能是特定应用的,另一些是单一链,某些是 Rollups,还有一些使用共享数据可用性层。然而,要实现这样的世界,还有几个问题尚待解决。有些会降低我们构建系统的信任假设和安全风险,另一些则会提升用户体验。本文将旨在涵盖我们认为在跨域未来中将发挥重要作用的一些突出发展。

我们希望生活在一个建立在最少信任的中心化参与者基础上的模块化世界。在几十个,甚至上千个 Rollups、特定应用链和更多的环境中,最小化信任的状态互操作性对 Rollups、应用和链的正常运作至关重要。这其中的一些通过共享数据可用性(DA)层来最小化信用,但这并不能解决验证特定执行或结算层正确执行数据的问题。因此,可能会在处理预言机和数据计算问题中发挥首要作用的内容很可能是存储(或状态)证明。访问和计算分散的链上状态是构建表达性跨域应用程序的重要组成部分。

全球状态

在当前的模块化世界中,状态分散在数十个应用链、L1 和 Rollups 之间。有些链的区块时间比其他链快,但所有链都面临快速的状态膨胀和数据结构的大小和复杂性增加。在这些领域的应用无法在当前状态或历史状态上有效地可验证地搜索、计算和查询这些数据。

虽然当前的 Rollups 确实将一些信息发布到以太坊,但它没有保留所有 Rollups 的全球状态视图(以当前的形式也无法扩展)。因此,Rollups 之间的状态是分散的,构建跨 Rollups 应用程序是一个麻烦。每个 Rollup 仅保留其状态的视图,虽然可以从以太坊(pre-4844/4444)上的可用信息中重新计算该状态, 但这并不提供对这段历史状态信息的即时/无需信任的访问。存储证明在某种程度上“解决”了这些问题,同时也允许对这些数据进行更高效的链下计算。

存储证明是对某种在链上存储状态的有效性的证明,或在某个时间槽中被提取(例如,通过收缩 EIP4844 blob 数据,一个散列会在执行层中指向某种链下状态)。之前通过预言机或运行自己的归档节点(或请求该数据)来证明这一点;然而,证明也可以在链上的数据上进行更高效的计算(链下)。这些主要通过有效性证明来证明(这其中没有任何零知识的内容),并且在过去一年中,针对具体存储证明及其计算进行了一系列的优化和性能改进。我们还看到了一些针对链上数据的协处理器的兴起,以及用于链下-to-链上数据的 zkML

存储证明的简化表示

当你尝试创建独立的部署,并不是“真正的”跨链应用时,流动性分散的问题变得普遍。如果你是一种借贷协议,那么你就必须考虑到贷款价值比(LTV)等因素。由于在处理跨链流动性池时预言机问题,LTV 可能需要显著更高,并且某些部署的流动性差异。存储证明(和最小化信任的预言机)在某种程度上能帮助跨链应用从孤岛走向粮仓,并引导单一性的崩溃。除此之外,存储证明还为应用开发者提供了对其应用进行更具表达性的方式,而无需在信任假设上做出让步。

解释存储证明最简单的方式是,它们证明了“现有”承诺的开启。这一开启(根)是证明某状态存在于某个网络的证据。另一种可能在跨域案例中使用的证明类型(并且已经在许多跨域消息协议中有所使用)是轻客户端证明,而不是证明状态更改(执行),而是证明 validator 签名(共识),这些签名已经签署了某个区块(并信任接收的最终状态)。这意味着存储、执行和共识证明并不是同一回事。当我们提到存储证明时,我们主要指的是某状态在某树上链上存储的证明,而共识证明是指对某区块上 validator 签名的证明。

轻客户端(例如,在 Tendermint)与某区块的存储证明对比

请注意,随着网络上的 validator 数量越来越高,共识证明变得越来越困难。特别是在我们想证明整个集合的情况下。一些可以帮助解决这个问题的东西如 BLS 聚合,而 ZKP 也可能会发挥重要作用。不过,在单线程证明系统(大多数)中,公钥聚合的扩展性与验证者的数量呈线性关系。舞台已经搭建,但我们的英雄会愿意扮演他们的角色吗?


在任何区块链中,如果我们知道一系列区块导致某个根,我们可以证明这些区块的存在,以及这些区块内的不同树。例如,我们可以证明账户存储树指向特定链的世界状态树中的某账户状态的存储根。我们也可以证明收据,甚至区块尝试中的特定交易。

块头中不同树的根的简化表示

这些证明还可以汇聚成特定的树结构,以优化存储证明,例如 Verkle 树、Merkle 树山脉(MMRs)等。然后,我们可以取该树的根并将其发布到链上以进行验证。有一些新颖的方法可以使这些树和证明的更新更高效,其中之一便是 Recproofs,我们将在稍后讨论。

需要注意的是(在以太坊中)根(区块头)指向状态(例如 Patricia-Merkle),而信标根(这是单独的,并且基于 SHA256/SSZ 而非 Keccak/RLP)证明该区块上的 validator 签名。如果某段状态的散列被包含在根中,我们可以确保它在状态树中。以太坊中的独立信标根目前在 EVM(执行层)中不可访问,但 EIP-4788 计划改变这一点,以允许共识层根在 EVM 中公开,以便用于无信任访问。

那么,我们如何高效地存储这些数据,以便能够更高效地引用/包含它?一种方法是利用 Merkle Tree Mountain Ranges(MMRs),许多项目使用它,因为它是一种相对高效的数据结构,适用于大型日志数据,可以轻松获取,而无须提供整个树。

多个峰的 Merkle 树山脉的简化表示

它的构造是为了尽可能保持一个一致的单一二进制树(意味着每个节点最多有两个子节点),这可能导致该树结构具有多个“峰”(因此被称为山)。当需要一个 MMR 的根(顶部)节点时,必须将各个树的顶部结合在一起以计算整个 MMR 的根散列。使用 MMR 时,你并不是将整个 MMR 发布到链上,而是可以在链上验证 MMR 根的有效性证明,从而验证该 MMR 的正确存在。

另一种方法是转化。例如,你可以将 Merkle 树转化为 Verkle 树,并使用有效的向量承诺证明 Verkle 树中的路径。有关更多信息,请查阅 Verkle TreesBlockchain Commitments

状态证明的使用案例相当广泛,且有许多领域可以利用它们,而不仅仅是“替代”链上状态的预言机。例如;

  • 在懒惰共享排序节点中使用存储证明,以便 Rollup 节点能够向其他证明状态存储/执行。

  • 在状态委员会中使用存储证明。

  • 在 zk 轻客户端中使用存储证明。

  • 在提供定价/数据中使用存储证明。

  • 证明访问措施以参与空投和公共产品资助的存储证明。

  • 在桥接中证明区块头已发送至目标链的存储证明 - telepathy、polyhedra/zkbridge。

  • 用于数据等价转换的状态证明(我们会深入讨论这一点)。

存储证明的著名参与者包括 LagrangeAxiomHerodotus,还有各种其他轻客户端协议的实现(例如 Succinct)和存储证明。此外,还有受到它们衍生影响的桥接协议。


虽然存储证明使应用可以以最小信任的方式访问特定的历史存储,并比运行自己的归档/全节点更高效,但它并没有提供对获取数据进行有效计算或查询的能力。它们是独立的,在证明特定的历史数据时非常出色,但在可以展示的内容上高度受限,并且对该数据的计算并不高效。

那么,如果我处于一种情况下,我希望问的不仅仅是某个账户拥有什么,而是 ETH-USDC 在某个区块的价格是多少?如果我想了解 several blocks 中的时间加权平均价格(TWAP),或者我想分析某资产池在几块上的波动性呢?这就是协处理器、Recproofs 以及零知识 MapReduce (ZKMR) 大显身手的地方。

简单而言,协处理器(由 Axiom 推广)是一个链下协议,类似于链上虚拟机(VM)的扩展。开发者可以提交对他们希望获取的某种状态的查询(通过存储证明),然后让这个链下机制在经过验证的数据上执行一些请求的计算,这些结果可以再发送回链上。这在链上计算中是非常有用的,这些计算要么是不可能的,要么是成本极高的(因而是不切实际的),甚至超出当前的 Gas 限制。虽然这种计算可能会根据自定义电路进行调整,但也有可能运行 EVM 的扩展链下(基本上是一个 Rollup,但没有整个状态、排序者和内存池部分),基本上是一个并非真正的 Rollup 的 Rollup。这些我们喜欢称之为 VM 扩展,因为它们本质上充当了底层层的原生 VM 的扩展,同时证明了对其下获取的链上数据的链下计算。请注意,这些构造均是在不同于上层链的原生 VM 的异步执行下进行的。

链下计算(VM-扩展、协处理器等)

这些可以采取的构造示例包括 Zeth(由 Risc Zero 开发)、fhEVM 等。这些通常一开始可能是无状态的构造。然而,绝对有未来可能会希望进行有状态的事情——意味着像有状态的 Bonsai 或将 VM 或计算证明与存储/状态证明结合的可能性。

不同类型证明之间差异的总结:

  • 存储证明: 证明一个“现有”承诺的开启(根)。这一开启是一种证明,证明某种状态存在于某个网络中。

  • 状态证明 对状态/内存/栈操作已正确执行做出证明。这并未检查是否已读取/写入正确位置。

  • VM证明 检查在正确时间调用了正确的操作码。验证这些操作码的有效性,同时确认每个这些操作码和状态证明都执行了正确的操作。

然而,对于许多计算仍然存在一些限制。那么如果我们想进行的计算和分析更类似于那些大型传统 Web2 公司,如 Uber 等公司所进行的计算呢?这些事情包括 SQL、MapReduce 和 Spark/RDD。对此的一个提案(超出前面提到的 VM 扩展/协处理器)来自 Lagrange

基于存储证明的计算

零知识 MapReduce (ZKMR)

ZKMR 证明本质上是一个数据框架(本质上是类表格的数据结构),可以证明一系列区块(及其特定存储槽),前提是对数据进行了附加计算。例如,这可能是对一段时间内的流动性进行平均的范围。这一证明本身只是有效性证明,验证在特定数据框架(通过特定区块头引用到每个数据框架)上执行的一组计算的结果。这意味着,证明不仅要证明底层数据的存在(一个简单的存储证明),而且还要连同所执行状态的计算结果合而为一。你可以进行的计算类型相当灵活。可以像通常一样简单进行验证输出证明。这意味着你现在可以证明一批存储,以及在该存储上执行的计算。

你基本上需要四样东西:

  • 来自链的区块头.

  • 一个指定的区块编号和存储槽的范围。

  • 可并行化的计算(例如,SQL、MapReduce 或 Spark/RDD)。

  • 部署在接收链上的验证合约。

这份验证合约可以在任何你希望的链上,只要它支持该证明方案的验证。这也意味着跨链消息协议可以中继它们,并增加在不同域间使用状态的表达性。

从多个链生成的一套批量存储证明的 ZK-MapReduce 计算的简化表示。

因此,你可以生成和证明与数据并行计算的大范围批量存储证明。这是通过向量承诺(我们之前详细描述的内容)实现的,非常便于证明分布式计算(特别是分布式编程模型,如 SQL 和 MapReduce,因而得名)。

MapReduce 风格的计算,在本例中在三个链上对三组资产的流动性/TVL 进行计算。

获得的另一个特性是能够合并来自不同链的存储证明,对这些存储证明进行一些计算(例如,在多个 Rollups 上的 Eth-USDC 在一段时间内的流动性值),将这些计算合并以获取平均价格,并将该输出作为单一的有效性证明在链上进行验证。借助这种组合性,它们在消息协议中实际上获得了充当跨链协处理器的能力。

然而,虽然你现在拥有非常高效的属性,再三计算这些模型在稍微更改的数据上所花费的成本相当高。解决这一问题的一种方法是拥有可更新证明,可以重新组合、更新和合并。对此的一种解决方案是 Recproofs。

Recproofs

Recproofs 是一种基于 Merkle 树的向量承诺方案,使用递归 SNARK 对 Merkle 树中叶子子集(而不是整个组)执行批处理证明。然而,在递归 SNARK 的情况下,如果验证者(在递归电路中)大于电路本身,就不太有效。尽管我们处理的是非常大的集合,因此这不是特别的担忧。另一个正在讨论的想法是利用折叠方案。因此,不是验证电路中的证明,而是将许多证明折叠成新的证明。检查折叠比验证每个证明简单得多,最后可以进行耗时的验证。然而,在分布式(或横向扩展的)证明系统中,如何在规模上有效沟通仍然是一个 开放问题。此外,需要存储折叠方案的证人以使其工作,显著增加存储需求。然而,这可以降低证明时间。正如我们所说,世界上总是存在权衡。

简单的 Merkle 树结构和一个加了检查点的递归 Snark 构建(你也可以递归证明每个证明,而不是检查点,检查点在扩展解决方案中更有价值 - 例如,Starknet使用这样的设计)

在 Recproofs 的当前设置下(使用递归 SNARKs)将子集散列的计算折叠到 Merkle 树验证过程的计算中。这是通过规范性散列(划分、散列、组合、重复生成表示整个集合的单个更短散列根值)来实现的。这允许在树内的叶子子集发生变化时,在对批量证明的更新上以对数时间进行操作(计算不会随着输入规模的增长线性增加,基本上,性能在输入规模增加时保持高效)。数据结构则维护存储先前计算的递归证明以促进更新。

通过 Recproofs 实现可更新和部分证明

这在 zkMapReduce 中创建证明时非常有用。它允许某人锁定内存,证明其部分内容,并在事物更改时轻松更新证明。简单而言,它减少了对大量数据生成新证明时的证明时间,同时保持证明通过组合先前的证明而不进行重新计算而扩展。对于需要对动态区块流或其他持续变化的数据进行计算和维护证明的情况,这尤其方便。这对 BLS 签名聚合等方案也可能非常有用。

如果你想更深入地了解 Recproofs,我们推荐查看原始论文 这里

来自 Lagrange 的上述实现的另一个可能有趣的使用案例是证明数据根等价性,针对那些不一定是零知识友好的结构(零知识友好的数据结构模拟非零知识友好的结构)。在 DA 层(或 ZK Rollups)上的数据块的情况下,这可能特别有趣。如果你对此感兴趣,我们强烈建议查阅 Ismael Khoffi 在这次演讲中的这一部分,暗示了可能性,以及 Nick White 的这个演讲,概述了进一步为 Celestia 等提供 ZK 启用改进的可能性。在这里,Recproofs 是特别有吸引力的,因为这些层处理的持续更新流量。Recproofs 论文中还有一小节关于摘要转换,涵盖了这一点。另一个迷人的应用是使用 ZK Rollup 桥与数据等价性构建最小状态层的潜在想法 逃逸速度


Periander

我们相信在不久的将来,大多数链上数据将通过存储证明以最低的信任方式进行引用和验证——实现形式可能是去中心化和信任最小化,或者是中心化但“无信任”的。这并不意味着预言机“死亡”的 Nekromanteion,而是有效性证明的扩散和使用,以最大程度地降低对链上数据的预言机网络的信任。毕竟,我们甚至有信任的预言机用于链上状态,这是一种相当显着的悖论。

对于链外的数据,我们所知道的预言机仍然非常有用(或者如果我们考虑那些无法从某个具有经济安全性、数学上被证明的数据和削减标准的网络中获取的价格的实际应用,则可能存在问题)。有趣的是,对于一些可以通过数学证明的使用案例,还可以探索 交互式零知识证明 作为预言机——然而,因几种因素,实际在生产中使用这些仍然非常有限,例如成本。


桥接和无信任预言机

在桥接中,如前所述,存储证明也有可能发挥重要作用。它已经做到了一定程度,通过能够证明特定区块头/消息已发送到接收链(因而被存储),提升现有跨链消息协议的安全性。

然而,在处理桥接资产/状态时,还有一个重要的因素需要记住。这一点尤其会在具有不同 分叉选择规则 的主权链中使用。

为了确保跨链消息处理正确,我们都需要验证链的状态有效性及其分叉选择。存储证明解决了第一部分,通过证明一些状态存储在某个槽中。然而,由于区块链中只有一个规范块,我们需要确信特定区块是规范块(因为根据链的不同,实际上可能存在多个有效区块——因此会存在重组)。要对此进行验证,我们需要保证(或证明)区块数据在 DA 层上已最终确定。在这里,我们可以在特定的 DA 层上运行轻节点(或完整节点)以获得保证,或者从 DA 层的数据等价结构(例如,类似 Lagrange 的 ZK 友好数据结构)提取数据。然而,在连接到另一条具有不同 DA 层的链,以及后者未在前者 DA 层上运行轻节点的情况下,我们仍然需要确保。在这里,你可以有一个中继集,其任务是中继 DA 块上的 validator 签名到所需的链。

区块头桥接是存储证明的自然扩展,因为区块头(作为根的存储证明)证明了与相关区块的信息存在,并且很可能会成为桥接代币的标准。这些证明不仅限于代币桥接,还可以扩展超出此范围。以下是若干所需结构的示例;

这里可以探索类似结构:https://ethresear.ch/t/hashi-a-principled-approach-to-bridges/14725

只有在有冲突报告的情况下,你才需要共识来解决这一问题,如果你希望这在没有权限的情况下与一些参与方一起工作。然而,如果问题中的代币在某链上,而网络在链下,则经常会遇到引人注目的社会削减(当协议参数控制着未遵循相同规则的不同协议上的资产时,难以解决)。另一方面,还有乐观执行协议,其中第三方承担库存风险以更快地处理桥接。这些方法很好,但附带的风险更高。不过,这些方法仍可能希望为所述消息提供更高水平的“最终确定”,并可能还会使用类似的解决方案。

预言机

另一个用例是将有效性证明重新利用到预言机中,帮助减少对受信第三方的依赖。例如,现有的质押池,甚至重新质押的参与者,可以帮助为网络提供所需的(预言机)信息,因为他们已经是链的活跃参与者,因而可以获得相当可观的密码经济安全性。此外,事实是,当用户和验证者追逐最高收益时,我们也会获得越来越多的质押代币的变种和表示。这些代币通常在 DeFi 中使用(例如在借贷中),并经常依赖于可信的预言机,这对基础协议构成了重大风险(在包括重新质押、社会削减以及这个经济问题之前,更是如此)。我们依赖上述可信预言机获取数据,而这些数据合理上会影响基础协议的健康。因此,确保获得最高级别的安全性至关重要。下面是这些原生重用预言机的示例(请记住,这不仅用于链上 AMM 上的定价案例):

类似的构造可以在这里找到:https://blog.lido.fi/grants-exploration-zkproof-trustless-oracles/

在此设置中,区块哈希合约接收来自重用预言机的报告,执行检查并验证有效性证明,对所述报告的有效性进行证明。然后,可以进行检索。预言机(例如由重新质押/验证者池“保护”的扩展链下机制)计算所需的数据,并将所需的证明数据发送给证明者。证明者存在的目的是重复所需计算,证明链下通过数学方式指定的预言机数据的正确性,然后发送给链上的验证证明,可以进行交叉引用。

这类“验证者作为预言机”的示例在 Cosmos 生态系统中已经可见,尤其是在 SeiUmee 中。然而,Cosmos 链相对较低的活跃验证者集(和委托)使得合谋所需的验证者数量显著降低。尽管如此,这确实将重要方面(预言机)与网络的密码经济和共识安全绑定在一起。

状态膨胀和优化

不断增长的状态膨胀问题仍然在持续,尽管存储证明可以帮助验证链上(或链下)状态,但它并没有解决状态仍需存储这一事实。虽然你可以将状态存储到其他网络、节点组或归档节点,但它仍然需要以某种方式存储。 Verkle 树、MMR 和存储证明所帮助的无状态性仅适用于积极的共识/执行节点,但承载庞大的状态存储仍然是必需的。然而,在我们拥有特定状态节点(可以说是巨大的、运行成本极高,因此很可能数量较少)的情况下,我们仍然可以依赖诚实少数的假设 - 只要有一个参与者是诚实的,我们就可以保证可以重建状态。构造如 Joachim Neu 和合作 提出的 ETHStorage 等系统也很有趣。

一般来说,我们认为区块链要想达到全球规模,唯一的方法是对特定节点类型进行委托、专业化和优化,同时让轻客户端能够具有更强的表达能力。 这延展至积极(高功能)客户端的想法,它们参与链上的积极行动(例如执行和共识)必须尽可能地对此目的进行优化。例如,执行客户端可能应持有更少的状态,或共识/数据可用性应委托给轻客户端(在共识情况下,委托给最小状态的共识客户端)。在这种情况下,状态应委托给归档节点、状态租赁构造或类似方案,同时在 Verkle 树中存储向量承诺以供正确参考。存储证明在此处的帮助在于让智能合约“无需信任”地验证某些状态在这些诚实的少数存储节点之一(最好是受托管)。

本质上,一个高效的区块链就如同一个结构良好、组织良好的公司。公司中的不同部分专注于特定任务和操作,同时彼此验证输出。

感谢 Mathijs van Esch (M11)、Ismael H-R (Lagrange)、Dougie DeLuca (Figment)、Pim Swart (M11)、Lachlan (Kosmos)、Tracy (Pluto)、Terry (1kx) 和 Yuki (Fenbushi) 就撰写本文的讨论或审查。

在此找到 Maven11:Maven11.com 以及 Twitter @ Maven11Capital

作者:0xrainandcoffee

  • 原文链接: maven11.substack.com/p/t...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
maven11
maven11
江湖只有他的大名,没有他的介绍。