ZKStack 跨链架构内幕 — 第一部分:Merkle 树层级结构的深度解析

本文是 ZKStack 协议升级技术结构的探索系列的第一部分,重点介绍了构成 ZKChain 生态系统中安全跨链通信骨干的三个关键 Merkle 树实现:L2ToL1LogsTree、ChainTree 和 SharedTree,并详细解释了它们的构成、大小以及根的用途。

目录

简介

这个分为两个部分的文章,探讨了即将到来的 ZKStack 协议升级的技术结构,该升级引入了一个 ZKChain 生态系统,该生态系统可以通过在另一个 ZKChain 而不是 L1 上进行结算,从而轻松创建新的 rollup ZKChain,内置跨链功能并降低结算成本。

第一部分描述了三个关键的 Merkle 树实现,它们构成了 ZKChain 生态系统中安全跨层通信的支柱,即 L2ToL1LogsTreeChainTreeSharedTree

第二部分说明了这种树层次结构的最重要的用例,即 ZKChain 在另一个 ZKChain 而不是直接在 L1 上进行结算,方法是为其跨链代币转账构建递归证明。

这个分为两个部分的文章描述了撰写本文时 ZKChain 生态系统的当前状态及其内部流程。 随着生态系统的发展,某些描述的功能将来可能会更新。


第一部分:树的形状

让我们深入了解这些支持生态系统的关键树数据结构的细节。 对于每棵树,我们系统地探讨它的:

  • 叶子:构成树的内容
  • 大小:它有多大以及如何生长
  • :根如何使用以及它位于何处。

有用的术语

  • ZKChains:生态系统中的任何 rollup 链都被视为 ZKChain。 ZKChain 可以在 L1(以太坊网络)或另一个 ZKChain 上进行结算。 仅在本系列的下一部分中,我们将考虑一个 ZKChain 在另一个特殊的 ZKChain 而不是 L1 上进行结算。
  • 结算层:ZKChain 提交、验证和最终确定批次的网络。 对于某些链,这是以太坊 (L1),而对于其他链,结算层可能是另一个 ZKChain。 目前,唯一被列为结算层白名单的 ZKChain 是 Gateway ZKChain。 将在本系列的下一部分中进一步探讨 Gateway 链。
  • 批次:ZKChain 的批次包含来自一个或多个 L2 区块的链交易,以及在这些区块内生成的任何其他信息,这些信息是重建结算层上 ZKChain 状态所必需的。
  • DiamondProxy:ZKsync 生态系统中每个 ZKChain 使用的一组智能合约,可实现结算并允许升级,同时保留存储布局。 ZKChain 的状态(例如,批次的 merkle 根)保留在其结算层上的 DiamondProxy 中。

在第一部分中,我们从相对于其结算层的通用角度描述树。 在这里,我们使用 L2 来指代通用的 ZKChain,而 L1 指代其结算层。


L2ToL1LogsTree

这棵树由每个已提交批次从 L2 到 L1 的所有已启动的跨链交易组成。 因此,每个批次都有自己的 L2ToL1LogsTree。 它构建在每个 L2 链上,其中包含 L2 交易产生的日志,L1 应该收到通知。 无论 ZKChain 是在 L1 上还是在另一个 ZKChain 上结算,或者它本身是否是结算层,L2ToL1LogsTree 对于所有 ZKChain 的构建方式都相同。

img1-2

叶子:L2ToL1Log

L2ToL1Log 叶由来自每个批次的 L2 交易的消息或日志组成,包括但不限于:

  • L1-to-L2 TX 执行状态: 当 L1-to-L2 交易成功或失败时,会记录日志。 如果失败,这些日志可以帮助用户恢复失败的 L1-to-L2 代币转账。
  • L2-to-L1 代币提款: 当启动 L2-to-L1 提款时,会创建一个日志,例如提款原生代币。 这也适用于从 L2AssetRouterL2LegacyBridge 提款。 这些日志有助于在 L1 上完成提款,以完成 L2-to-L1 代币桥接。
  • 协议升级: 当 L2 合约进行协议升级时,日志有助于更新 L1 链存储变量,确保升级得到反映。
  • 字节码发布: 新部署的合约的压缩未压缩字节码使用 L2ToL1Logs 发布在 L1 上。 这有助于在从 L1 上发布的状态差异重建 L2 状态时实现数据可用性。

通常,不需要 L1 通信的常规 L2 交易不包括在 L2ToL1Logs 中。 相反,L2 状态差异会发布在 L1 上,以确保数据可用性。

大小:16_384

这棵树的 固定大小为 2^14 个叶子,这使得它非常大,高度为 14 层。 但是,它可能非常稀疏,这意味着有很多空叶子。 在这种情况下,它的构造需要用默认值填充所有内容,表示一个空叶子。 因此,这棵树有足够的空间供未来高吞吐量链使用。

根:LocalLogsRootHash

