存储证明:实现跨时间、跨链的状态感知

进阶Dec 26, 2023
本文阐述了如何使用存储证明传输信息、处理数据,并将其应用于跨链治理、跨链借贷、多链预言机等领域。
存储证明:实现跨时间、跨链的状态感知

前言

如果你每小时都失去记忆怎么办?而且你需要不断地请别人告诉你你做了什么?这就是智能合约的现状。在以太坊等区块链上,智能合约无法直接访问超过256个区块的状态。这个问题在多链生态系统中进一步加剧,使系统中跨不同执行层的数据检索和验证更加困难。

2020年,Vitalik Buterin 和 Tomasz Stanczak 提出了一种跨时间访问数据的方法。虽然 EIP 已经停滞不前,但它的需求在以 Roll-up 为中心的多链世界中重新出现。如今,存储证明已经成为一个前沿领域,能为智能合约提供意识和记忆。

访问链上数据

Aapp 可以通过多种方式访问数据和状态。所有方法都要求应用程序信任人类/实体或加密经济安全或代码,并进行一些权衡:

对人类/实体的信任:

  • 归档节点:运营者可以自己运行归档节点,也可以依赖 Alchemy 或 Infura 等归档节点服务提供者来访问自创世区块以来的所有数据。它们提供与完整节点相同的所有数据,而且还提供整个区块链的所有历史状态数据。Etherscan 和 Dune Analytics 等链下服务使用归档节点来访问链上数据。链下参与者可以证明该数据的有效性,链上智能合约可以验证数据是由受信任的参与者/委员会签署的。底层数据的完整性未经验证。这种方法要求 dapp 相信归档节点服务提供者正在正确运行基础设施,并且没有任何恶意意图。

信任加密经济安全:

  • 索引器:索引协议组织区块链上的所有数据,允许开发人员构建和发布应用程序可以查询的开放 API。单个索引器是节点运营者,它们通过抵押代币来提供索引和查询处理服务。然而,当提供的数据不正确时,可能会发生争议,并且仲裁过程可能需要时间。此外,来自 The Graph 等索引器的数据不能直接被智能合约的业务逻辑利用,而是在基于 web2 的数据分析环境中使用。
  • 预言机:预言机服务提供商使用来自许多独立节点运营者聚合的数据。这里的挑战是,Oracle 提供的数据可能不会经常更新,并且范围有限。像 Chainlink 这样的预言机通常只维护特定的状态(例如价格馈送),但对于特定于应用程序的状态和历史记录,它们是不可行的。此外,这种方法还引入了一定程度的数据偏差,需要对节点运营者的信任。

信任代码:

  • 特殊变量和函数:像以太坊这样的区块链具有特殊变量和函数,主要用于提供有关区块链的信息或通用实用函数。智能合约只能访问256个最新区块的区块哈希值。出于可扩展性的原因,块哈希值并非适用于所有区块。访问历史区块哈希值将会很有用,因为它支持验证它们的证明。EVM 执行中没有支持访问旧区块内容或以前的交易内容或收据输出的操作码,因此节点可以安全地忽略这些内容,但仍然能够处理新区块。该方法也仅限于单个区块链。

考虑到这些解决方案具有的挑战和局限性,显然需要在链上存储并提供块哈希。这就是存储证明发挥作用的地方。为了更好地理解存储证明,让我们先快速了解一下区块链中的数据存储。

区块链中的数据存储

区块链是一个公共数据库,可以在网络中的许多计算机之间更新和共享。数据和状态存储在称为块的连续组中,每个区块通过存储前一个块头的哈希值以加密方式引用其父块。

