一个能签交易、能铸NFT、能替我管资产的智能体,每天替我做和真金白银有关的决定。问题恰恰出在这里:它可以说自己查过余额、核过收款方、按正确理由批了付款,但一句声明不等于证据。它要是错了、撒谎了、被黑了,它的话一文不值。
加密世界早就把这条道理用在钱上:不要信任,去验证。zkVerify 的 Agent Games 把同一套原则搬到了智能体身上。我让我的智能体去做了赛事第一条赛道要求的东西——一个 Proof Gatekeeper(证明守门人),它负责裁决带证明的付款请求,并用零知识证明为每一个决定背书。然后我在本地拿赛事自己的电路测了它。
任务本身:一个只有60秒的守门人
按官方现场指南的定义,Proof Gatekeeper 的任务是一份签名的 JSON 信封,描述一笔转账请求。平台把它 POST 到智能体的公开端点,智能体要在 60 秒内给出一个确定性决定——APPROVE 或 REJECT——外加该决定的 Groth16 证明,平台再用自己注册的验证密钥重新验证一遍。
计分规则刻意不对称:正确且验证通过的决定 +12;错误的 REJECT −3;错误的 APPROVE——把一笔坏付款放过去——−6;超时或缺少证明 −2。信号很清楚:粗心比谨慎更糟,慢本身就是失败。
任务并不全是老实的。现场指南记录了七类陷阱:一个有效条件(约占一半任务),外加验证密钥替换、阈值不匹配、证明复用、条件过期、收款方不匹配、金额溢出。只检查“这个证明有效吗”的守门人会把陷阱一路批下去——因为一个证明可以完全有效,却授权了错误的事情。指南把话说得很直白:验证是必要条件,不是充分条件。
我建了什么
整个守门人是一个 Node.js 单文件,不用框架,本地运行。它按顺序做五件事:
- 解析之前先验签名。每个进来的请求都带一个 x-agent-games-signature 头,是对原始请求体的 HMAC-SHA256。服务器先拿原始字节做常量时间比对,签名不对直接返回 401,后面的活一概不做。
- 做决定,失败即关闭。判定逻辑按陷阱清单逐条走:任务格式错误、证明的验证密钥与注册密钥不一致、证明已被用过、余额低于下限、条件过期、收款方不匹配、金额超过上限。任何一项不过就是 REJECT,只有全部检查都活下来的任务才给 APPROVE。拿不准就 REJECT,绝不默认放行。
- 为决定生成证明。对每个可证明的决定,服务器用赛事自己的 gatekeeper.wasm 和 gatekeeper_final.zkey(从官网下载)配合 snarkjs 0.7.6 生成 Groth16 证明。APPROVE 在电路里是 decision 1,REJECT 是 decision 0。如果 APPROVE 的证明生成失败,服务器会失败关闭转为 REJECT,而不是返回一个它证明不了的批准。证明复用的任务按规则不生成任何证明——没有新东西可证。
- 保持幂等。平台可能在网络故障后重试,所以每个响应按任务 ID 缓存,重复的任务 ID 返回字节完全一致的缓存体。
- 给响应签名。每个响应都带自己的 x-agent-games-signature,覆盖原始响应体;服务器不挂起,内部错误返回 500 而不是超时。
一句实话:这个构建里的 HMAC 密钥是本地测试密钥。真实平台的密钥在注册时生成,这个构建从未碰过它。
证明,验证过了
我在活动页面自带的样例场景上跑通了完整闭环:公开余额 1460 对下限 1000,金额 500 对上限 1000,收款方与条件匹配,过期区块 8,430,000 在当前区块 8,420,000 之后,证明的验证密钥等于注册密钥。守门人返回 APPROVE,以及一个能用官方证明密钥导出的验证密钥验过的 Groth16 证明。
测试运行的真实输出:
- 有效任务 → APPROVE,status=200,reason=VALID_CONDITION,totalMs=863,proveMs=843
- Groth16 证明对导出的验证密钥验证通过,verify=true
- 用陷阱输入对 decision=1 做 fullProve 失败:Assert Failed,模板 GatekeeperEvaluation_79 第 102 行
证明生成耗时 843 毫秒,对着 60,000 毫秒的截止线。验证确认了两次:snarkjs.groth16.verify 在进程内返回 true,独立 CLI 运行打印 OK! 且退出码为 0。我还解码了证明的 13 个公开信号,确认它们编码的正是该编码的东西:注册验证密钥的哈希、收款地址、decision 1。
本地检查 12 项全过:有效批准、六类陷阱拒绝且理由码正确、坏 HMAC 的 401、字节一致的重复回放、复用证明的拒绝且不带证明、格式错误任务的拒绝。
最让我满意的是那个故意设计成失败的检查。我把陷阱输入喂给电路,要求它证明 decision 1——也就是硬批——它拒绝了:gatekeeper 模板第 102 行 Assert Failed。电路不会让你证明一个不成立的批准。这正是整件事的意义所在,而且它确实管用。
没对上的地方:验证密钥哈希
不是所有东西都吻合。网站公布了守门人电路的注册验证密钥哈希(0x6b79c6…d77b0)。我从官方证明密钥导出验证密钥,试着复现那个哈希——试了 12 种序列化变体:对紧凑、缩进、排序后的 JSON 做 keccak256 和 SHA-256,只取曲线点字段,展平承诺数据,包装与不包装的形式。没有一个对上。
最可能的解释是 zkVerify(或其 Kurier 服务)对验证密钥用它自己的规范序列化来计算注册哈希,而我没能复现那套序列化。这不影响本地构建:用下载的电路文件生成的证明能对导出的密钥验证通过,产物是自洽的。但我不会声称本地哈希与注册哈希一致。它被检查过,用我试过的方法没对上。如果我把这个构建带进竞技场,补上这个缺口是第一件要做的事——因为平台是用它注册的密钥重新验证证明,不是用我的。
我没做的事
这篇记录的是一个构建,不是一个竞技场成绩。把范围说清楚:
- 没有公开端点。服务器只在 127.0.0.1:8787 上跑过这些测试,现在已经停了。没有隧道,没有托管账号。
- 没有参赛。没有练习任务,没有计分回合,没有积分。
- 没有向 Kurier 或 zkVerify 主网提交任何东西。没有验证密钥注册,没有证明引用,没有任何链上交易。
- 没有资金移动。没花 VFY,没付 gas。总成本:0 美元。
我带着这份记录进创作者赛道,是因为这些工作是真的、数字是可查的——而不是因为我在声称一个我并没有的排行榜位置。
为什么这不只是场比赛的事
我的智能体替我动钱。每一个干这事的智能体——批付款、签合同、管仓位——都是一个迟早要爆发的信任问题。今天我们主要用声誉来解决它:这个智能体昨天表现不错,所以我们假设它今天也不错。那不是验证,那是指望。
守门人模式是更好的答案,它有两半。第一半是证明:一个决定附带任何人都能检查的密码学证据。第二半是指南反复强调的那部分——验证是必要条件,不是充分条件。一个错误命题的有效证明仍然是错的。智能体必须检查被证明的是什么:对的密钥、对的阈值、对的收款方、对的过期时间、一个还没被花掉的证明。密码学执行规则,但智能体仍然得懂规则。
这就是我在这里搭出来的缩微版:先检查,再证明,拒绝批准它证明不了的东西。证明花了 843 毫秒。这堂课花的时间长一点——但这是我会留下的那一课。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.