{"content":{"title":"ethers-rs 后继者  Alloy 发布","body":">- 原文链接：https://www.paradigm.xyz/2024/06/alloy-release\r\n>- 译者：[AI翻译官](https://learnblockchain.cn/people/19584)\r\n>- 本文永久链接：[learnblockchain.cn/article…](https://learnblockchain.cn/article/8451)\r\n    \r\n\r\nAlloy 到目前为止的故事\r\n----------------\r\n\r\n一年前，我们[宣布](https://www.paradigm.xyz/2023/06/alloy#what-does-alloy-include)了 Alloy，我们对与 EVM 区块链交互的低级构建模块进行了全面重写，从 RPC 类型到 ABI 编码器和原始类型。\r\n\r\n今天，我们[发布了 Alloy 0.1](https://github.com/alloy-rs/alloy/releases)（[crates](https://crates.io/crates/alloy)），这是 Alloy 项目的第一个版本，包括与基于 EVM 的区块链交互所需的所有实用工具。此版本包括多个 API 改进和新功能，我们很高兴终于能与用户分享这些内容。作为此版本的一部分，我们还正式[停止维护 ethers-rs](https://github.com/gakonst/ethers-rs/issues/2667)，并鼓励大家迁移到 [Alloy](https://www.paradigm.xyz/2024/06/alloy.rs)。\r\n\r\n虽然我们现在才发布 Alloy 作为[包含所有 JSON-RPC 功能的顶级包](https://www.paradigm.xyz/2024/06/github.com/alloy-rs/alloy) ，但 [Alloy Core](https://github.com/alloy-rs/core/releases) 内部的低级类型和 ABI 编码器包已经发布了几个月，其中许多已经有[超过 100 万次下载](https://crates.io/search?q=alloy&sort=downloads) ！\r\n\r\n为了帮助用户快速上手 Alloy，我们发布了 [Alloy Book](https://alloy.rs/)（包括 ethers 到 alloy 的[迁移指南](https://alloy.rs/migrating-from-ethers/reference.html) ），[Alloy](https://alloy-rs.github.io/alloy/) 和 [Alloy Core](https://docs.rs/alloy-core/latest/alloy_core/) 文档，以及[大量示例](https://github.com/alloy-rs/examples) ，展示了使用 Alloy 的各种方式。\r\n\r\nAlloy [已经](https://sourcegraph.com/search?q=context:global+file:Cargo.toml+alloy+-repo:alloy-rs+-repo:foundry-rs+-repo:paradigmxyz&patternType=standard&sm=1&groupBy=repo)集成到许多 Rust 代码库中，以及我们正在开发的所有项目中：[Revm](https://github.com/bluealloy/revm/)、[Foundry](https://github.com/foundry-rs/foundry/) 和 [Reth](https://github.com/paradigmxyz/reth/)。我们自己已经在生产环境中使用了几个月，我们很高兴它能成为 Rust 以太坊生态系统的高性能和稳定基础，正如我们在[最初的公告](https://www.paradigm.xyz/2023/06/alloy#what-does-alloy-include)中所设想的那样。\r\n\r\n说到这里，让我们深入了解一下！\r\n\r\nAlloy 的亮点是什么？\r\n---------------------------------------------\r\n\r\nAlloy 从底层开始编写，旨在高性能、安全使用和直观。我们从 4 年的 ethers-rs 开发中汲取了经验，并将其全部投入到设计一个与 EVM 区块链交互的优秀客户端库中。\r\n\r\n这花费了很多时间，自我们宣布 Alloy 项目以来已经过去了一年，但我们为这个结果感到自豪。\r\n\r\n今天我们很高兴揭示一些由我们的核心团队与 [James Prestwich](https://twitter.com/_prestwich) 共同架构和开发的令人兴奋的新功能，他在过去一年中与我们一起维护 Alloy。特别感谢 James 推动我们超越 ethers-rs 之前的限制，并为今天发布的成功交付提供了核心输入。\r\n\r\n重新设计的 Provider Middleware 架构\r\n-----------------------------------------\r\n\r\nRPC 客户端库中最重要的抽象是 Provider，它让你可以与网络交互。用户通常希望扩展基本的提供者操作：不同的 gas 估算、gas 升级、替代签名管道等。你希望以模块化的方式来实现这一点，从而使开发人员能够扩展核心库的行为，而不是修改它。\r\n\r\n在 ethers-rs 中，我们将 [Middleware](https://docs.rs/ethers/latest/ethers/middleware/trait.Middleware.html) 定义为修改 RPC 客户端行为的一站式解决方案。如果你想要管理 nonce，它是一个中间件。Gas 升级，它是一个中间件。签名交易？中间件。Flashbots 捆绑？中间件。这种方法有效，因为它给了我们很多灵活性，可以根据需要覆盖内容，但它也太容易出错，并且开发者体验不佳（例如，当 Middleware trait 所需的函数没有意义时，期望开发者 `panic`）。\r\n\r\nAlloy 从头开始重新设计了这种抽象。我们将 Middleware 分为 3 个可覆盖的抽象：\r\n\r\n*   **传输层：** [Transport](https://alloy-rs.github.io/alloy/alloy/transports/trait.Transport.html) 是将数据传输到节点的“线”。它现在实现了 [Tower 的服务层](https://github.com/tower-rs/tower)，允许访问 [Tower 生态系统](https://github.com/tower-rs/tower/blob/master/guides/building-a-middleware-from-scratch.md) 的常见中间件，如请求重试、速率限制等。\r\n*   **提供者层：** 模仿 Tower 的层，这允许覆盖各种 Provider 功能，例如，如果你想劫持 `get_storage_at` 方法，你需要实现一个 `[ProviderLayer](https://alloy-rs.github.io/alloy/alloy/providers/trait.ProviderLayer.html)`。\r\n*   **填充器(Fillers)：** 这可能是最令人兴奋的抽象，填充器处理交易生命周期的所有内容。用户通常提交部分填充的交易，提供者负责找出缺失的数据并填充它们。填充器可以独立于顺序安装，解决了 ethers-rs 的一个主要问题。我们提供了 `.with_recommended_fillers()` 方法，通过多个 `[JoinFill](https://alloy-rs.github.io/alloy/alloy/providers/fillers/struct.JoinFill.html)` ProviderLayers 聚合常用的填充器，方便使用：\r\n    *   `[Wallet Filler](https://alloy-rs.github.io/alloy/alloy/providers/fillers/struct.WalletFiller.html)`：使用[广泛套件](https://alloy-rs.github.io/alloy/alloy/signers/index.html)中的凭证签署交易：从十六进制字符串解析的本地私钥、12/24 字助记词、密钥库文件、硬件钱包如 Trezor 或 Ledger，甚至是生产化的密钥管理系统如 YubiHSM、AWS KMS 或 GCP KMS。\r\n    *   `[Nonce Filler](https://alloy-rs.github.io/alloy/alloy/providers/fillers/struct.NonceFiller.html)`：自动管理所有账户的 nonce。\r\n    *   `[Gas Filler](https://alloy-rs.github.io/alloy/alloy/providers/fillers/struct.GasFiller.html)`：处理每笔交易的 gas 价格和 gas 限制的计算。\r\n    *   `[ChainId Filler](https://alloy-rs.github.io/alloy/alloy/providers/fillers/struct.ChainIdFiller.html)`：根据连接的链将正确的链 ID 嵌入交易中。将所有内容整合在一起，我们拥有的功能堆栈如下所示：\r\n\r\n![Image 1](https://img.learnblockchain.cn/attachments/migrate/1719066322576)\r\n\r\n这个堆栈通过 [ProviderBuilder](https://alloy-rs.github.io/alloy/alloy/providers/struct.ProviderBuilder.html) 捆绑并暴露给用户，它有一个非常符合人体工程学的 API：\r\n\r\n```\r\n// 从随机私钥创建一个签名者。\r\nlet signer = PrivateKeySigner::random();\r\n\r\nlet provider = ProviderBuilder::new()\r\n   // 配置所有填充器\r\n  .with_recommended_fillers()\r\n   // 设置签名者，允许配置多个签名者，这些签名者将根据你的交易的`from`字段进行选择。\r\n  .wallet(EthereumWallet::from(signer))\r\n  // 连接到链\r\n  // 也可以使用`.on_http`、`.on_ws`或`.on_ipc`来避免动态调度\r\n  // 也可以使用`.on_anvil`进行本地测试\r\n  // 也可以使用`.on_client`来配置认证选项，例如 bearer 认证。\r\n  .on_builtin(\"ws://localhost:8545\")\r\n  .await?;\r\n\r\nlet tx = TransactionRequest::new().with_to(...).with_value(...);\r\nlet receipt = provider.send_transaction(tx).await?.get_receipt().await?;\r\n// 使用收据做一些事情\r\n```\r\n\r\n哦，我们还确保了 Provider 和 Signers 是对象安全的，以便通过`Box`它们更容易避免代码中的泛型。有关如何使用 providers 的更多信息，请参阅[书籍](https://alloy.rs/building-with-alloy/connecting-to-a-blockchain/setting-up-a-provider.html) 。\r\n\r\nRPC 类型抽象\r\n---------------------\r\n\r\n世界正在走向多链，这意味着 RPC 类型的差异更多！这是 ethers-rs 中最痛苦的事情之一，我们通过[一个特性标志](https://github.com/gakonst/ethers-rs/blob/34ed9e372e66235aed7074bc3f5c14922b139242/ethers-core/src/types/transaction/request.rs#L63-L81)支持例如 Celo 相关字段。这意味着如果你想要对 Celo 和 Ethereum 进行类型安全的连接，你必须在两次导入库之间进行选择，或者期望 Celo 字段在所有 Ethereum 情况下都为 None。这是我们要解决的问题。\r\n\r\n在 Alloy 中，我们定义了`[Network](https://alloy-rs.github.io/alloy/alloy/network/trait.Network.html)`特性，它定义了每个网络的所有 RPC 请求和响应的“形状”，其中每种类型必须实现某些特性，例如`[Eip2718Envelope](https://alloy-rs.github.io/alloy/alloy/network/eip2718/trait.Eip2718Envelope.html)`、`[TxReceipt](https://alloy-rs.github.io/alloy/alloy/consensus/trait.TxReceipt.html)`、`[TransactionBuilder](https://alloy-rs.github.io/alloy/alloy/network/trait.TransactionBuilder.html)`，总结如下：\r\n\r\n```\r\npub trait Network {\r\n    /// 网络交易类型枚举。\r\n    type TxType\r\n    /// 网络交易信封类型。\r\n    type TxEnvelope: Eip2718Envelope + Debug;\r\n    /// 各种交易类型的枚举。\r\n    type UnsignedTx: From<Self::TxEnvelope>;\r\n    /// 网络收据信封类型。\r\n    type ReceiptEnvelope: Eip2718Envelope + TxReceipt;\r\n    /// 网络头类型。\r\n    type Header;\r\n    /// 交易请求的 JSON 主体。\r\n    type TransactionRequest: RpcObject + TransactionBuilder<Self> + Debug + From<Self::TxEnvelope> + From<Self::UnsignedTx>;\r\n    /// 交易响应的 JSON 主体。\r\n    type TransactionResponse: RpcObject + TransactionResponse;\r\n    /// 交易收据的 JSON 主体。\r\n    type ReceiptResponse: RpcObject + ReceiptResponse;\r\n    /// 头响应的 JSON 主体。\r\n    type HeaderResponse: RpcObject;\r\n}\r\n```\r\n\r\n这使我们可以在没有任何特性标志的情况下导入库，并且根据我们指定的网络，我们会得到不同的类型抽象。这太棒了！类型安全，没有冗余开销！这也是我们在 [Reth](https://github.com/paradigmxyz/reth/issues/7680) 中采用的方法，允许任何开发人员在服务器端构建具有自定义 RPC 类型的链，例如具有本地账户抽象的网络。\r\n\r\n我们提供了两个网络实现`[Ethereum](https://alloy-rs.github.io/alloy/alloy/network/struct.Ethereum.html)`和`[AnyNetwork](https://alloy-rs.github.io/alloy/alloy/network/struct.AnyNetwork.html)`。Ethereum 包含你熟知和喜爱的所有类型。然而，`AnyNetwork`将每个 RPC 类型包装在`[WithOtherFields<T>](https://alloy-rs.github.io/alloy/alloy/rpc/types/struct.WithOtherFields.html)`类型中，该类型充当任何不匹配 Ethereum 结构的 RPC 响应字段的捕获。\r\n\r\n开发人员可以使用`[.network::()](https://alloy-rs.github.io/alloy/alloy/providers/struct.ProviderBuilder.html#method.network)`方法在`[ProviderBuilder](https://alloy-rs.github.io/alloy/alloy/providers/struct.ProviderBuilder.html)`上选择他们的`Network`实现。这使我们能够以一种有原则的方式支持比 Ethereum 更多的网络，而不会增加核心维护过程的负担。你只需实现网络特性及其所有关联类型，在代码中导入它，你就完成了！\r\n\r\n关注我们在[op-alloy](https://github.com/alloy-rs/op-alloy/) crate 中定义`[OpStackNetwork](https://github.com/alloy-rs/op-alloy/issues/10)`的工作，如果你想实现自己的网络，请联系我们！\r\n\r\nsol! 宏\r\n--------------\r\n\r\n我们在[初始帖子](https://www.paradigm.xyz/2023/06/alloy#what-does-alloy-include)中首次谈到了 sol 宏。它是我们之前`[abigen](https://docs.rs/ethers/latest/ethers/contract/macro.abigen.html)`宏的重构，用于生成与合约 ABI 的类型安全绑定。sol 宏不是编译器，但它是 Rust 中 Solidity 类型系统的完整表示，这意味着你只需粘贴 Solidity 代码，它就会为其生成绑定，甚至支持自定义类型！\r\n\r\nsol 宏还通过`#[sol(rpc)]`属性生成 JSON RPC 绑定。如果你传递`#[sol(bytecode = \"...\")]`属性，还会生成一个部署方法。例如，下面的代码将生成一个`Counter::deploy`函数以及一个`Counter::increment(&self)`方法，你可以用它来增加计数器。\r\n\r\n```\r\nsol! {\r\n    // solc v0.8.26; solc a.sol --via-ir --optimize --bin\r\n    #[sol(rpc, bytecode=\"608080...\")]\r\n    contract Counter {\r\n        uint256 public number;\r\n\r\n        function increment() public {\r\n            number++;\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n要了解有关 sol 宏的更多信息，请查看[书籍页面](https://alloy.rs/highlights/the-sol!-procedural-macro.html)及其[详细文档](https://docs.rs/alloy-core/latest/alloy_core/sol_types/macro.sol.html) 。与智能合约交互类似于 ethers-rs（注意，不再有`Arc`！），在获取交易收据的 API 中有一些底层变化。\r\n\r\n```\r\nlet provider = ProviderBuilder::new().on_builtin(\"...\").await?;\r\n\r\n// 部署合约。\r\nlet contract = Counter::deploy(&provider).await?;\r\nprintln!(\"Deployed contract at address: {}\", contract.address());\r\n\r\nlet receipt = contract.setNumber(U256::from(42)).send().await?.get_receipt().await?;\r\nprintln!(\"Receipt: {receipt}\");\r\n\r\n// 将数字增加到 43（无需等待收据）\r\nlet tx_hash = contract.increment().send().await?.watch().await?;\r\nprintln!(\"Incremented number: {tx_hash}\");\r\n\r\n// 检索数字，应该是 43。\r\nlet number = contract.number().await?.number.to_string();\r\nprintln!(\"Retrieved number: {number}\");\r\n```\r\n\r\nsol 宏的功能也与 Foundry 集成在一起，用于生成所有客户端集成的类型安全绑定。请查看更新的 Foundry Rust 模板，如果你对此感兴趣的话！\r\n\r\n广泛的文档和测试\r\n-----------------\r\n\r\n我们希望用户能够通过高级教程和示例来使用该项目，作为一个库。为此，我们提供了大量的文档：\r\n\r\n*   [Alloy 文档](https://alloy-rs.github.io/alloy/): Alloy 仓库中每个函数的 Rustdoc 文档。\r\n*   [Alloy Core 文档](https://docs.rs/alloy-core): Alloy Core 仓库中每个函数的 Rustdoc 文档。\r\n*   [Alloy 示例](https://github.com/alloy-rs/examples): 关于如何在日常中使用 Alloy 的各种代码示例。\r\n*   [Alloy 之书](https://alloy.rs/): 关于 Alloy 的教程和长篇文章。\r\n\r\n让文档变得优秀是我们的首要任务，请在书籍上提出更多你想看到的教程。\r\n\r\nAlloy 的下一步是什么？\r\n-----------------------\r\n\r\n今天的 0.1 版本发布标志着 [Alloy](https://alloy.rs/) 在功能上与 ethers-rs 相当甚至超越，同时也具有高性能、经过充分测试和良好文档记录。我们认为 Alloy 是高级用户的首选工具，但它也足够简单和直观，任何人都可以使用。\r\n\r\n我们的下一个优先事项是 1.0 版本，这意味着我们将打磨我们的 API 并努力实现适当的稳定性。虽然我们不提供任何正式的稳定性保证，但大多数 API 已经成熟，我们不预计会有大的变化。\r\n\r\n为了实现 Alloy 的长期成功，我们正在寻找一名全职的高级工程师加入 Alloy 团队，帮助推动项目的日常工作，并帮助我们扩大贡献者基础。如果上述内容对你有吸引力，请联系 [georgios@paradigm.xyz](mailto:georgios@paradigm.xyz)。\r\n\r\n我们很高兴每个 ethers-rs 用户都能将他们的代码迁移到 Alloy，并用它构建新的服务！请阅读 [alloy-core](https://docs.rs/alloy-core) 和 [alloy](https://alloy-rs.github.io/alloy/) 的文档、[示例](https://github.com/alloy-rs/examples/) 和 [书籍](https://alloy.rs/)！\r\n\r\n在那之前，Github 上见！\r\n\r\n免责声明：本文仅供一般信息用途。它不构成投资建议或购买或出售任何投资的推荐或招揽，也不应在评估任何投资决策的优点时使用。它不应被依赖于会计、法律或税务建议或投资建议。本文反映了作者的当前意见，并非代表 Paradigm 或其附属机构的意见，也不一定反映 Paradigm、其附属机构或与 Paradigm 相关的个人的意见。本文所反映的意见如有变更，恕不另行通知。\r\n\r\n> 本文由 AI 翻译，欢迎小伙伴们来[校对](https://github.com/lbc-team/Pioneer/blob/master/translations/8451.md)。"},"author":{"user":"https://learnblockchain.cn/people/21017","address":null},"history":null,"timestamp":1719067106,"version":1}