我们以以太坊区块为例。以太坊利用一种特殊类型的 Merkle 树,称为“Merkle Patricia 树”(MPT)。以太坊区块头包含四种不同 Merkle-Patricia 树的根,即状态树、存储树、收据树和交易树。这四种尝试对包含所有以太坊数据的映射进行编码。Merkle 树因其具有数据存储效率而被使用。使用递归哈希,最终只需要存储根哈希,节省了大量空间。它们允许任何人通过证明对节点进行递归哈希会导致相同的根哈希这一事实来证明树中元素的存在。Merkle 证明允许以太坊上的轻客户端获得以下问题的答案:

  • 该交易是否存在于特定区块中?
  • 我的账户当前余额是多少?
  • 这个账号存在吗?

“轻客户端”只能下载区块头链并使用 Merkle 证明验证信息,而不是下载每笔交易和每个区块。因此,整个过程非常高效。请参阅本博客中 Vitalik 和 Maven11 的这篇研究博文,以更好地了解与 Merkle树相关的实现、优点和挑战。

存储证明

存储证明使我们能够证明某些内容已在数据库中提交,并且使用加密承诺也是有效的。如果我们能够提供这样的证据,那么区块链上发生的事情就是可验证的。

存储证明可以实现什么?

存储证明有两个主要功能:

  1. 访问过去 256 个区块之外的历史链上数据,一直追溯到创世区块
  2. 借助共识验证或 L1-L2 桥(如果是 L2),访问另一个区块链上一个区块链的链上数据(包括历史和当前数据)

存储证明如何发挥作用?

非常高级别的存储证明负责检查特定块是否是区块链规范历史的一部分,然后验证请求的特定数据是否是该区块的一部分。这可以通过以下方式实现:

  • 链上处理:dapp 可以获取初始可信区块,将该区块作为 calldata 传递以访问前一个区块,并一路访问至创世块。这需要大量的链上算力和大量的调用数据。由于链上需要大量算力,这种方法根本不可行。 2018年,Aragon 尝试使用链上方式,但由于链上成本较高,并不可行。
  • 使用 ZK 证明:该方法与链上处理类似,不同之处在于 ZK 证明者用于将复杂的计算移至链外。
  1. 访问同一链上的数据:ZK 证明可用于确定任意历史区块头是执行环境中可访问的256个最新区块头之一的先创区块。另一种方法是索引源链的整个历史记录并生成相同的 ZK 证明以证明索引正确发生。随着新区块添加到源链中,该证明会定期更新。
  2. 跨链访问数据:提供者在目标链上收集源链的区块头,并使用 ZK 共识证明来证明这些区块头的有效性。还可以使用现有的 AMP 解决方案(例如 Axelar、Celer 或 LayerZero)来查询块头。
  3. 源链块头的哈希值缓存或链外块哈希累加器的根哈希值保存在目标链上。该缓存定期更新,用于有效地在链上证明给定区块的存在,并且具有与可从状态访问的最近块哈希的加密链接。这个过程被称为证明链的连续性。也可以使用专用区块链来存储所有源链的块头。
  4. 根据目标链上 dapp 的请求,从链外索引数据或链上缓存(取决于请求的复杂性)访问历史数据/块。虽然块头哈希的缓存在链上维护,但实际数据可能存储在链外。
  5. 通过 Merkle 包含证明检查指定块中数据的存在,并生成相同的 zk 证明。该证明与正确索引的 zk 证明或 ZK 共识证明相结合,并且该证明可在链上进行无需信任的验证。
  6. 然后,dapp 可以在链上验证此证明并使用该数据执行所需的操作。除了 ZK 证明的验证之外,还会根据链上维护的块头缓存检查块号和块哈希等公共参数。

采用这种方法的一些项目有 Herodotus、Lagrange、Axiom、Hyper Oracle、Brevis Network 和 nil Foundation。尽管人们正在努力使应用程序跨多个区块链进行状态感知,但 IBC(区块链间通信)作为互操作性标准脱颖而出,支持 ICQ(链间查询)和 ICA(链间账户)等应用程序。ICQ 使链 A 上的应用程序能够通过将查询包含在简单的 IBC 数据包中来查询链 B 的状态,而 ICA 允许一个区块链安全地控制另一个区块链上的帐户。将它们组合起来就能实现值得期待的跨链用例。Saga 等 RaaS 提供商默认使用 IBC 向其所有应用程序链提供这些功能。