通过以通常的方式哈希 L2ToL1LogsTree merkle 树,可以得到局部根,称为 LocalLogsRootHash,由 16_384 个叶子构成。

请注意,正如本系列的下一部分将解释的那样,这不是在发布批次时提交到结算层的根。 为了获得批次的根,LocalLogsRootHash 进一步与 sharedTree 的根在右侧连接,以生成 fullRootHash。 (sharedTree 的面纱很快就会在下面揭开。)


ChainTree

当创建一个新的 ZKChain 时,它的 ChainTree 在 L1 上的 MessageRoot 合约以及 ZKChain 的结算层(如果它与 L1 不同)中启动。 每个 ZKChain 都有自己的 ChainTree

尽管 MessageRoot 合约在所有 L2 ZKChain 的创世时都被强制部署,但只有结算层具有非平凡的 ChainTree(以及 SharedTree,我们稍后会看到)。 与 L2toL1LogsTree 相比,链的 ChainTree 不存在于它自己的链上,而是位于其结算层的 MessageRoot 合约中。

通常,结算层负责跟踪每个在其上结算的 ZKChain 的最新 ChainTree。 其目的是将有关成功结算的批次的所有信息提交到单个根哈希中。

img2-2

叶子:chainBatchRoot

当来自此 ZKChain 的新批次在结算层结算时,ZKChain 的 ChainTree 会增长一个新的叶子。 因此,这棵树代表了从 L2 到 L1 所有成功执行的批次的记录。 这棵树使用 DynamicIncrementalMerkle.Byte32PushTree 数据结构表示。

叶子的构造方式是,首先在每个批次的已提交根(即 fullRootHash(即 L2toL1LogsTreeSharedTree 的根的串联))前加上 BATCH_LEAF_PADDING,然后在哈希所有内容到适当的 32 字节大小的叶子之前,后缀相应的 batchNumber

大小

与具有固定大小的 L2ToL1LogsTree 不同,ChainTree 是一种动态结构,随着链的结算层上每个新执行的批次而递增地增长。 树的叶子的总数等于已在该层结算的批次数。 但是,如果链已从一个结算层迁移到另一个结算层,则这棵树将拆分。 当链迁移回来时,先前停滞的 ChainTree 将继续增长。 因此,如果发生了迁移,ChainTree 的叶子的索引可能与其批号不对应。

动态性质使其能够有效地适应链的实际吞吐量,而无需预先确定的空间分配。

根:chainRoot

通过以通常的方式哈希 ChainTree 叶子,可以得到 chainRoot。 对于每个结算 ZKChain,每当执行一个新批次时,都会更新此根,并立即用于更新 SharedTree 的相应叶子。


SharedTree

SharedTree 中的每个叶子都对应于结算 ZKChain 的 ChainTree 根。 SharedTree 位于 MessageRoot 合约中,这意味着与所有结算 ZKChain 的 ChainTree 所在的合约相同。 请注意,与 ChainTree 类似,尽管所有 ZKChain 共享相同的设计并具有 SharedTree,但只有结算层的 SharedTree 是非平凡的。 不作为结算层的 ZKChain 将仅公开一个表示默认 SharedTree 的根。

SharedTree 的目的是将包含在所有结算 ZKChain 的 ChainTree 中的所有批次信息提交到单个根哈希中。

img3-2

叶子:chainRoot

当一个新的 ZKChain 第一次添加到该层或是迁移到该层时,结算层的 SharedTree 会增长一个新的叶子。 每个叶子对应于一条链。 这棵树使用 FullMerkle.FullTree 数据结构表示,在存储中保留所有叶子和节点值。

每个叶子由其 ChainId 对 chainRoot 的填充版本进行哈希 形成,称为 ChainIdLeaf。 每次 ZKChain 的 ChainTree 根更新时(即,每当结算一个批次时),SharedTree 中相应的叶子也会更新。

大小

除非添加一个新的 ZKChain,否则 SharedTree 的大小不会增长。 随着每个新批次的结算,ShareTree 保持其大小,但更新其根。 因此,与 ChainTree 相比,SharedTree 的预期大小较小,并且上限为 100。 请注意,在非结算层中,SharedTree 本质上是空的。

根:aggregatedRoot

对任何结算 ChainTree 的每次更新都会触发对 aggregatedRoot 的相应更新。 在不是结算层的 ZKChain 上,aggregatedRoot 始终是以其自己的 chainId初始化的默认哈希。 但是,在列入白名单的结算层上,这是对结算在那里的所有 ZKChain 的整个交易历史的承诺。


结论

这三棵 Merkle 树共同构成了一个复杂的密码学架构,可确保 ZKChain 与其结算层之间的安全、可验证的通信。

在第二部分中,我们将探讨这种分层结构的最重要应用,即当 ZKChain 在另一个 ZKChain 上结算时,即所谓的 Gateway 链,这是目前唯一列入白名单的结算层。 我们将说明如何为跨链代币转账的具体用例构建递归证明。

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

0 条评论

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