news 2026/9/12 3:03:14

fhEVM Coprocessor 压测流量生成器 stress-test-generator 完整指南:场景配置、REST API 与源码原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fhEVM Coprocessor 压测流量生成器 stress-test-generator 完整指南:场景配置、REST API 与源码原理

fhEVM Coprocessor 压测流量生成器 stress-test-generator 完整指南:场景配置、REST API 与源码原理

【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm

本指南面向需要为 fhEVM Coprocessor 全链路(网关监听、ZK 输入验证、TFHE 计算、解密流程)构造可控、可重复压测流量的开发者与运维人员。文章以仓库中 stress-test-generator/README.md 为核心骨架,结合该模块的 Rust 源码、示例 CSV/JSON 文件与 Docker 构建方式,系统讲解环境变量、场景文件格式、全部支持的事务类型、REST API 服务模式,以及流量生成背后的实现原理。读完本文,你将能够独立编写压测场景文件、以 CLI 或服务方式驱动压力测试,并理解每条流量在数据库与 ZK 验证链路上的行为。

一、模块定位:为 Coprocessor 压测而生的事务生成器

stress-test-generator 是 fhEVM 仓库coprocessor/fhevm-engine工作区中的一个独立二进制 crate(Cargo.toml),编译产物名为stress_generator。它的职责不是直接压测单机性能,而是按照用户设定的速率或数量,持续向 Coprocessor 系统的数据库注入模拟的 FHE 事务事件(ERC20 转账、DEX 兑换、加法/乘法链、ZK 输入证明、解密句柄生成等),从而驱动 gw-listener、zkproof-worker、tfhe-worker、transaction-sender 等下游组件形成真实的全链路负载。

从依赖关系看(Cargo.toml),它直接复用fhevm-engine-commonschedulerhost-listenerzkproof-workertest-harnesstfhe-worker等本地 crate,并依赖tfhe(全同态加密)、sqlx(PostgreSQL)、alloy(以太坊类型)与axum(HTTP 服务),这说明它既可以作为纯 CLI 工具单次执行场景,也可以作为常驻 REST 服务远程提交压测任务。

二、环境变量配置:参数清单与源码默认值

工具的全部运行参数通过环境变量注入,由EnvConfig::new()统一读取(实现见 src/utils.rs)。下表完整列出 README 声明及源码确认的变量、默认值与作用:

环境变量默认值作用
EVGEN_SCENARIOdata/evgen_scenario.csvCLI 模式下读取的分号分隔场景文件路径(仅在 CLI 模式使用;服务模式下场景改由 API 提交)
EVGEN_DB_URLpostgresql://postgres:postgres@127.0.0.1:5432/coprocessor连接 Coprocessor 数据库的 PostgreSQL URL,用于写入事务事件、查询 ZK 公钥/CRS、轮询验证结果
ACL_CONTRACT_ADDRESS0x05fD9B5EFE0a996095f42Ed7e77c390810CF660cACL 合约地址,被编码进 ZK 证明的 aux 数据(见 zk_gen.rs)
CHAIN_ID12345主机链 Chain ID,用于生成模拟句柄与写入数据库
API_KEYa1503fb6-d79b-4e9e-826d-44cf262f3e05API 密钥(README 声明项;当前源码中未发现读取逻辑,使用时以环境为准)
TENANT_ID1租户 ID(README 声明项)
SYNTHETIC_CHAIN_LENGTH10合成基准场景(MULChainADDChain)中每条事务的链长度,即单个事务内连续执行的 FheAdd/FheMul 次数
MIN_DECRYPTION_TYPE0生成解密句柄时的最低 FHE 类型编号(0 → FheBool)
MAX_DECRYPTION_TYPE6生成解密句柄时的最高 FHE 类型编号(6 → FheUint128)
OUTPUT_HANDLES_FOR_PUB_DECRYPTIONdata/handles_for_pub_decryptionGenPubDecHandles场景输出的公开解密句柄文件路径
OUTPUT_HANDLES_FOR_USR_DECRYPTIONdata/handles_for_usr_decryptionGenUsrDecHandles场景输出的用户解密句柄文件路径

关于解密类型的取值范围,源码中的FheType枚举(src/utils.rs)给出了完整映射:0=FheBool、1=FheUint4、2=FheUint8、3=FheUint16、4=FheUint32、5=FheUint64、6=FheUint128、7=FheUint160、8=FheUint256、9=FheBytes64、10=FheBytes128、11=FheBytes256。因此MIN_DECRYPTION_TYPE/MAX_DECRYPTION_TYPE实际可扩展的范围比默认的 0~6 更大,可用于覆盖更多密文类型。