可通过多种方式优化存储证明,以找到内存消耗、证明时间、验证时间、计算效率和开发人员体验之间的适当平衡。整个流程大致可以分为3个主要分步骤。

  • 数据存取
  • 数据处理
  • 生产用于访问和处理数据的 ZK 证明

数据访问:在此分步中,服务提供者在执行层本地或通过维护链上缓存来访问源链的块头。对于跨链数据访问,需要在目的链上验证源链共识。正在采用的一些方法和优化包括:

  • 现有以太坊区块链:以太坊区块链的现有结构可用于使用 ZKP 证明任何历史存储插槽相对于当前区块头的价值。这可以被视为是一个大型包含证明。这证明,给定高度为 b 的最近块头 X,存在块头 Y,它是高度 b-k 处的 X 的先创区块。它基于以太坊共识的安全性,需要快速证明的系统来提高效率。这就是Lagrange所使用的方法。
  • 链上 Merkle Mountain Ranges (MMR) 缓存:Merkle Mountain Range 可以被视为 Merkle 树的列表,其中当两棵树达到相同大小时,各个 Merkle 树将被合并。 MMR 中的各个 Merkle 树通过将父节点添加到树先前的根来组合。 MMR 是一种类似于 Merkle 树的数据结构,具有一些额外的优点,例如元素的高效附加和高效的数据查询,特别是在从大型数据集中读取顺序数据时更是如此。通过 Merkle 树附加新块头需要传递每个级别的所有姐妹节点。为了有效地附加数据,Axiom 使用 MMR 在链上维护块头哈希的缓存。Herodotus 将 MMR 区块哈希累加器的根哈希存储在链上。这使他们能够通过包含证明根据这些块头哈希检查获取的数据。这种方法需要定期更新缓存,如果不具有去中心化特性,就会带来活跃性问题。
  • 希罗多德维持两种不同的 MMR。根据特定的区块链或层,可以定制累加器以利用不同的哈希函数,优化效率和算力成本。为了在 Starknet 上进行证明,可能会使用poseidon 哈希,但 Keccack 哈希可能会用于 EVM 链。
  • 链下 MMR 缓存:Herodotus 维护先前获取的查询和结果的链下缓存,以便在再次请求数据时可以更快地获取。这需要额外的基础设施,而不仅仅是运行归档节点。对链下基础设施进行的优化可能会降低最终用户的成本。
  • 用于存储的专用区块链:Brevis 依靠专用的 ZK rollup(聚合层)来存储它们所证明的所有链的所有块头。如果没有这个聚合层,每个链都需要存储每个其他链的块头,从而导致 N 个区块链的“连接”为 O(N2)。通过引入聚合层,每个区块链只需要存储汇总的状态根,从而将整体连接减少到 O(N)。该层还用于聚合块头/查询结果的多个证明,并且可以提交用于在每个连接的区块链上进行验证的单个证明。
  • L1-L2 消息传递:在 L2 的情况下,可以避免源链共识的验证,因为 L2 支持用于更新 L1 上的 L2 合约的本地消息传递。缓存可以在以太坊上更新,L1-L2 消息传递可用于将链下编译的块哈希或树根发送到其他 L2。Herodotus正在采用这种方法,但这对于替代 L1 来说是不可行的。

数据处理:

除了访问数据之外,智能合约还应该能够在数据之上进行任意计算。虽然某些用例可能不需要计算,但对于许多其他用例来说,它是一项重要的增值服务。许多服务提供商都可以对数据进行计算,因为可以在链上生成并提供计算的 zk 证明以确保有效性。由于 Axelar、LayerZero、Polyhedra Network 等现有 AMP 解决方案可能用于数据访问,因此数据处理可能成为存储证明服务提供商的区分因素。

