fhevm-relayer 本地开发指南:构建、测试、Lint 与本地协议栈全流程
【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm
本文是 fhevm 仓库中 relayer/docs/DEVELOPMENT.md 的深度展开版,面向需要在本地克隆、构建、测试并调试 fhevm-relayer 的开发者。fhevm-relayer 是 fhevm 生态中连接宿主链(如 Ethereum)与 Gateway 的桥接服务,承担公开解密(public decryption)、输入证明校验(input proof verification)、用户解密(user decryption)与密钥材料 URL(keyurl)等关键能力。读完本文,你将掌握:一条命令完成本地开发环境初始化、按测试组精确运行集成测试、在本地拉起完整 Zama 协议栈并注入自建 relayer 镜像、管理本地 PostgreSQL、执行 lint/format 门禁,以及构建可发布的 Docker 镜像。
面向运维/自托管部署的说明,请参见 SELF_HOSTING.md;贡献规范参见 CONTRIBUTING.md。
目录
- 环境与前置条件
- 首次设置:一条命令完成开发环境初始化
- 运行测试:nextest 与按组执行
- Local Stack:本地运行完整 Zama 协议
- Lint 与格式化
- 数据库管理
- Docker 镜像构建
- 故障排查
- 仓库源码导读
环境与前置条件
在动手之前,请确认本机具备以下工具链(见 relayer/README.md):
| 依赖 | 用途 |
|---|---|
| Rust 工具链 + Cargo | 编译、运行与测试 relayer 本体 |
| Docker + Docker Compose v2 | 本地 Postgres、本地协议栈、镜像构建 |
Foundry(cast) | 仅网络对接类目标需要(make preflight-*、make mint-zama-*、make approve-payment-*) |
| Node.js + npm | 仅make api-lint需要 |
工具链版本以仓库内 rust-toolchain.toml 为准(当前 channel 为1.97.1,包含rustfmt与clippy组件)。运行make help可随时查看全部可用目标。
首次设置:一条命令完成开发环境初始化
make setup # 启动 Postgres、执行迁移、复制配置模板该命令聚合了本地开发所需的全部初始化工作,对应 Makefile 中的setup目标,实际依次执行:
- 启动本地 PostgreSQL:通过 Docker Compose 拉起实例,映射到5433 端口(刻意避开默认的 5432,避免与系统自带 Postgres 冲突)。对应
make db-start。 - 执行数据库迁移:使用独立的
relayer-migrate二进制(cargo run --manifest-path relayer-migrate/Cargo.toml --bin relayer-migrate)应用全部 schema 迁移,最多重试 20 次。对应make db-migrate。 - 复制配置模板:若
config/local.yaml不存在,则将config/local.yaml.example复制为config/local.yaml。
本地 Postgres 的完整定义在 dev/docker-compose.yaml:数据库名relayer_db、用户/密码均为postgres、启用trust认证,并配置了pg_isready健康检查、命名卷postgres_data持久化数据。值得注意的是它的启动参数把max_connections抬高到了500,并预加载了pg_cron扩展——这是为了给并行的集成测试留出连接余量(详见下文测试一节)。
本地连接串由 Makefile 统一派生:
DATABASE_URL := postgresql://postgres:postgres@localhost:5433/relayer_db提示:Makefile 中的
_db-probe前置检查会同时校验DB_PORT/DB_NAME与dev/docker-compose.yaml的一致性,以及 Postgres 是否真正在 5433 端口就绪。如果手工修改了其中一方而未同步另一方,make会在运行前直接报错,而不是连到错误的地方。
运行测试:nextest 与按组执行
relayer 的测试体系运行在 nextest 之上,测试目标会直接检查cargo-nextest是否安装(见 Makefile 的_check-nextest),因此第一步是安装它:
cargo install cargo-nextest --locked随后可以运行:
make test # 完整套件,与 CI 完全一致(需要 Postgres) make test-unit # 仅 src/ 下的单元测试与文档测试(不需要 Postgres)make test-unit实际上执行两部分:cargo nextest run --lib(单元测试)与cargo test --workspace --doc(nextest 不跑 doctest,所以交给 cargo 自己)。而make test-integration会先单独跑ethereum_rpc_mock测试 crate,再以--features integration-tests --test '*'模式运行 tests/ 下所有测试二进制。
按测试组精确执行
测试被划分为若干组(group),一组对应一个测试二进制,其语义是"一条 API 流程"(如public-decrypt)或"流程间共享的横切特性"(如listener-redundancy)。组的定义与成员映射全部集中在 Makefile,例如:
public-decrypt→public_decrypt_v2_testinput-proof→input_proof_v2_testuser-decrypt→user_decrypt_v2_test+user_decrypt_v3_testrestart→shutdown_test+handled_events_test+recovery_test("进程存活"这一行为被合并为一组)listener-redundancy、dispatcher-lock、sweep、epoch-fencing等横切特性各占一组
按组执行的方式:
make test-groups # 列出全部可用组名 make test-group GROUP=public-decrypt # 跑一个组内的全部用例 make test-group GROUP=public-decrypt CASE=acl # 仅跑名称匹配 "acl" 子串的用例 make test-group GROUP=public-decrypt SKIP=timeout # 排除名称匹配 "timeout" 的慢用例CASE与SKIP会合成为 nextest 的过滤器表达式,例如test(acl) and not test(timeout)(见 Makefile)。
并发模型与连接预算
测试默认8 个并发(与 CI 相同),且 nextest 的调度池横跨所有测试二进制(而不是一个二进制跑完再跑下一个)。每个测试使用独立的 schema,大约占用3 条 Postgres 连接,因此并发上限由服务端max_connections决定:CI 中是 100,本地是 500(见 dev/docker-compose.yaml 的max_connections=500)。
想加快本地运行,可在任意上述命令后追加TEST_THREADS=32;调试单个用例时可使用TEST_THREADS=1串行化。
组与测试文件的强一致性校验
Makefile 还提供了make test-groups-check:它对比"组中声明的测试文件"与"磁盘上实际存在的tests/*.rs",任何不在任何组中的测试文件或组中声明却不存在的测试文件都会让构建失败——确保 CI 不会漏跑新写的测试,也不存在"从未被执行"的孤儿测试。CI 会执行该校验。
测试用配置见 tests/relayer-test-config.yaml,其结构是 config/local.yaml.example 的近亲,差异点包括更快的 keyurl 轮询间隔、关闭负载均衡等待时间等,专门为测试场景调优。
Local Stack:本地运行完整 Zama 协议
这一模式通过 fhevm 仓库的fhevm-cli在本地跑起整套 Zama 协议,然后把你本地构建的 relayer 镜像注入其中,非常适合做端到端联调。
部署 Zama 协议
git clone git@github.com:zama-ai/fhevm.git cd fhevm/test-suite/fhevm ./fhevm-cli deploy该步骤需要 Docker 至少分配12 GB 内存。这也是 relayer/README.md 明确记录的硬性要求。
构建并注入本地 relayer 镜像
fhevm-cli 的 Docker Compose 栈期望镜像名带 registry 前缀,因此先用带时间戳的 tag 构建本地镜像:
LOCAL_RELAYER_TAG=local-relayer-$(date +%Y%m%d%H%M%S) make docker-release TAG=${LOCAL_RELAYER_TAG}make docker-release(Makefile)会依次构建relayer与relayer-migrate两个镜像并打上ghcr.io/zama-ai/console/前缀,同时校验 TAG 不能是latest。随后在 fhevm 栈目录中升级 relayer:
# 在 fhevm/test-suite/fhevm 目录下执行 RELAYER_VERSION=${LOCAL_RELAYER_TAG} \ RELAYER_MIGRATE_VERSION=${LOCAL_RELAYER_TAG} \ ./fhevm-cli upgrade relayer验证运行中的镜像
确认升级后容器实际使用的镜像:
docker inspect fhevm-relayer --format '{{.Config.Image}}' docker inspect relayer-db-migration --format '{{.Config.Image}}'两条命令应分别输出你构建的local-relayer-<时间戳>镜像。
通过 fhevm-cli 运行 E2E 测试
./fhevm-cli test input-proof停止本地栈
./fhevm-cli cleanLint 与格式化
make check # fmt + clippy(推荐的 push 前门禁) make fix # 自动修复 fmt + clippy 问题 make clippy # 仅 clippy make fmt # 仅格式检查make check是推荐的pre-push 门禁,它同时运行fmt --check与clippy,但不启动 Postgres、不跑测试,因此非常快。其实际组成(Makefile)还包括openapi-check——它会重新生成 OpenAPI 规范并git diff校验openapi.yml是否漂移。
值得注意的细节:
make clippy使用cargo clippy --workspace --all-targets --all-features -- -D warnings,把任何 clippy 警告都升级为错误,防止警告悄悄堆积。make fmt只针对本仓库拥有的包(fhevm-relayer与ethereum_rpc_mock),刻意排除了通过路径依赖引入的生成代码(如gateway-contracts/rust_bindings、host-contracts/rust_bindings),因为这些不是 relayer 团队可以格式化的代码。make fix依次执行fmt-fix与clippy-fix(clippy 以--fix --allow-dirty --allow-staged自动应用修复)。
数据库管理
生命周期管理
make db-start # 启动本地 Postgres(5433 端口)并等待就绪 make db-stop # 停止 Postgres(保留数据) make db-destroy # 停止 Postgres 并清空所有数据(-v 删除卷) make db-reset # 清空并从头重新执行迁移 make db-status # 显示容器状态 + 连接测试 make db-shell # 打开 psql shell make db-logs # 跟踪 Postgres 容器日志其中db-reset是"先db-destroy再db-start再db-migrate"的组合,适合需要从干净 schema 重跑测试的场景。db-migrate依赖relayer-migrate二进制执行迁移(带连接重试);迁移脚本位于 relayer-migrate/migrations/(例如建表、job id 唯一约束、请求类型演进、sweep 索引等),回滚脚本位于 relayer-migrate/down/。
sqlx-cli 目标
这些目标依赖sqlx-cli。安装时必须固定到 0.8.x 系列:因为 sqlx-cli 0.9.0 将 MSRV 提升到了 rustc 1.94,而rust-toolchain.toml指定的工具链更高(当前 1.97.1),但仓库注释中明确建议的版本为 0.8.6:
cargo install sqlx-cli --version 0.8.6 --no-default-features --features postgres,rustls安装后:
make sqlx-migrate # 通过 sqlx-cli 执行迁移 make sqlx-prepare # 重新生成离线元数据,供 CI / Docker 构建使用关键约束:Docker 构建依赖预计算的查询元数据.sqlx/(仓库根relayer/.sqlx/下是一批query-*.json文件,配合SQLX_OFFLINE使用)。因此每当你新增或修改 SQL 查询,必须先在本地运行make sqlx-prepare再构建 Docker 镜像,否则离线构建会基于过期的元数据编译通过却描述错误的数据访问。make sqlx-check可以在 CI 中"只校验不写入",用于及时发现.sqlx/与迁移的漂移。
Docker 镜像构建
make docker-build # 构建 relayer 镜像 make docker-build-migrate # 构建 relayer-migrate 镜像 make docker-build-all # 同时构建上述两者 make docker-release TAG=v0.9.0-rc.1 # 带 registry 前缀构建(TAG 必填)构建细节(Dockerfile):
- 构建阶段使用 golden 基础镜像
ghcr.io/zama-ai/fhevm/gci/rust-glibc:${RUST_IMAGE_VERSION},Rust 版本由 rust-toolchain.toml 单一来源派生(Makefile 用 awk 读取channel字段),保证本地与 CI 一致。 - Dockerfile 通过 bind mount 引入仓库根级路径依赖:
gateway-contracts/rust_bindings、host-contracts/rust_bindings、shared/user-decryption-signature、shared/ciphertext-attestation,这正是 relayer 作为 monorepo 子项目、跨 crate 依赖多个绑定库的体现。 - 构建以
--locked --release进行,并挂载 cargo registry 与 target 缓存加速增量构建。 - 运行阶段使用最小化镜像,创建非特权用户
appuser(UID 10001)并以该用户运行/bin/server。
Git worktree 限制:relayer 的 Dockerfile 需要真实的.git/目录(而非 worktree)用于构建期版本信息嵌入。在 Git worktree 中,.git是一个文件而非目录,会导致挂载失败。请从主克隆(primary clone)构建,这也是 README 排障章节 记录的已知问题。
故障排查
完整的排障清单见 relayer/README.md 的 Troubleshooting 章节,以下是几个高频问题速查:
| 症状 | 原因与解决 |
|---|---|
connection refused | 本地 Postgres 映射在5433而非 5432。确认连接串使用localhost:5433。 |
| Docker 构建失败(Git 挂载错误) | 正在 worktree 中构建。改用主克隆构建。 |
| 构建通过但查询行为与 schema 不符 | .sqlx/离线元数据过期。运行make sqlx-prepare后重新构建。 |
| 本地协议栈起不来 | ./fhevm-cli deploy需要 Docker 至少12 GB 内存。 |
| 配置连到 mock 地址 | config/local.yaml.example内置localhost:8757RPC 与0.0.0.0:3001keyurl,仅适用于本地 mock 栈;对接 Testnet/Mainnet 应使用make preflight-testnet/make preflight-mainnet,它们会自动复制正确的示例配置。 |
仓库源码导读
如果你想进一步深入,下面这些路径是继续阅读的起点:
- Makefile:本文所有命令的权威定义,自文档化(
make help可读)。 - dev/docker-compose.yaml:本地 Postgres 的完整定义(端口、连接上限、pg_cron)。
- config/local.yaml.example:本地开发配置模板,覆盖 keyurl、listener_pool、tx_engine 节流器、readiness_checker、动态 retry-after、cron 超时/过期策略、dispatcher_lock 等全部可调参数。
- tests/:全部集成测试二进制,与 Makefile 中的
BINS_<group>一一对应。 - tests/relayer-test-config.yaml:集成测试专用配置。
- relayer-migrate/:独立迁移 crate,含迁移脚本与回滚脚本。
- docker/relayer/Dockerfile 与 docker/relayer-migrate/Dockerfile:镜像构建定义。
- rust-toolchain.toml:工具链单一事实来源。
- SELF_HOSTING.md:面向运维的自托管部署指南。
- README.md:服务能力总览、API 端点、超时与数据保留策略、排障。
整个 fhevm 仓库是一个 monorepo:relayer 与 gateway-contracts、host-contracts、shared 等模块通过路径依赖联动,理解这一点有助于把握构建上下文。开发期间一切以make help的输出为最权威的操作清单。
【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考