三、场景文件(Scenario CSV)格式规范

场景文件是分号分隔的 CSV,无表头,逐行描述一个流量场景。CSV 解析配置(分隔符;、去空白、无表头、flexible 允许变长列)见 src/bin/stress_generator.rs。

3.1 列顺序与取值

列序含义可选值说明
1事务类型见 §4决定生成哪种 FHE 事件序列
2ERC 转账变体WhitepaperNoCMUXNA仅对 ERC20/ERC7984 转账有意义;其他事务填NA
3生成目标RateCountRate:每秒生成的事务数;Count:直接生成指定批次数量
4输入模式ReuseInputsNewInputs是否复用预先生成的输入句柄(详见 §3.3)
5依赖关系DependentIndependent事务是否链式串联(详见 §3.4)
6合约地址十六进制地址流量注入的目标合约
7用户地址十六进制地址模拟的调用者/账户
8场景规格(float, integer)无限序列成对的(速率或数量,持续时长或迭代次数)

3.2 Rate 与 Count 的语义差异

场景规格是"速率/数量 + 时长/次数"的成对序列,且支持在同一行内书写多对。README 给出的例子:1.1; 20; 3.4; 10——

  • 若目标为Rate:生成器先以平均 1.1 笔/秒的速率持续 20 秒,再以 3.4 笔/秒的速率持续 10 秒;
  • 若目标为Count:先产生1.1 × 20 = 22笔事务的批量,紧接着再产生34笔事务的批量。

对应源码实现:

  • 速率模式generate_transactions_at_rate(stress_generator.rs):按time_between_transactions = 1.0 / target_throughput计算间隔,每生成一笔事务后若耗时低于间隔则休眠补齐;若目标速率过高导致生成跟不上,则退化为"尽力而为"地连续生成;
  • 计数模式generate_transactions_count(stress_generator.rs):每对(num_transactions, iter_count)换算为iters = num_transactions × iter_count次迭代,逐次生成事务。

仓库自带的一个直观示例是 data/minitest_002_erc20.csv:

ERC20Transfer; NoCMUX; Count; ReuseInputs; Independent; 0xa5880e99d86F081E8D3868A8C4732C8f65dfdB08; 0xa0534e99d86F081E8D3868A8C4732C8f65dfdB07; 10.0; 2

含义为:以Count目标生成10.0 × 2 = 20NoCMUX变体的 ERC20 转账,复用输入、事务互相独立。

3.3 ReuseInputs 与 NewInputs:输入生成策略

  • NewInputs:每笔事务都新生成输入——即重新执行"加密 → 生成 ZK 证明 → 提交验证 → 取回句柄"的完整往返,能真实模拟输入验证链路的压力,但会显著增加每笔事务的时延;
  • ReuseInputs:启动时生成一批随机输入后放入内存缓存(每合约+用户组合缓存CACHED_INPUTS_COUNT = 16个句柄,见 zk_gen.rs),后续直接复用,避免反复 round-trip zkproof-worker,从而让负载更集中在计算/监听链路。

输入缓存的实际结构是(contract_address, user_address) → Vec<Option<Handle>>的全局哈希表(zk_gen.rs),get_inputs_vector(zk_gen.rs)负责按策略返回新输入或命中缓存。

3.4 Dependent 与 Independent:事务串联

  • Dependent:事务之间链式串联,前一笔的输出句柄作为后一笔的输入。README 举例:Dependent 的 ERC 转账意味着场景中所有转账都汇入同一个目标钱包。这样可以在单一依赖链上持续累积计算深度,压测长链场景;
  • Independent:每笔事务独立执行,互不依赖。

实现上,generate_transaction返回(Handle, Handle)两个输出句柄,Dependent场景会将其保存并传入下一次生成(见 stress_generator.rs)。依赖句柄缓存的大小默认 128(default_dependence_cache_size(),见 utils.rs)。

四、支持的事务类型:12 种场景全景

README 声明了 7 种事务类型;结合 src/utils.rs 的Transaction枚举,工具实际支持 12 种,按其注入行为可分为以下几类:

4.1 应用型业务事务

类型行为
ERC20Transfer模拟密文 ERC20 转账:先做FheGe余额检查,再按变体更新转出/转入余额。实现见 src/erc20.rs
DEXSwapRequest模拟去中心化交易所的兑换请求,涉及多组输入与双余额输出(src/dex.rs)
DEXSwapClaim模拟兑换后的领取/结算事务(src/dex.rs)
ERC7984Transfer模拟 ERC-7984 的机密转账confidential_transfer_from(src/erc7984.rs)