例如,Hyper Oracle 允许开发人员使用 JavaScript 定义自定义链下计算。Brevis 设计了一个开放的 ZK 查询引擎市场,它接受来自 dApp 的数据查询,并使用经过验证的块头对其进行处理。智能合约发送数据查询,该数据查询由市场上的证明者获取。证明者根据查询输入、相关区块头(来自 Brevis 聚合层)和结果生成证明。Lagrange 引入了 ZK Big Data Stack 来证明 SQL、MapReduce 和 Spark/RDD 等分布式编程模型。证明是模块化的,可以从源自现有跨链桥和 AMP 协议的任何块头生成。ZK MapReduce是Lagrange ZK BigData堆栈中的第一个产品,是一个分布式计算引擎(基于著名的MapReduce编程模型),用于证明涉及大量多链数据的计算结果。例如,单个 ZKMR 证明可用于证明在指定时间窗口内部署在 4-5 条链上的 DEX 的流动性变化。对于相对简单的查询,计算也可以直接在链上完成,就像Herodotus 目前所做的那样。

证明生成:

  • 可更新证明:当需要在移动的区块流上计算和有效维护证明时,可以使用可更新证明。当 dapp 希望维护合约变量(例如代币价格)的移动平均线的证明时,随着新区块的创建,无需从头开始重新计算新的证明,现有的证明可以有效地更新。为了证明链上状态上的动态数据并行计算,Lagrange 在 MPT 的一部分之上构建了一个批量向量承诺(称为 Recproof),可动态更新它,并对其进行动态计算。通过在 MPT 之上递归地创建 Verkle 树,Lagrange 能够高效计算大量动态链上状态数据。
  • Verkle 树:与 Merkle 树不同,我们需要提供共享父节点的所有节点,Verkle 树只需要到根的路径。与 Merkle 树的所有姐妹节点相比,这条路径要小得多。以太坊也在探索在未来版本中使用 Verkle 树,以最大限度地减少以太坊全节点需要保存的状态量。Brevis 利用 Verkle Tree 在聚合层中存储经验证过的块头和查询结果。它大大减少了数据包含证明的大小,特别是当树包含大量元素时,并且还支持对一批数据实施高效包含证明时更是如此。
  • Mempool 监控可加快证明生成速度:Herodotus 最近发布了 Turbo,它允许开发人员在其智能合约代码中添加几行代码来指定数据查询。Herodotus 监控内存池中与 Turbo 合约交互的智能合约交易。当交易位于内存池本身时,证明生成过程就开始了。一旦在链上生成并验证了证明,结果就会被写入链上turbo交换合约中。结果只有在通过存储证明验证后才能写入 Turbo 交换合约。一旦发生这种情况,一部分交易费用将与排序器​​或区块构建器共享,从而激励他们等待更长的时间来收取费用。对于简单的数据查询,在用户的交易包含在区块中之前,所请求的数据可能在链上可用。

状态/存储证明的应用

状态和存储证明可以在应用程序、中间件和基础设施层开启智能合约的许多新用例。其中一些包括:

应用层:

治理:

  • 跨链投票:链上投票协议可以允许链 B 上的用户证明链 A 上资产的所有权。用户无需桥接其资产即可在新链上获得投票权。例如,Herodotus 上的 SnapshotX。
  • 治理代币分配:应用程序可以向活跃用户或早期采用者分发更多治理代币。例如,Lagrange上的 RetroPGF

身份和声誉:

  • 所有权证明:用户可以提供链 A 上特定 NFT、SBT 或资产的所有权证明,使他们能够在链 B 上执行某些操作。例如,游戏应用链可能决定在链上推出其 NFT 系列另一条具有现有流动性的链,如以太坊或任何 L2。这将允许游戏利用其他地方存在的流动性并桥接 NFT 实用程序,而实际无需桥接 NFT。
  • 使用证明:用户可以根据其平台的历史使用情况获得折扣或高级功能(证明用户在 Uniswap 上交易的 X 量)
  • OG证明:用户可以证明他/她拥有超过X天的活跃帐户
  • 链上信用评分:多链信用评分平台可以汇总单个用户的多个账户的数据,以生成信用评分

