name: midnight-dapp:proof-handling description: 在构建ZK证明的见证数据、向用户展示证明生成进度、实现披露同意流程、处理证明超时和重试、或解释隐私保证时使用。
证明处理
在您的Midnight DApp中构建和呈现零知识证明,从构建见证数据到展示证明生成进度以及处理隐私披露。
何时使用
- 为合约交易构建见证数据
- 向用户展示证明生成进度
- 实现披露同意流程
- 处理证明超时和重试
- 向用户解释隐私保证
核心概念
见证构建
见证是TypeScript函数,为ZK电路提供私有数据。数据保留在本地——只有加密证明上链。
// 见证提供私有输入 - 电路证明您知道它
const witnesses = {
get_secret: ({ privateState }: WitnessContext<PrivateState>): bigint => {
return privateState.secret; // 永远不会离开客户端
}
};
客户端证明
所有证明生成都在用户设备本地进行:
- 绝不在远程服务器上 - 私有数据永远不会离开浏览器
- 证明服务器本地运行 - 端口6300上的Docker容器
- 需要数秒,而非毫秒 - 向用户展示进度UI
- 可能超时 - 为实现可靠性实施重试逻辑
披露用户体验
当电路使用 disclose() 时,用户必须理解他们正在披露什么:
// 这将在链上公开确切值
const disclosedAge = disclose(userAge);
// 用户应该看到:“这将公开您的年龄(25)”
参考文档
| 文档 | 描述 |
|---|---|
| witness-fundamentals.md | 见证模式和类型映射 |
| client-side-proofs.md | 证明服务器设置和性能 |
| disclosure-ux.md | 隐私披露UI模式 |
| web3-comparison.md | 以太坊签名与Midnight证明对比 |
示例
| 示例 | 描述 |
|---|---|
| witness-builder/ | 构建见证对象的函数 |
| proof-progress/ | 证明生成进度组件 |
| disclosure-modal/ | 隐私披露同意模态框 |
快速开始
1. 定义见证类型
interface PrivateState {
secretKey: Uint8Array;
credentials: Map<string, Credential>;
balance: bigint;
}
2. 实现见证
import type { WitnessContext } from "@midnight-ntwrk/midnight-js-types";
const witnesses = {
get_balance: ({ privateState }: WitnessContext<PrivateState>): bigint => {
return privateState.balance;
},
get_credential: (
{ privateState }: WitnessContext<PrivateState>,
credentialId: Uint8Array
): Credential => {
const id = bytesToHex(credentialId);
const credential = privateState.credentials.get(id);
if (!credential) {
throw new WitnessError("凭证未找到", "NOT_FOUND");
}
return credential;
}
};
3. 展示证明进度
function TransferButton({ onTransfer }) {
const { status, progress, error, generateProof } = useProofStatus();
const handleClick = async () => {
const result = await generateProof(async () => {
return contract.callTx.transfer(recipient, amount, witnesses);
});
if (result.success) {
onTransfer(result.transaction);
}
};
return (
<div>
<button onClick={handleClick} disabled={status === "generating"}>
{status === "generating" ? "正在生成证明..." : "转账"}
</button>
{status === "generating" && <ProgressBar value={progress} />}
{error && <ErrorMessage error={error} />}
</div>
);
}
4. 处理披露同意
function DisclosureFlow({ disclosures, onConfirm, onCancel }) {
return (
<DisclosureModal
disclosures={disclosures}
onConfirm={onConfirm}
onCancel={onCancel}
>
<p>此交易将披露以下信息:</p>
<ul>
{disclosures.map((d) => (
<li key={d.field}>
<strong>{d.label}</strong>: {d.value}
</li>
))}
</ul>
</DisclosureModal>
);
}
常见模式
带验证的见证
const witnesses = {
get_credential: (
{ privateState }: WitnessContext<PrivateState>,
credentialId: Uint8Array
): Credential => {
const credential = privateState.credentials.get(bytesToHex(credentialId));
if (!credential) {
throw new WitnessError("凭证未找到", "NOT_FOUND");
}
// 返回前验证
if (credential.expiry < BigInt(Date.now())) {
throw new WitnessError("凭证已过期", "EXPIRED");
}
return credential;
}
};
用于外部数据的异步见证
const witnesses = {
get_oracle_price: async (
{ privateState }: WitnessContext<PrivateState>,
tokenId: Uint8Array
): Promise<bigint> => {
const response = await fetch(`/api/price/${bytesToHex(tokenId)}`);
if (!response.ok) {
throw new WitnessError("价格不可用", "ORACLE_ERROR");
}
const { price } = await response.json();
return BigInt(price);
}
};
证明重试逻辑
async function submitWithRetry(
buildTx: () => Promise<Transaction>,
maxRetries = 3
): Promise<string> {
let lastError: Error | null = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const tx = await buildTx();
const provenTx = await walletAPI.balanceAndProveTransaction(tx, newCoins);
return await walletAPI.submitTransaction(provenTx);
} catch (error) {
lastError = error as Error;
// 用户拒绝时不重试
if (error.message.includes("rejected")) {
throw error;
}
// 重试前等待,使用指数退避
if (attempt < maxRetries) {
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, attempt)));
}
}
}
throw lastError ?? new Error("证明生成失败");
}
安全考虑
- 绝不持久化见证数据 - 仅将私有状态保留在内存中
- 清除敏感数据 - 使用后尽可能将数组清零
- 验证所有输入 - 在见证中检查参数有效性
- 优雅处理错误 - 不要在错误消息中泄露信息
- 披露需用户同意 - 始终展示将要披露的内容
相关技能
wallet-integration- 证明生成前需要钱包连接state-management- 管理见证的私有状态transaction-flows- 提交已证明的交易error-handling- 证明错误消息和恢复
相关命令
/dapp-check- 验证证明服务器配置/dapp-debug proofs- 诊断证明生成问题