其中ERC20Transfer的两种变体值得展开:

  • Whitepaper变体(erc20.rs):用FheGe生成"余额是否充足"的布尔句柄,再通过FheIfThenElse条件选择转入/转出目标,最后FheAdd/FheSub更新双方余额——这是 fhEVM 白皮书描述的经典转账模式;
  • NoCMUX变体(erc20.rs):将布尔句柄Cast为 u64,与转账金额做FheMul得到"实际可转金额"(不足则自动为 0),再FheAdd/FheSub更新余额——避免使用条件选择(CMUX),适用于压测无 CMUX 的电路路径。

4.2 合成基准事务(Synthetic Bench)

类型行为
ADDChain单笔事务内连续执行length(由SYNTHETIC_CHAIN_LENGTH控制,默认 10)次FheAdd,形成加法链
MULChain同上,但连续执行FheMul乘法链

实现见 src/synthetics.rs:每条链以next_random_handle(FheUint64)生成中间句柄,循环写入FheAdd/FheMul事件,仅最后一环标记为is_allowed,最终句柄通过allow_handle授予AllowedForDecryption权限后返回。这类事务用于衡量计算深度对 tfhe-worker 的影响。

4.3 ZK 输入验证类事务

类型行为
InputVerif生成并提交 ZK 输入证明,等待 zkproof-worker 验证后取回密文句柄(zk_gen.rs)
BatchInputProofs批量生成 ZK 输入证明并插入verify_proofs表(zk_gen.rs),用于压测输入证明批量处理吞吐

4.4 解密句柄生成类事务

类型行为
GenPubDecHandlesMIN_DECRYPTION_TYPEMAX_DECRYPTION_TYPE范围内的每种 FHE 类型生成一个可公开解密的句柄,追加写入公开解密句柄文件(synthetics.rs)
GenUsrDecHandles同上,但句柄同时授权给合约与用户账户,供用户解密流程使用(synthetics.rs)

4.5 其他批量辅助事务

类型行为
BatchAllowHandles批量向allowed_handles表授予句柄权限(默认关闭 pbs_computations 写入),可用于准备压测前置数据
BatchSubmitEncryptedBids批量提交加密竞价(密封拍卖场景),batch_size上限为 10(MAX_NUMBER_OF_BIDS,见 stress_generator.rs),实现见 src/auction.rs

4.6 JSON 格式场景文件

除 CSV 外,服务模式(以及仓库 data/json 目录下)使用 JSON 数组描述同样的场景,字段与 CSV 列一一对应,且为批量类事务额外提供可选的batch_size字段。以 example_job.json 为例:

[ { "transaction": "ERC20Transfer", "variant": "NoCMUX", "kind": "Rate", "inputs": "NewInputs", "is_dependent": "Independent", "contract_address": "0xa5880e99d86F081E8D3868A8C4732C8f65dfdB08", "user_address": "0xa0534e99d86F081E8D3868A8C4732C8f65dfdB07", "scenario": [ [1.1, 2], [1.0, 1] ] } ]

批量场景示例(batch_input_proofs.json)展示了batch_size: 4000的用法:以 1.0 次/秒的速率持续 600 秒,每次触发一批 4000 条 ZK 输入证明的生成。

五、REST API 服务模式

除了作为 CLI 工具一次性执行场景,stress_generator还可以作为独立服务运行在远程机器上。服务内部使用容量为 100 的mpsc通道 + 单消费者循环串行处理任务(stress_generator.rs),同一时刻只运行一个 job,其余排队,从而保证性能指标采集的准确性。

5.1 启动服务

README 给出的启动方式(注意:服务模式下所有 ENV 变量照常配置,唯独EVGEN_SCENARIO不需要,因为场景由 API 提交):

# 配置除 EVGEN_SCENARIO 外的全部 ENV 变量 # 以服务方式运行 cargo run --release -- --run-server --listen-address 127.0.0.1:3030

CLI 参数由 src/args.rs 定义,除--run-server--listen-address外还支持:

