零知识证明(ZKP)是一种密码学协议,证明者使验证者相信某个陈述为真,而不透露除该陈述为真之外的任何信息。该协议基于三个性质:完备性、可靠性和零知识性。在实践中,现代系统使用非交互式证明,如 zk-SNARK 和 zk-STARK,它们生成一个简短的产物,任何验证者都可以检查。本指南解释了心智模型,演示了针对 RPC 端点的可运行验证工作流,并展示了如何在不编造基准数字的情况下测量证明验证行为。
零知识证明实际保证了什么
在密码学中,零知识证明是两方之间的协议:持有秘密见证的证明者和持有公开陈述的验证者。证明者希望使验证者相信该陈述为真——例如,“我知道与此公钥对应的私钥”或“此交易守恒价值”——而不交出见证本身。验证者只获知该陈述为真这一比特信息。
这比普通认证提供了更强的保证。密码检查会向服务器泄露密码;签名会泄露消息;ZKP 既不泄露见证,也不泄露任何中间计算。这一性质正是零知识证明密码学支撑隐私保护身份、机密交易和公共网络上的可验证计算的原因。
形式化定义可追溯到 1985 年 Goldwasser、Micali 和 Rackoff 的论文《交互式证明系统的知识复杂性》,该论文引入了至今仍在使用的证明者-验证者框架。NIST 的隐私增强密码学项目将 ZKP 视为核心 PEC 技术,并指出其在其他协议(如安全多方计算)中用于确立正确行为。
- 证明者:持有见证并生成证明。
- 验证者:持有公开陈述并检查证明。
- 见证:绝不能传输的秘密输入。
- 陈述:被证明的公开声明,例如哈希或余额约束。
每个 ZKP 必须满足的三个性质
任何声称是零知识证明的协议都必须满足三个性质。这些是您应该测试的验收标准,而不是营销声明。
完备性: 如果陈述为真且双方诚实遵循协议,验证者接受。在有效输入上失败的证明系统是有缺陷的。
可靠性: 如果陈述为假,任何不诚实的证明者都无法说服验证者,除非概率可忽略。可靠性是防止伪造证明在链上被接受的关键。
零知识性: 如果陈述为真,验证者除其真实性外不获知任何信息。形式上,这通过一个模拟器来证明,该模拟器可以在没有见证的情况下生成与真实记录不可区分的记录。
- 完备性——诚实的证明者,真实的陈述,验证者接受。
- 可靠性——不诚实的证明者,虚假的陈述,验证者以压倒性概率拒绝。
- 零知识性——记录不泄露关于见证的任何信息。
交互式与非交互式证明系统
早期的 ZKP 是交互式的:证明者和验证者交换多轮挑战-响应。经典例子是色盲朋友和两个球,或阿里巴巴洞穴,其中重复使作弊概率趋近于零。交互式证明非常适合教学,但对区块链来说很别扭,因为验证者必须在线,且记录随每一轮增长。
非交互式证明将交换压缩为单条消息。证明者运行设置、计算证明并发布;任何验证者都可以稍后检查,无需进一步通信。这是生产系统中使用的形式。两个主要家族是 zk-SNARK(简洁非交互式知识论证)和 zk-STARK(可扩展透明知识论证)。
这种权衡对基础设施很重要。SNARK 通常生成非常小的证明和廉价的验证,但需要可信设置仪式。STARK 避免可信设置并依赖基于哈希的假设,但证明更大。两者并非普遍更好;选择取决于验证成本、证明大小以及您可以容忍的信任模型。
- zk-SNARK:小证明、快速验证、许多构造中需要可信设置。
- zk-STARK:透明设置、更大的证明、基于哈希的安全假设。
- 递归证明:在一个证明内验证另一个证明,以压缩长计算历史。
测试 ZKP 流水线前的先决条件和假设
在运行任何验证工作流之前,请确认以下内容。本指南假设您有一个可用的 RPC 端点,用于证明或验证者合约所在的网络,并且您可以读取合约状态或提交只读调用。
您需要:一个 JSON-RPC URL(使用占位符如 RPC_URL,切勿提交真实凭据)、一个验证者合约地址或本地验证者二进制文件,以及一个已知良好的证明产物及其公共输入。如果您正在测试 zk-rollup,您还需要证明所要证实的批次或状态根。
关于端点选择,本页保持方法论重点。如果您需要针对特定链的具体提供商推荐,请使用 RPC Assistant,而不是猜测端点。有关更广泛的基础设施背景,请参阅多链 RPC 端点指南和RPC 端点指南。
心智模型:陈述、见证、证明、验证者
记住四个对象。陈述是公开且固定的。见证是私有的,只有证明者知道。证明是证明算法产生的产物。验证者是一个确定性函数,接受陈述和证明并返回接受或拒绝。
以太坊文档中一个有用的类比是带有防篡改印章的不透明信封:验证者可以确认算术而不打开信封。用密码学术语来说,印章是证明,隐藏的内容是见证。
关键的工程后果:验证必须廉价且确定性,因为它在链上或轻客户端中运行。证明可能很昂贵,通常在链下完成。当您测量 ZKP 系统时,几乎总是将证明时间和证明大小与验证时间分开测量。
可运行诊断:通过 JSON-RPC 查询验证者合约
以下 curl 调用对验证者合约执行只读 eth_call。将 RPC_URL、VERIFIER_ADDRESS 和 calldata 替换为您自己部署中的值。所示选择器是占位符;使用验证者的 ABI 编码真实函数和证明字节。
此步骤在您尝试完整证明提交之前,确认连接性以及验证者对格式良好的调用有响应。
curl -s -X POST "$RPC_URL" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_call",
"params": [{
"to": "VERIFIER_ADDRESS",
"data": "0xPROOF_AND_PUBLIC_INPUTS_CALLDATA"
}, "latest"]
}'JavaScript 中的可运行验证脚本
下面的脚本通过 JSON-RPC 客户端发送相同的调用,并打印解码后的布尔值。它将传输错误与验证失败分开,这在调试时至关重要:被拒绝的证明和不可达的节点看起来非常不同,绝不能混为一谈。
首先针对已知有效的证明运行它,然后针对故意损坏的证明运行,以确认可靠性行为。正确的验证者必须对损坏的输入返回 false。
const RPC_URL = process.env.RPC_URL;
const VERIFIER = process.env.VERIFIER_ADDRESS;
async function verify(calldata) {
const res = await fetch(RPC_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'eth_call',
params: [{ to: VERIFIER, data: calldata }, 'latest']
})
});
const json = await res.json();
if (json.error) throw new Error(`RPC error: ${json.error.message}`);
return json.result;
}
verify(process.env.VALID_CALLDATA)
.then(r => console.log('valid proof result:', r))
.catch(e => console.error(e.message));
verify(process.env.CORRUPTED_CALLDATA)
.then(r => console.log('corrupted proof result:', r))
.catch(e => console.error(e.message));预期验证结果和测量表
正确的流水线产生可预测的模式:有效证明返回真值结果(通常为 0x...01),损坏的证明返回假值结果(0x...00),格式错误的 calldata 返回 RPC 错误而不是布尔值。将每个结果记录在结果表中,以便行为可复现。
不要填写您未测量的数字。下表是模板;从您自己的运行中填充时间和大小列。分别测量证明时间、证明大小和验证时间,并至少运行十次以观察方差。
- | 案例 | 输入 | 预期结果 | 观察结果 | 证明时间(毫秒) | 证明大小(字节) | 验证时间(毫秒) |
- | 有效证明 | 已知良好产物 | 接受 | (测量) | (测量) | (测量) | (测量) |
- | 损坏证明 | 证明中翻转字节 | 拒绝 | (测量) | 不适用 | (测量) | (测量) |
- | 错误公共输入 | 不匹配的陈述 | 拒绝 | (测量) | 不适用 | (测量) | (测量) |
- | 格式错误 calldata | 截断字节 | RPC 错误 | (测量) | 不适用 | 不适用 | 不适用 |
排查常见的 ZKP 验证失败
大多数失败属于少数几类。按顺序隔离它们:传输、编码、陈述不匹配,然后证明有效性。
传输失败表现为超时或 JSON-RPC 错误。检查端点、链 ID 和速率限制。当您运行重复验证调用时,专用节点可减少争用;有关操作模型,请参阅专用节点基础设施。
编码失败通常意味着 calldata 与验证者 ABI 不匹配。从 ABI 重新编码并确认函数选择器。
陈述不匹配发生在证明时使用的公共输入与验证时提交的公共输入不同时。对两边的公共输入进行哈希并比较。
证明有效性失败意味着验证者正确拒绝了证明。重新运行证明者,确认设置参数匹配,并检查见证满足每个约束。
- 超时或 429——端点或速率限制,不是证明问题。
- 无原因回滚——ABI 或 calldata 不匹配。
- 持续为假——公共输入不匹配或证明无效。
- 间歇性为假——输入序列化中的非确定性。
零知识证明密码学的局限性和权衡
ZKP 功能强大但并非没有代价。证明计算量大,通常比原生执行昂贵几个数量级。可信设置如果毒性废物未被销毁,会引入仪式风险。验证者合约增加链上部署的 gas 成本和字节码大小。
工具链中也存在信任边界:电路、编译器或证明库中的错误可能产生验证通过但证实错误陈述的证明。对于高价值系统,电路的形式化验证和独立审计不是可选项。
最后,零知识性是协议的性质,而不是其周围应用的性质。即使证明本身是零知识的,元数据、时序和网络级关联仍可能泄露信息。
下一步:从证明验证到生产基础设施
一旦您能复现接受/拒绝模式并填写了测量表,就转向运营关注点:负载下的端点可靠性、证明提交重试以及验证者合约事件的监控。
有关特定网络的部署细节,请浏览支持的网络。有关容量规划和成本,请查看RPC 定价和API 服务概述。如果您需要针对特定链的具体端点推荐,请询问 RPC Assistant,而不是硬编码未经验证的 URL。
合理的进展是:本地验证、针对测试网端点验证,然后针对带有监控的专用生产端点验证。每个阶段都应重用相同的结果表,以便回归可见。