name: midnight-proofs:proof-generation
description: 用于在服务器端生成ZK证明、构建证明即服务后端、从客户端卸载证明计算、创建证明生成队列或实现异步证明生成的场景。
证明生成
在服务器端生成ZK证明,以减轻客户端设备的计算负担,并构建可扩展的证明即服务后端。
使用时机
- 构建为客户端生成证明的后端服务
- 从移动设备或低功耗设备卸载证明计算
- 为高吞吐量应用创建证明生成队列
- 实现带状态轮询的异步证明生成
- 处理证明生成超时和错误
核心概念
服务器端证明 vs 客户端证明
| 方面 |
客户端 |
服务器端 |
| 隐私性 |
见证数据保留在本地 |
见证数据发送至服务器(可加密) |
| 延迟 |
受设备性能限制 |
使用快速专用硬件 |
| 可扩展性 |
一次一个证明 |
并行证明生成 |
| 用例 |
对隐私要求高的应用 |
高吞吐量服务 |
证明生成流程
- 接收请求 - 接受见证数据和电路标识符
- 加载电路 - 检索电路的证明密钥
- 生成证明 - 使用见证输入执行证明器
- 返回证明 - 将证明字节发送回客户端
// 服务器端证明生成概述
async function generateProof(request: ProofRequest): Promise<ProofResponse> {
const { circuitId, witness } = request;
// 加载电路证明密钥
const provingKey = await loadProvingKey(circuitId);
// 生成证明(CPU密集型)
const proof = await prover.prove(provingKey, witness);
return { proof, circuitId };
}
见证数据处理
见证数据包含电路的私有输入。在服务器端处理时:
- 传输中加密 - 使用TLS并考虑额外加密
- 最小化保留 - 证明生成后立即删除见证数据
- 审计日志 - 记录证明请求(非见证内容)用于调试
- 访问控制 - 对证明请求进行身份验证和授权
参考资料
示例
快速开始
1. 设置证明器服务
import { createProver } from '@midnight-ntwrk/midnight-js-prover';
const prover = await createProver({
// 电路证明密钥路径
circuitKeysPath: './circuit-keys',
// 证明生成的内存限制
memoryLimit: 4096, // MB
});
2. 创建证明端点
import express from 'express';
const app = express();
app.use(express.json());
app.post('/api/prove', async (req, res) => {
const { circuitId, witness } = req.body;
try {
const proof = await prover.prove(circuitId, witness);
res.json({ success: true, proof: proof.toString('base64') });
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
3. 处理异步请求
// 对于长时间运行的证明,使用异步模式
app.post('/api/prove/async', async (req, res) => {
const { circuitId, witness } = req.body;
// 创建作业ID
const jobId = crypto.randomUUID();
// 将证明生成加入队列
await proofQueue.add({ jobId, circuitId, witness });
// 立即返回作业ID
res.json({ jobId, status: 'queued' });
});
// 轮询状态
app.get('/api/prove/status/:jobId', async (req, res) => {
const job = await proofQueue.getJob(req.params.jobId);
if (!job) {
return res.status(404).json({ error: 'Job not found' });
}
if (job.status === 'completed') {
return res.json({ status: 'completed', proof: job.result });
}
res.json({ status: job.status });
});
常见模式
请求验证
import { z } from 'zod';
const ProofRequestSchema = z.object({
circuitId: z.string().min(1),
witness: z.record(z.unknown()),
timeout: z.number().optional().default(60000),
});
function validateProofRequest(body: unknown) {
return ProofRequestSchema.parse(body);
}
超时处理
async function proveWithTimeout(
circuitId: string,
witness: WitnessData,
timeoutMs = 60000
): Promise<Proof> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
return await prover.prove(circuitId, witness, {
signal: controller.signal,
});
} finally {
clearTimeout(timeout);
}
}
健康检查端点
app.get('/health', async (req, res) => {
try {
// 验证证明器是否就绪
const isReady = await prover.isReady();
res.json({
status: isReady ? 'healthy' : 'degraded',
proverReady: isReady,
uptime: process.uptime(),
});
} catch (error) {
res.status(503).json({ status: 'unhealthy', error: error.message });
}
});
错误分类
enum ProofErrorCode {
INVALID_WITNESS = 'INVALID_WITNESS',
CIRCUIT_NOT_FOUND = 'CIRCUIT_NOT_FOUND',
PROOF_GENERATION_FAILED = 'PROOF_GENERATION_FAILED',
TIMEOUT = 'TIMEOUT',
OUT_OF_MEMORY = 'OUT_OF_MEMORY',
}
class ProofError extends Error {
constructor(
public code: ProofErrorCode,
message: string,
public details?: unknown
) {
super(message);
this.name = 'ProofError';
}
}
性能考量
| 关注点 |
缓解措施 |
| CPU密集型的证明生成 |
使用工作线程或独立进程 |
| 证明过程中的内存峰值 |
设置内存限制,监控使用情况 |
| 请求超时时间长 |
使用异步作业队列模式 |
| 电路密钥加载时间长 |
在启动时预加载密钥 |
相关技能
proof-verification - 验证生成的证明
proof-caching - 缓存证明组件以提高性能
prover-optimization - 为生产工作负载调整证明器
相关命令
当前未定义。