参数默认值说明
--run-serverfalse以 API 服务模式启动(缺省则执行 CLI 场景)
--listen-address0.0.0.0:3000HTTP 监听地址(README 示例使用127.0.0.1:3030
--zkproof-notify-channelevent_zkpok_new_work用于 ZK 证明事件通知的 PostgreSQLpg_notify通道名
--log-levelinfo日志级别

仓库还提供了 run_with_localnet.sh,它会先加载./../.env-test环境文件,再以--run-server --listen-address=0.0.0.0:3030启动服务,适合本地联调。

5.2 端点一览

README 声明了 4 个端点;源码路由表(stress_generator.rs)还额外实现了任务取消端点:

方法路径作用
POST/job入队一个新 job(一组场景),返回{id, scenarios_count, queued_at},HTTP 201
GET/job/:id查询指定 job 的状态
PATCH/job/:id取消指定 job(源码额外提供,README 未列出)
GET/status/running返回当前正在运行的 job_id
GET/status/queued按执行顺序列出所有排队中的 job

job 状态机包含四种状态:Queued(入队时间)、Running(开始时间)、Completed(完成时间)、Cancelled(取消时间),定义见 stress_generator.rs。取消通过CancellationToken实现,可同时作用于排队中与运行中的 job(stress_generator.rs)。

5.3 完整调用示例

# 从 data/json 中选择/准备一个 job 文件(例如 data/json/minitest_002_erc20.json) # 提交 job curl -X POST http://localhost:3030/job \ -H "Content-Type: application/json" \ -d @./data/json/minitest_002_erc20.json # 查询 job 结果 curl -X GET http://localhost:3030/job/0

job id 由进程内自增计数器分配(GLOBAL_COUNTER,见 stress_generator.rs),服务重启后从 0 重新计数,查询时以响应中返回的id为准。

六、完整运行示例

6.1 CLI 模式:直接执行场景文件

# 配置环境变量(可覆盖默认值) export EVGEN_SCENARIO=data/evgen_scenario.csv export EVGEN_DB_URL=postgresql://postgres:postgres@127.0.0.1:5432/coprocessor export ACL_CONTRACT_ADDRESS=0x05fD9B5EFE0a996095f42Ed7e77c390810CF660c export CHAIN_ID=12345 export SYNTHETIC_CHAIN_LENGTH=10 export MIN_DECRYPTION_TYPE=0 export MAX_DECRYPTION_TYPE=6 # 编译并执行 cargo run --release

不传--run-server时,程序进入parse_and_execute分支(stress_generator.rs):解析EVGEN_SCENARIO指向的 CSV,逐行并行 spawn 场景执行,等待全部完成。仓库自带的默认场景 data/evgen_scenario.csv 同时覆盖了 ERC20Transfer(两种变体)、ADDChain、MULChain、DEXSwapRequest/Claim、InputVerif 共 9 条场景,可直接作为模板。

6.2 解密句柄生成与摘要回填

CLI 模式执行完包含GenPubDecHandles/GenUsrDecHandles的场景后,程序会额外连接数据库,为句柄文件中的每一行查询ciphertext_digest表中的密文摘要(64 位与 128 位),并将文件更新为handle 0x<digest64> 0x<digest128>的格式(stress_generator.rs)。查询最多重试 500 次、每次间隔 200ms(utils.rs)。对应示例见 data/minitest_003_generate_handles_for_decryption.csv 与同名的 JSON 版本。

6.3 Makefile 与容器化

  • Makefile 提供make build(release 编译)、make preparecargo sqlx prepare离线查询缓存)、make runcargo run --release);
  • Dockerfile 采用两阶段构建:builder 阶段从ghcr.io/zama-ai/fhevm/gci/rust-glibc基础镜像编译stress_generator二进制,runtime 阶段使用cgr.dev/chainguard/glibc-dynamic以非 root 用户fhevm运行,默认入口即stress_generator二进制。

七、源码级运行原理

7.1 主流程:CLI 与服务两分支

入口main(stress_generator.rs)根据args.run_server分派:

  • 服务模式:初始化Context,构建 axum Router,后台 spawn 单一消费者循环,从通道取 job 串行执行;
  • CLI 模式:直接parse_and_execute,先同步执行全部场景,再处理解密句柄的摘要回填。

Context中保存argsEnvConfigCancellationToken与预生成的输入池inputs_pool(utils.rs),取消令牌贯穿速率/计数生成循环,使 job 取消能及时中断事务注入。

7.2 ZK 输入生成与验证链路

NewInputs模式下的每笔事务都走完整 ZK 往返(zk_gen.rs):

  1. 从数据库读取最新 TFHE 紧凑公钥pks与 CRS(query_and_save_pks,内部使用DbKeyCacheCrsCache,见 utils.rs);
  2. tfhe::ProvenCompactCiphertextList构建随机 u64 输入并生成带证明的密文列表;
  3. 将证明与(contract_address, user_address, acl_contract_address, chain_id)编码的 92 字节 aux 数据组装后插入verify_proofs表,并通过pg_notify通知--zkproof-notify-channel指定的通道(默认event_zkpok_new_work,见 zk_gen.rs);
  4. 轮询verify_proofs.verifiedhandles字段,最多重试 5000 次,验证通过后按 32 字节切分返回句柄列表。

