Chainlink Devenv 实战:在本地与 CI 中一键搭建 Docker 化的临时端到端测试环境

Chainlink Devenv 实战:在本地与 CI 中一键搭建 Docker 化的临时端到端测试环境 Chainlink Devenv 实战在本地与 CI 中一键搭建 Docker 化的临时端到端测试环境【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink导读本文围绕 Chainlink 仓库中的 devenv 环境包 展开介绍如何用 Docker 容器快速搭建一套临时的端到端E2E集成测试环境既能在本地/CI 中拉起私有的模拟以太坊网络与 Chainlink 节点、Job Distributor任务分发器也能让测试直接连接 Sepolia、Avalanche Fuji、BSC Testnet 等现有测试网/主网。读完本文你将掌握两种环境的完整配置流程、全部环境变量清单以及从源码层面理解这套环境的核心组件Chain、DON、JD 客户端、RMN 集群等是如何协同工作的。Devenv 的定位为本地/CI 测试而生根据 devenv README 的说明这个包的核心目标是创建用于本地与 CI 测试的临时ephemeral环境。它会在 Docker 中拉起一组容器里面运行着 Chainlink 节点与一个 Job Distributor并且支持两种连接模式创建新的模拟私有以太坊网络容器Chainlink 节点、Job Distributor 与私链容器位于同一个 Docker 网络内适合本地快速验证连接现有的测试网/主网测试直接复用 Sepolia、Avalanche Fuji、BSC Testnet 等真实网络的 RPC 与钱包密钥。在源码层面这个定位由 environment.go 中的常量与入口函数体现包内定义了环境标识DevEnv devenv并提供NewEnvironment(ctx, lggr, config)来组装链BlockChains与链下客户端OffchainClient最终返回一个cldf.Environment来自chainlink-deployments-framework其中使用内存地址簿NewMemoryAddressBook与密封的内存数据存储NewMemoryDataStore().Seal()完全符合临时环境、用完即弃的定位。使用这套环境创建的测试最终作为端到端集成冒烟测试运行代码位于 integration-tests/smoke其中 CCIP 相关冒烟测试在 integration-tests/smoke/ccip。核心组件与源码结构在深入配置之前先了解 devenv 包在源码上由哪些组件构成。该包目录deployment/environment/devenv包含以下文件文件职责environment.goNewEnvironment入口组装链与链下客户端生成cldf.Environmentchain.goChainConfig结构体与NewChains支持 EVM / Solana / Aptos / Tron 多链族的并发初始化don.goDON、Node、NodeInfo以及节点注册 Job Distributor 的完整流程jd.goJDConfig与JobDistributor客户端对 CLDF JD 客户端的封装rmn.goRMN 相关容器组件RageProxy、AFN2Proxy、RMNClusterrmn_config.goRMN 的 shared/local/proxy 四类配置结构与默认值fast-filler.goCCIP Fast Filler 容器组件与 JSON 配置结构internal/kms/kms_client.goAWS KMS 签名客户端用于在未提供私钥时获取部署者密钥环境配置入口EnvironmentConfig 与 ChainConfigenvironment.go 中定义了顶层配置type EnvironmentConfig struct { Chains []ChainConfig JDConfig JDConfig }Chains一个环境可同时挂接多条链每条链由ChainConfig描述JDConfigJob Distributor 的连接与节点信息。NewEnvironment的执行顺序是先调用NewChains并发创建所有链再通过NewJDClient创建 Job Distributor 客户端并完成节点注册NewRegisteredDON随后为 DON 创建各链的 ChainConfigCreateSupportedChains最后把nodeIDs、链对象、内存地址簿等组装成cldf.Environment返回。chain.go 中ChainConfig的字段如下字段含义ChainID链 ID按 EIP-155 语义ChainName链名称来自 chain-selectors 仓库ChainType链族合法值包括EVM、SOLANA、APTOS、TRON等PreferredURLScheme首选 RPC URL 协议偏好WS 或 HTTPWSRPCs/HTTPRPCs每条链的 WebSocket 与 HTTP RPC 列表内部/外部地址成对见CribRPCsDeployerKey用于在链上部署/配置合约的部署者密钥EVMIsZkSyncVM/ClientZkSyncVM/DeployerKeyZkSyncVMzkSync VM 支持开关与对应客户端/钱包SolDeployerKey/SolArtifactDirSolana 部署者密钥与预构建产物目录Users以普通用户身份与链交互的密钥集合MultiClientOpts配置底层MultiClient的选项函数AptosDeployerKeyAptos 部署者账户ChainConfig还提供了几个实用方法SetUsers(pvtkeys)支持将私钥列表转换为用户 transactor若不提供私钥则回退用部署者密钥当作用户SetDeployerKey(pvtKeyStr)在传入私钥时直接构造部署者未传私钥时则回退到 AWS KMS见下文SetSolDeployerKey/SetAptosDeployerKey分别解析 Base58 的 Solana 私钥与十六进制的 Aptos 私钥。NewChains会为每条链做并行初始化errgroup并借助chainselectors.GetChainDetailsByChainIDAndFamily将 ChainID 解析为 ChainSelectorEVM 链还会构造统一的交易确认函数confirmFn等待交易上链3 分钟超时若收据状态为 0回滚会通过CallContract解码 revert 原因并在日志中给出可读的错误信息。DON 与节点注册流程don.go 是整个环境中最关键的部分它实现了节点与 Job Distributor 的完整对接NodeInfo创建单个节点所需信息包括 Chainlink API 连接配置CLConfig、P2P 端口、是否为 bootstrap 节点、节点名、admin 地址、bootstrap 节点的 multiaddr、注册标签与容器名DON持有[]Node提供PluginNodes()按typeplugin标签过滤、ReplayAllLogs(blockByChain)在各节点上按区块号重放日志、NodeIds()等能力NewRegisteredDON(ctx, nodeInfo, jd)逐个创建节点为 bootstrap 节点设置 multiaddr、为插件节点设置默认 admin 地址并调用SetUpAndLinkJobDistributor完成节点 ↔ JD 的双向打通。节点会以标签label形式在 Job Distributor 中登记身份源码中定义的标签键包括type值为bootstrap或plugin、p2p_id、jobTypello/stream、environment、streamID、product。注册时还会自动附加节点的 P2P PeerID 标签便于后续按 PeerID 查询节点。CreateCCIPOCRSupportedChains会为每个节点按链获取账户地址EVM/TRON 走FetchAccountAddressAPTOS/SOLANA 走FetchKeys、P2P PeerID 与 OCR2 密钥束 ID然后在 JD 中创建 JobDistributorChainConfig其中 OCR2 插件配置为{commit:true,execute:true,median:false,mercury:false}即 CCIP 场景所需的 commit/execute 插件。值得注意的是该方法内置了重试逻辑10 秒窗口、每 3 秒重试因为 Job Distributor 侧更新 chain config 可能静默失败需要二次校验。Job Distributor 客户端封装jd.go 定义了JDConfigtype JDConfig struct { GRPC string WSRPC string Creds credentials.TransportCredentials Auth oauth2.TokenSource NodeInfo []NodeInfo }NewJDClient会基于这些配置创建底层 CLDF JD 客户端并在提供NodeInfo时自动完成 DON 的注册。JobDistributor结构体嵌入了 CLDF 的*jd.JobDistributor并额外持有一个*DON指针——这正是注释中所说的CLDF 的 JD 客户端本身没有 DON 能力因此在这里做包装。包装后还重写了ProposeJob任务提案成功后会自动在目标节点上执行AcceptJob实现提案即接受的自动化流转。可选的 RMN 集群与 Fast Filler对于 CCIP 测试devenv 还提供两类可选组件RMN 集群rmn.go rmn_config.go由RageProxy面向 Oracle 的代理与AFN2Proxy面向 RMN 的代理两个容器组成。默认配置为DefaultRageProxy 0.0.0.0:8081与 RMN 通信、DefaultProxyListenAddress 0.0.0.0:8080与 Oracle 通信、默认口令my-not-so-secret-passphrase。启动时会先通过镜像内的--generate命令生成密钥库keystore/afn2proxy-keystore.json与keystore/rageproxy-keystore.json再挂载 shared/local 两类配置文件启动代理最终解析出 RMN 的链上公钥EVMOnchainPublicKey与 PeerID供 RMNHome/RMNRemote 合约使用CCIP Fast Fillerfast-filler.go以 JSON 配置signerProviders、listeners、fillers三段挂载到容器的/app/config.json等待日志中出现Relayer started即视为就绪。镜像名/版本由E2E_FAST_FILLER_IMAGE、E2E_FAST_FILLER_VERSION环境变量提供默认ccip-fast-filler:latest。密钥管理AWS KMS 回退chain.go 的SetDeployerKey在未传入私钥时会调用 internal/kms/kms_client.go 中的KMSConfigFromEnvVars()读取 KMS 配置通过 AWS KMS 的GetPublicKey/Sign接口构造 EVM transactor对 ASN.1 编码的 KMS 公钥与 secp256k1 签名做解包/适配。这意味着在 CI 等不希望明文私钥落盘的场景中可以直接把部署者密钥托管在 AWS KMS 里。环境前置条件根据 devenv README运行前需要满足Docker环境中所有组件私链、Chainlink 节点、Job Distributor、RMN 代理等都以容器方式运行镜像拉取权限具备 Chainlink 与 job-distributor 镜像的拉取权限镜像地址与版本通过环境变量指定见下文。方式一使用模拟私有以太坊网络这是本地开发与快速验证最常用的路径容器全部跑在同一个 Docker 网络中。配置 testconfig运行测试前需要先按照 testconfig 配置指南 完成测试配置。testconfig 负责描述搭建环境与运行测试所需的各种配置其覆盖优先级1 最高为环境变量BASE64_CONFIG_OVERRIDEoverrides.tomlproduct.toml产品专属配置default.toml默认配置testsecrets远程环境/CI 所需一般情况下测试使用 default.toml 中的默认配置除非被产品专属配置覆盖。testconfig 支持通过[NodeConfig].BaseConfigTOML配置节点基础 TOML、通过CommonChainConfigTOML与ChainConfigTOMLByChainID配置 EVM 链专属节点配置具体字段说明见 integration-tests/testconfig/README.md。通过环境变量提供密钥类配置testconfig 中不存放devenv 环境所需的密钥类参数它们统一从环境变量读取如 Chainlink 镜像、Job-Distributor 镜像等。所有这类环境变量都列在 .sample.env 中。实际操作时可以在测试所在目录创建一个.env文件按需写入这些变量例如# 不希望在测试结束后自动销毁 Docker 容器时取消注释 # TESTCONTAINERS_RYUK_DISABLEDtrue # Job Distributor 镜像 E2E_JD_IMAGEjob-distributor-image E2E_JD_VERSIONjob-distributor-version # Chainlink 节点镜像仓库示例中的默认值 E2E_TEST_CHAINLINK_IMAGEpublic.ecr.aws/w0i8p0z9/chainlink-ccip E2E_TEST_CHAINLINK_VERSION2.14.0-ccip1.5.0 # RMN 相关代理镜像可选 E2E_RMN_RAGEPROXY_IMAGErmn-proxy-image E2E_RMN_RAGEPROXY_VERSIONmaster-5208d09 E2E_RMN_AFN2PROXY_IMAGErmn-afn2proxy-image E2E_RMN_AFN2PROXY_VERSIONmaster-5208d09提示若希望排查问题时保留容器现场可在.env中设置TESTCONTAINERS_RYUK_DISABLEDtrue以跳过测试结束后的自动清理testcontainers-ryuk。方式二连接现有测试网/主网默认情况下测试会使用与 Chainlink 节点、Job Distributor 同处一个 Docker 网络的私有以太坊网络容器。若要改为连接现有测试网/主网需要编写 overrides.toml按照 testconfig 框架的配置与覆盖规则在integration-tests目录下的任意位置新建overrides.toml写入目标网络的详细信息指定网络在 testconfig 中通过selected_network示例文件中为[Network].selected_networks字段指定具体的网络名。例如要同时跑 Sepolia、Avax 与 BSC 测试网可直接把仓库中现成的 sepolia_avax_binance.toml 内容复制到overrides.toml其核心内容如下[Common] # chainlink node funding in native token chainlink_node_funding 2 [Logging] test_log_collect true [Network] selected_networks [SEPOLIA, AVALANCHE_FUJI, BSC_TESTNET] [Network.EVMNetworks.SEPOLIA] evm_name Sepolia Testnet evm_chain_id 11155111 evm_simulated false client_implementation Ethereum evm_chainlink_transaction_limit 5000 evm_transaction_timeout 5m evm_minimum_confirmations 1 evm_gas_estimation_buffer 1000 evm_supports_eip1559 true evm_default_gas_limit 6000000 evm_finality_tag true [Network.EVMNetworks.AVALANCHE_FUJI] evm_name Avalanche Fuji evm_chain_id 43113 evm_simulated false client_implementation Ethereum evm_chainlink_transaction_limit 5000 evm_transaction_timeout 2m evm_minimum_confirmations 1 evm_gas_estimation_buffer 1000 evm_supports_eip1559 true evm_default_gas_limit 6000000 evm_finality_tag true [Network.EVMNetworks.BSC_TESTNET] evm_name BSC Testnet evm_chain_id 97 evm_simulated false client_implementation BSC evm_chainlink_transaction_limit 5000 evm_transaction_timeout 2m evm_minimum_confirmations 3 evm_gas_estimation_buffer 0 evm_supports_eip1559 true evm_default_gas_limit 6000000 evm_finality_tag true [CCIP] HomeChainSelector 16015286601757825753 # for sepolia设置 RPC 与钱包密钥环境变量运行测试前必须把这些网络的 RPC 与钱包密钥配置为环境变量。命名模式遵循 .sample.env 中的规律按目标网络提供对应变量E2E_TEST_networkName_WALLET_KEY_sequence_numberE2E_TEST_networkName_RPC_HTTP_URL_sequence_numberE2E_TEST_networkName_RPC_WS_URL_sequence_number以 Sepolia 为例对应 .sample.envE2E_TEST_SEPOLIA_WALLET_KEYsepolia-wallet-key E2E_TEST_SEPOLIA_RPC_HTTP_URL_1sepolia-rpc-http-url E2E_TEST_SEPOLIA_RPC_HTTP_URL_2sepolia-rpc-http-url E2E_TEST_SEPOLIA_RPC_WS_URL_1rpc-ws-url E2E_TEST_SEPOLIA_RPC_WS_URL_2rpc-ws-url样例中同类网络通常配置两路 HTTP/WS RPC后缀_1、_2用于多客户端容灾与负载均衡。Avalanche Fuji 与 BSC Testnet 的变量前缀分别为E2E_TEST_AVALANCHE_FUJI_*与E2E_TEST_BSC_TESTNET_*。完成以上步骤后即可使用现有测试网/主网运行测试。对于远程环境CI、Kubernetes或从本地机器触发远程测试还可以使用BASE64_CONFIG_OVERRIDE环境变量整体覆盖配置# Go test BASE64_CONFIG_OVERRIDE$(cat ./testconfig/overrides.toml | base64) go test test args环境变量速查表下表汇总了 devenv 环境涉及的全部环境变量来源.sample.env环境变量用途说明/示例值TESTCONTAINERS_RYUK_DISABLED测试结束后是否保留容器true表示不销毁容器便于调试E2E_JD_IMAGEJob Distributor 镜像job-distributor-imageE2E_JD_VERSIONJob Distributor 版本job-distributor-versionE2E_TEST_CHAINLINK_IMAGEChainlink 节点镜像示例默认public.ecr.aws/w0i8p0z9/chainlink-ccipE2E_TEST_CHAINLINK_VERSIONChainlink 节点版本示例默认2.14.0-ccip1.5.0E2E_RMN_RAGEPROXY_IMAGERMN RageProxy 镜像可选rmn-proxy-imageE2E_RMN_RAGEPROXY_VERSIONRageProxy 版本示例默认master-5208d09E2E_RMN_AFN2PROXY_IMAGERMN AFN2Proxy 镜像可选rmn-afn2proxy-imageE2E_RMN_AFN2PROXY_VERSIONAFN2Proxy 版本示例默认master-5208d09E2E_FAST_FILLER_IMAGECCIP Fast Filler 镜像可选默认ccip-fast-filler:latestE2E_FAST_FILLER_VERSIONFast Filler 版本见 fast-filler.goE2E_TEST_NETWORK_WALLET_KEY目标网络钱包密钥如E2E_TEST_SEPOLIA_WALLET_KEYE2E_TEST_NETWORK_RPC_HTTP_URL_n目标网络 HTTP RPC如E2E_TEST_SEPOLIA_RPC_HTTP_URL_1E2E_TEST_NETWORK_RPC_WS_URL_n目标网络 WebSocket RPC如E2E_TEST_SEPOLIA_RPC_WS_URL_1此外若部署者密钥托管在 AWS KMS 中不通过SetDeployerKey传私钥还需要提供 KMS 相关的环境变量其读取逻辑见 internal/kms/kms_client.go 中的KMSConfigFromEnvVars()。运行端到端冒烟测试配置完成后即可在integration-tests目录下运行对应的冒烟测试测试用例如 integration-tests/smoke 下的产品目录组织CCIP 冒烟测试位于 integration-tests/smoke/ccip。参考 testconfig README 中的用法运行方式形如# 在 integration-tests 目录下执行 go test -v -p 1 ./smoke/ccip/...若使用overrides.toml覆盖配置可结合BASE64_CONFIG_OVERRIDE一并使用BASE64_CONFIG_OVERRIDE$(cat ./testconfig/overrides.toml | base64) go test -v -p 1 ./smoke/ccip/...测试运行期间可以观察到 devenv 拉起的容器私链、Chainlink 节点、Job Distributor 等在同一个 Docker 网络中协同工作通过docker ps可查看容器清单配合TESTCONTAINERS_RYUK_DISABLEDtrue可在测试结束后保留现场用于排查。注意事项与排错要点结合 devenv README 与相关源码、配置文档以下几点在实践中值得特别注意testconfig 的指针字段与校验testconfig README 明确指出产品/测试专属配置缺失时可能触发nil 指针运行期错误建议为所用测试显式补齐所需配置并实现配置校验重复配置文件名的风险不同目录下出现同名配置文件可能导致不可预期的执行行为命名时应保持唯一revert 原因解码对归档节点的依赖chain.go 的parseError中若错误消息包含missing trie node会直接提示请使用归档节点archive node——连接测试网/主网时建议使用支持历史状态的 RPCJD 链配置可能静默失败CreateCCIPOCRSupportedChains在 JD 侧创建 ChainConfig 后并不保证立即生效因此源码中实现了列出链配置核对 定时重试的双保险逻辑节点默认命名未显式提供NodeInfo.Name时节点会被命名为node-0、node-1……见 don.go 的NewRegisteredDON在日志中据此定位具体节点十分方便密钥安全overrides.toml虽被 git 忽略但远程环境使用的 override 文件不在此列切勿在其中写入敏感信息钱包私钥一律通过环境变量注入。总结Devenv 是 Chainlink 仓库中连接测试代码与真实运行环境的关键一环它把链EVM/Solana/Aptos/Tron、Chainlink 节点、Job Distributor、可选的 RMN 代理与 Fast Filler 统一封装为 Docker 容器化的临时环境既支持本地私链的快速闭环也支持对现有测试网/主网的直接复用。通过 devenv README、.sample.env 与 testconfig README 三份文档的组合使用加上 deployment/environment/devenv 目录下源码的深入理解你就可以在自己的本地或 CI 流水线中稳定地复现这套端到端测试流程。【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考