name: midnight-proofs:proof-verification
description: 在服务器端验证ZK证明,在交易提交前验证证明,构建验证网关,实现批量验证,或调试证明生成问题。
证明验证
在向网络提交交易之前,在服务器端验证ZK证明,以尽早捕获无效证明并减少失败交易。
何时使用
- 在向网络提交交易之前验证证明
- 为传入的证明构建验证网关
- 为高吞吐量系统实现批量验证
- 作为API请求的一部分检查证明有效性
- 调试证明生成问题
关键概念
为什么要在服务器端验证?
| 好处 |
描述 |
| 快速失败 |
在网络提交前捕获无效证明 |
| 节省Gas |
避免为无效证明支付交易费用 |
| 更好的用户体验 |
向用户提供即时反馈 |
| 安全性 |
验证来自不受信任客户端的证明 |
验证 vs 校验
- 验证 - 密码学检查,确保证明对电路有效
- 校验 - 业务逻辑检查(例如,正确的公共输入)
// 同时进行验证和校验
async function verifyAndValidate(proof: Proof, publicInputs: PublicInputs): Promise<boolean> {
// 步骤1: 密码学验证
const isValidProof = await verifier.verify(proof, publicInputs);
if (!isValidProof) return false;
// 步骤2: 业务校验
const isValidBusiness = validateBusinessRules(publicInputs);
return isValidBusiness;
}
验证性能
验证比证明生成快得多:
| 操作 |
典型持续时间 |
| 证明生成 |
5-30 秒 |
| 证明验证 |
10-100 毫秒 |
参考资料
示例
快速开始
1. 设置验证器
import { createVerifier } from '@midnight-ntwrk/midnight-js-verifier';
const verifier = await createVerifier({
verificationKeysPath: './circuit-keys',
});
2. 验证单个证明
async function verifyProof(
circuitId: string,
proof: Uint8Array,
publicInputs: Record<string, unknown>
): Promise<boolean> {
try {
const result = await verifier.verify(circuitId, proof, publicInputs);
return result.valid;
} catch (error) {
console.error('验证失败:', error);
return false;
}
}
3. 提交前验证
async function submitWithVerification(
transaction: Transaction
): Promise<string> {
// 从交易中提取证明和公共输入
const { proof, publicInputs, circuitId } = transaction;
// 先验证
const isValid = await verifyProof(circuitId, proof, publicInputs);
if (!isValid) {
throw new Error('证明验证失败');
}
// 提交到网络
return await submitTransaction(transaction);
}
常见模式
验证网关
import express from 'express';
const app = express();
app.post('/api/verify', async (req, res) => {
const { circuitId, proof, publicInputs } = req.body;
try {
const result = await verifier.verify(
circuitId,
Buffer.from(proof, 'base64'),
publicInputs
);
res.json({
valid: result.valid,
circuitId,
verificationTime: result.duration,
});
} catch (error) {
res.status(400).json({
valid: false,
error: error.message,
});
}
});
批量验证
interface ProofBatch {
circuitId: string;
proof: Uint8Array;
publicInputs: Record<string, unknown>;
}
async function verifyBatch(
proofs: ProofBatch[]
): Promise<Map<number, boolean>> {
const results = new Map<number, boolean>();
// 并行验证
const verifications = proofs.map(async (p, index) => {
try {
const result = await verifier.verify(
p.circuitId,
p.proof,
p.publicInputs
);
results.set(index, result.valid);
} catch {
results.set(index, false);
}
});
await Promise.all(verifications);
return results;
}
缓存已验证的证明
import { createHash } from 'crypto';
const verifiedProofs = new Map<string, boolean>();
function proofHash(proof: Uint8Array, publicInputs: Record<string, unknown>): string {
const data = JSON.stringify({ proof: proof.toString(), publicInputs });
return createHash('sha256').update(data).digest('hex');
}
async function verifyWithCache(
circuitId: string,
proof: Uint8Array,
publicInputs: Record<string, unknown>
): Promise<boolean> {
const hash = proofHash(proof, publicInputs);
// 检查缓存
if (verifiedProofs.has(hash)) {
return verifiedProofs.get(hash)!;
}
// 验证
const result = await verifier.verify(circuitId, proof, publicInputs);
verifiedProofs.set(hash, result.valid);
return result.valid;
}
带超时的验证
async function verifyWithTimeout(
circuitId: string,
proof: Uint8Array,
publicInputs: Record<string, unknown>,
timeoutMs = 5000
): Promise<boolean> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const result = await verifier.verify(circuitId, proof, publicInputs, {
signal: controller.signal,
});
return result.valid;
} catch (error) {
if (error.name === 'AbortError') {
throw new Error('验证超时');
}
throw error;
} finally {
clearTimeout(timeout);
}
}
错误分类
enum VerificationError {
INVALID_PROOF = 'INVALID_PROOF',
INVALID_PUBLIC_INPUTS = 'INVALID_PUBLIC_INPUTS',
CIRCUIT_NOT_FOUND = 'CIRCUIT_NOT_FOUND',
MALFORMED_PROOF = 'MALFORMED_PROOF',
TIMEOUT = 'TIMEOUT',
}
function classifyVerificationError(error: Error): VerificationError {
if (error.message.includes('circuit')) {
return VerificationError.CIRCUIT_NOT_FOUND;
}
if (error.message.includes('public input')) {
return VerificationError.INVALID_PUBLIC_INPUTS;
}
if (error.message.includes('malformed')) {
return VerificationError.MALFORMED_PROOF;
}
if (error.message.includes('timeout')) {
return VerificationError.TIMEOUT;
}
return VerificationError.INVALID_PROOF;
}
性能考虑
| 关注点 |
缓解措施 |
| 验证密钥加载 |
在启动时预加载密钥 |
| 高请求量 |
使用验证缓存 |
| 大批量 |
限制并发验证数量 |
| 内存使用 |
流式处理大型证明批次 |
相关技能
proof-generation - 在服务器端生成证明
proof-caching - 缓存验证结果
prover-optimization - 优化创建证明的证明器
相关命令
当前未定义。