BatchInputProofs则在此基础上按batch_size循环插入证明,并设置retry_count = 5以保证 txn-sender 首轮即删除、避免误报VerifyProofNotRequested错误(zk_gen.rs)。

7.3 事件注入:绕过交易直接写库

除 ZK 类事务外,ERC20TransferADDChainMULChainGenPubDecHandles等场景并不真正发送链上交易,而是构造TfheContractEvents事件(如FheAddFheMulFheGeFheIfThenElseTrivialEncrypt),通过insert_tfhe_event直接写入监听器数据库(allowed_outputsoperand_boundary_mask等字段由uniform_allowed_outputsfixture_operand_boundary_mask生成,见 utils.rs)。句柄本身由next_random_handle按 fhEVM 句柄布局构造(随机哈希 + computed 标记 + chain_id + 类型 + 版本,见 utils.rs)。这种方式让压测负载可以绕开交易广播与区块确认的时延,直击下游计算与监听链路。

7.4 速率控制与依赖链

速率模式以1.0 / target_throughput计算事务间隔,并考虑单笔生成耗时动态补齐休眠;Dependent场景通过把上一笔的输出句柄传入下一笔形成依赖链,dependence_handle1/2即为链上传递的句柄(stress_generator.rs)。所有生成均在单个数据库事务(sqlx::Transaction)中完成并按场景类型 commit,保证事件写入的原子性。

八、小结

stress-test-generator 是 fhEVM Coprocessor 压测体系的核心入口:通过一套简洁的 CSV/JSON 场景描述与十个环境变量,即可在 CLI 与服务两种模式下,对 ERC20 转账、DEX 兑换、合成计算链、ZK 输入证明、解密句柄生成等十余种 FHE 工作负载进行速率可控、可串联、可取消的流量注入。理解其场景语义(Rate/Count、ReuseInputs/NewInputs、Dependent/Independent)与源码注入路径(直接写库的 TFHE 事件 + 完整的 ZK 证明往返),可以帮助你在压测 Coprocessor 时精确构造目标负载,并对采集到的性能数据建立正确的因果解释。

延伸阅读

  • 模块 README
  • 主程序与 REST API 实现
  • 环境变量与场景结构定义
  • ZK 输入生成与验证
  • ERC20 转账场景实现
  • 合成链与解密句柄生成
  • 示例场景文件(CSV 与 JSON)

【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 3:02:16

行人检测与重识别:从监控视频中快速搜索目标轨迹的工程实践

简介&#xff1a;面向机器学习与计算机视觉方向的开发者&#xff0c;这份压缩包提供了一套基于Python的监控视频行人轨迹搜索方案。通过输入一张目标图像&#xff0c;即可在大量视频片段中检索并标记包含该目标的内容&#xff0c;适用于安防监控、智慧安防等需要跨镜头追踪的工…

作者头像 李华
网站建设 2026/9/12 3:01:35

React useEffect对象监听:依赖数组原理与五种可靠方案

1. 先看现象&#xff1a;useEffect到底能不能监听对象这个问题几乎是所有React开发者绕不过去的一道坎&#xff0c;社群里隔三差五就有类似的提问&#xff1a;“我useEffect的依赖数组里传了一个对象&#xff0c;为什么改了里面的属性却不触发&#xff1f;”“为什么我传了对象…

作者头像 李华
网站建设 2026/9/12 3:01:34

基于Spring Boot的校园访客管理系统设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 3:00:50

量子蚁群算法、Grover搜索与量子神经网络:MATLAB实现与参数调优

简介&#xff1a;面向量子计算方向的科研初学者与算法爱好者&#xff0c;这份基于MATLAB的程序包提供了量子蚁群算法、量子格罗弗算法、量子神经网络算法等多类量子算法的可运行实现&#xff0c;可帮助读者快速搭建实验环境&#xff0c;理解不同算法的迭代机制与参数影响。压缩…

作者头像 李华
网站建设 2026/9/12 3:00:38

Apache Fesod流式解析原理与EasyExcel迁移实战

1. 从EasyExcel切换到Apache Fesod&#xff1a;不是跟风&#xff0c;是业务压测后的真实决策我去年在做一套供应链对账系统时&#xff0c;每天要处理300家供应商上传的Excel对账单&#xff0c;单文件平均2.8万行、42列&#xff0c;含合并单元格、多级表头、跨页合计、条件格式和…

作者头像 李华