{"content":{"title":"引介 shadow-reth - 通过扩展执行层节点，极大方便链上数据索引","body":">- 原文链接：[blog.shadow.xyz/shadow-reth](https://blog.shadow.xyz/shadow-reth/)\r\n>- 译者：[AI翻译官](https://learnblockchain.cn/people/19584)，校对：[翻译小组](https://learnblockchain.cn/people/412)\r\n>- 本文链接：[learnblockchain.cn/article…](https://learnblockchain.cn/article/10593)\r\n    \r\n5 月，我们发布了 [shadow-reth](https://github.com/shadow-hq/shadow-reth?ref=blog.shadow.xyz) – 一个基于 Reth 的开源影子节点。\r\n\r\nshadow-reth 包含了一系列 [Reth](https://github.com/paradigmxyz/reth?ref=blog.shadow.xyz) 的修改，允许你通过 [Execution Extensions](https://www.paradigm.xyz/2024/05/reth-exex?ref=blog.shadow.xyz) 生成影子事件，并通过自定义 RPC 扩展轻松检索它们。\r\n\r\n## 为什么选择影子事件？\r\n\r\n影子事件是一种强大的新原语，用于生成区块链数据，使开发者在处理来自智能合约的链上数据时拥有更大的自由度和灵活性。\r\n\r\n影子事件带来了明显的好处：\r\n\r\n1.  **更深入的数据覆盖**：通过访问以前无法访问（或很难访问）的链上数据，生成全新的事件，适用于任何智能合约。\r\n2.  **简化数据管道**：通过直接在智能合约中编写转换逻辑，极大减少数据管道的复杂性。\r\n3.  **更快的迭代周期**：使用你已熟悉的工具快速测试、验证和迭代影子事件。\r\n4.  **无权限、无 gas 记录**：在任何你想要的合约上，无权限添加尽可能多的事件，不会增加最终用户的 gas 负担。\r\n\r\n## 为什么选择 shadow-reth？\r\n\r\n我们的 [托管平台](https://www.shadow.xyz/?ref=blog.shadow.xyz) 将强大的功能打包成一系列易于使用的特性，使单个开发者能够在几分钟内编写高级数据管道，而无需复杂的 ETL 管道或额外的离线基础设施。\r\n\r\n然而，完全托管的平台存在信任无关性的权衡。尽管影子分叉不会以公共区块链的方式持有用户资金，但它们确实管理数据——而数据是非常有价值的。\r\n\r\n我们相信，任何人都应该能够以去中心化和自托管的方式生成影子事件，并验证托管影子分叉生成的数据是否符合其影子合约实现的预期——就像任何人都可以通过自托管自己的主网节点来验证他们从托管主网 RPC 提供者获取的数据一样。\r\n\r\n为此，我们发布了 [shadow-reth](https://github.com/shadow-hq/shadow-reth?ref=blog.shadow.xyz)：一个基于 Reth 的开源影子节点，采用 Apache 2.0 和 MIT 许可证。\r\n\r\n[Reth 执行扩展](https://www.paradigm.xyz/2024/05/reth-exex?ref=blog.shadow.xyz) 引入了一种构建可定制、高效节点的框架。简而言之，执行扩展 (ExExes) 是构建 Reth 之上的离线基础设施的后执行Hook。\r\n\r\nshadow-reth 利用 Reth ExExes 提供影子节点的开源实现，允许任何人生成影子事件并通过 JSON-RPC 检索它们。重要的是，这一切都可以在单一的 Reth 节点内运行，无需额外的离线基础设施或维护经过大量修改的客户端分叉。\r\n\r\n这使得影子事件的好处对所有人可及，并随着其使用的普及，增加了信任无关性和可验证性。\r\n\r\n接下来，让我们深入了解 shadow-reth 是如何构建的。\r\n\r\n## 工作原理\r\n\r\n在高层次上，shadow-reth 有三个主要组件：\r\n\r\n1.  执行扩展：`ShadowExEx` 从规范链重放交易，使用提供的影子字节码覆盖配置。此重放生成影子日志并将其写入索引 (SQLite)。\r\n2.  RPC：自定义影子 JSON-RPC 端点 (`shadow_getLogs`)，从索引中获取影子日志。\r\n3.  影子配置：影子分叉配置 (`shadow.json`)。这包含合约地址到影子合约字节码的映射。\r\n\r\n### 执行扩展\r\n\r\n当 Reth 节点内发生某些事件时——例如区块被提交到链、重组和状态回退——Reth 的 `ExExManager` 会发出相应的 `ExExNotification`，允许 ExEx Hook 链状态并在事件被发现时执行任意代码。这些通知使我们能够访问节点的状态、已提交链以及其他有用的上下文信息。\r\n\r\n通过后执行Hook，我们实现了一个影子节点，能够以影子合约覆盖重新执行规范链，允许发出自定义的影子事件。我们通过执行扩展 `ShadowExEx` 来完成这一点，它监听 `ExExNotification::ChainCommitted` 事件，并利用提供的状态构造一个 `ShadowDatabase<DB: revm::Database>`。该数据库实现封装了由通知的只读数据库提供者构建的 `HistoricalStateProviderRef`，并用来自 `shadow.json` 的提供的覆盖替换合约字节码。\r\n\r\n使用我们的 `ShadowDatabase`，我们能够使用 `ShadowExecutor` 重新执行已提交的链；一个简单的区块执行器，能够用重写字节码来执行区块。我们使用这个自定义执行器而不是 Reth 的 `BatchExecutor`，因为修改和执行自定义合约字节码会导致 gas 和状态根问题，从而导致执行器失败。另一方面，`ShadowExecutor` 不执行状态验证，而是使用 `revm::Evm::transact_preverified()` 来用影子字节码执行区块并将其状态提交到 `ShadowDatabase`。从已执行区块的 `ResultAndState` 中，我们能够获取区块内发出的影子事件并将其保存到 SQLite。\r\n\r\n此外，`ShadowExEx` 还监听 `ChainReverted` 通知，以便根据 [以太坊 JSON-RPC 规范](https://ethereum.org/en/developers/docs/apis/json-rpc/?ref=blog.shadow.xyz#eth_getlogs) 将重组的影子事件标记为 `removed`。\r\n\r\n_注意：尽管还有许多其他可扩展的数据库引擎，我们选择在这个初始实现中使用 SQLite，因为它在大多数系统上开箱即用，不需要额外安装，并且可以在单台机器上运行。我们希望 shadow-reth 支持多种数据目的地，如 Postgres，用户可以选择。_\r\n\r\n### 自定义 RPC 端点\r\n\r\nShadow RPC 扩展允许你创建自定义方法的实现，以返回有关索引的影子事件的信息。它主要由 `ShadowRpc` 类型和 `ShadowRpcApi` 特性驱动。\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1736820902310)\r\n\r\n`ShadowRpc` 类型作为数据库管理器和通用区块链提供者的包装器，允许访问链的状态。你可以根据需要更改和扩展这些类型；我们选择使用 SQLite 进行影子事件存储，是因为易于使用和可移植性，但这个类型及其实现可以轻松更改为使用不同的数据库产品，甚至在存储解决方案间保持无关性。\r\n\r\n`ShadowRpcApi` 特性定义了自定义 RPC 扩展的公共接口，应该为 `ShadowRpc` 结构体实现。为了说明该扩展的功能和与影子数据交互的可能性，我们包含了一个 `shadow_getLogs` RPC 调用：这是常用的 `eth_getLogs` RPC 调用的命名空间等效。你可以使用与 `eth_getLogs` 中相同的请求参数检索影子合约的原始日志。\r\n\r\n该接口还可以扩展以实现其他常见 RPC 调用，甚至完全是你影子数据唯一的新调用。`ShadowRpc` 类型上的 `provider` 字段使你能够访问链状态的多个部分，得益于 Reth 广泛的提供者特性集合；只需在自定义 RPC 调用的实现中包含必要的特性，你就能够使用你的 Reth 节点检索关于链的信息。\r\n\r\n### Shadow 配置\r\n\r\n为了方便起见，你可以创建一个免费的 [Shadow 账户](https://app.shadow.xyz/?ref=blog.shadow.xyz)，设置你希望具有自定义影子事件的合约，并下载 `shadow.json` 配置以在你自己的自托管 Reth 节点上运行。\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1736820902725)\r\n\r\n或者，你可以使用任何外部工具生成影子合约字节码，例如 [Foundry](https://github.com/foundry-rs/foundry?ref=blog.shadow.xyz)。未来，我们将发布一个集成，使你可以直接从 CLI 轻松完成这一步。\r\n\r\n## 限制\r\n\r\n由于 shadow-reth 旨在与单个自托管节点一起使用，因此相对于 Shadow 托管平台，有几个重要的功能限制需要注意。\r\n\r\n*   **Gas 限制**：出于数据一致性原因，shadow-reth 在使用 `ShadowExecutor` 重新执行区块时不会覆盖 gas 限制。如果在影子重新执行期间耗尽 gas，交易可能会失败，而且不会为该交易发出任何影子事件。\r\n*   **回填**：shadow-reth 不会回填影子事件。如果你开始在已同步的 Reth 节点上运行 shadow-reth，shadow-reth 仅会为自启动以来处理的区块生成影子事件。如果你需要历史影子事件，你需要从创世区块重新同步你的 Reth 节点。我们正在与 Reth 团队紧密合作以改善这一点。\r\n*   **解码**：shadow-reth 设计上类似于常规节点，不包括事件解码。如果你想解码影子事件，我们建议在单独的进程中轮询 `shadow_getLogs` 终端。\r\n*   **Websockets**：影子事件不会通过 `eth_subscribe` websocket 订阅发布。\r\n\r\n## 接下来是什么？\r\n\r\n我们很高兴能继续让影子事件对所有人可访问和可验证。\r\n\r\n它们带来的好处：无权限无 gas 日志、更深的数据覆盖以及简化的索引管道是难以忽视的。然而，仍然有很多工作要做，以解锁它们向更广泛的加密生态系统承诺的全部潜力和好处。\r\n\r\n未来，我们的目标是实现以下功能：\r\n\r\n*   发现和审查他人编写的影子合约\r\n*   动态选择你想要的确切影子事件\r\n*   在你希望的任何地方存储影子事件数据\r\n\r\n使用 shadow-reth，你将能够在不需要额外的离线基础设施或维护大量修改的客户端分支的情况下完成所有这些。如果你更喜欢不管理自己的节点，你也可以通过我们的托管平台轻松完成所有这些。\r\n\r\nshadow-reth 的代码在 [Github 上免费获取](https://github.com/shadow-hq/shadow-reth?ref=blog.shadow.xyz)，遵循 Apache 2.0 和 MIT 许可证，供任何人无条件使用。我们鼓励社区进行分叉，贡献文档、问题、PR、问题甚至尝试破解它。我们非常期待看到你对此的贡献。\r\n\r\n如果你希望与我们合作推动链上数据的未来，请通过 [gm@shadow.xyz](mailto:gm@shadow.xyz) 与我们联系。\r\n\r\n## 致谢\r\n\r\n没有以下项目的辛勤工作，shadow-reth 将不可能实现：\r\n\r\n*   [Reth](https://github.com/paradigmxyz/reth?ref=blog.shadow.xyz)：shadow-reth 的基础，专注于用户友好、高度模块化，并且快速高效的以太坊归档节点实现。\r\n*   [Revm](https://github.com/bluealloy/revm?ref=blog.shadow.xyz)：Revm 是用 Rust 编写的 EVM，专注于速度和简单性。Revm 是 shadow-reth 的 `ShadowExecutor` 以及 Reth 本身的核心。\r\n\r\n> 我是 [AI 翻译官](https://learnblockchain.cn/people/19584)，为大家转译优秀英文文章，如有翻译不通的地方，在[这里](https://github.com/lbc-team/Pioneer/blob/master/translations/10593.md)修改，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/25251","address":null},"history":"bafkreif5jvo72fr42fbjeunjvrqhmwqsw5bnjwd6oltrftzwgdn53cxn2u","timestamp":1736823864,"version":1}