上述所有证据都可用来为用户提供定制化的体验。Dapp 可以提供折扣或特权来留住有经验的交易者或用户,并为新手用户提供精简的用户体验。

Defi:

  • 跨链借贷:用户可以锁定A链上的资产,然后在B链上贷款,而不用桥接代币
  • 链上保险:可以通过访问历史链上数据来确定故障,保费可以完全在链上结算。
  • 池中资产价格的 TWAP:应用程序可以计算并获取 AMM 池中资产在指定时间段内的平均价格。例如, Uniswap TWAP Oracle 与 Axiom
  • 期权定价:链上期权协议可以利用去中心化交易所过去 n 个区块中资产的波动性对期权进行定价。

最后两个用例将要求每次将新区块添加到源链时更新证明。

中间件:

  • Intents:存储证明将使用户能够更加清晰地表达自己的意图。虽然解答器的工作是执行必要的步骤来满足用户的意图,但用户可以根据链上数据和参数更清楚地指定条件。解答器还可以证明链上数据的有效性,以找到最佳解决方案。
  • 账户抽象:用户可以依赖来自其他链的数据,使用存储证明通过账户抽象来设置规则。例如,每个钱包都有一个随机数。我们可以证明,一年前,nonce是一个特定的数字,而现在的nonce是相同的。这可以用来证明这个钱包根本没有被使用过,然后可以将对钱包的访问权限委托给另一个钱包。
  • 链上自动化:智能合约可以根据依赖于链上数据的预定义条件自动执行某些操作。自动化程序需要以一定的时间间隔调用智能合约,以维持 AMM 的最佳价格流或通过避免坏账来保持贷款协议的健康。 Hyper Oracle 支持自动化以及对链上数据的访问。

基础设施

  • 无需信任的链上预言机:去中心化的预言机网络聚合来自预言机网络内众多单独预言机节点的回应。 预言机网络可以消除这种冗余并利用链上数据的加密安全性。预言机网络可以将来自多个链(L1、L2 和替代 L1)的数据提取到单个链上,并使用其他地方的存储证明简单地证明存在性。极具吸引力的 DeFi 解决方案也可以适用于定制解决方案。例如,最大的流动性质押提供商 Lido Finance 与 Nil Foundation 合作,资助 zkOracle 的开发。该解决方案将实现对 EVM 历史数据的去信任的数据访问,并确保 Lido Finance 质押的以太坊流动性达到 15B 美元。
  • AMP 协议:现有的 AMP 解决方案可以通过与存储证明服务提供商合作来提高消息的表达度。这是Lagrange在其模块化论文文章中建议的方法。

结语

意识使科技公司能够更好地服务客户。从用户身份到购买行为再到社交图谱,科技公司利用意识来开启精准定位、客户细分和病毒式营销等功能。传统科技公司需要获得用户的明确许可,并且在管理用户数据时必须小心谨慎。然而,非许可的区块链上的所有用户数据都是公开的,不一定会泄露用户身份。智能合约应该能够利用公开的数据来更好地服务用户。随着更专业的生态系统的开发和采用,将愈发需要解决跨时间和区块链的状态意问题。存储证明可以使以太坊成为身份和资产所有权层以及结算层。用户可以在以太坊上维护自己的身份和重要资产,这些资产可以在多个区块链上使用,而无需一直桥接资产。我们将持续期待在未来将解锁的新可能性和用例。

声明:

  1. 本文转载自[medium],著作权归属原作者[LongHash Ventures],如对转载有异议,请联系Gate Learn团队,团队会根据相关流程尽速处理。
  2. 免责声明:本文所表达的观点和意见仅代表作者个人观点,不构成任何投资建议。
  3. 文章其他语言版本由Gate Learn团队翻译, 在未提及Gate.io的情况下不得复制、传播或抄袭经翻译文章。
learn.articles.start.now
learn.articles.start.now.voucher
learn.articles.create.account