Prover Configuration
The prover generates zero-knowledge proofs for transfers and unshields.
Initialization
Initialize the prover once at app startup:
typescript
import { createProver, setGlobalProver } from '@zkprivacy/sdk';
const prover = await createProver({
transferCircuit: '/circuits/transfer.json',
unshieldCircuit: '/circuits/unshield.json',
});
setGlobalProver(prover);TIP
Prover initialization takes 2-5 seconds. Show a loading state during this time.
Circuit Sources
Browser (URLs)
Fetch circuits from your public folder:
typescript
const prover = await createProver({
transferCircuit: '/circuits/transfer.json',
unshieldCircuit: '/circuits/unshield.json',
});Node.js (File System)
Load circuits from disk:
typescript
import { readFileSync } from 'fs';
const prover = await createProver({
transferCircuit: JSON.parse(
readFileSync('circuits/transfer.json', 'utf-8')
),
unshieldCircuit: JSON.parse(
readFileSync('circuits/unshield.json', 'utf-8')
),
});CDN
Host circuits on a CDN for better caching:
typescript
const prover = await createProver({
transferCircuit: 'https://cdn.example.com/circuits/transfer.json',
unshieldCircuit: 'https://cdn.example.com/circuits/unshield.json',
});Global vs Instance Prover
Global Prover
Set once, used by all PrivacyClient instances:
typescript
setGlobalProver(prover);
// Client uses global prover automatically
const client = new PrivacyClient({ ... });Instance Prover
Pass to specific client:
typescript
const client = new PrivacyClient({
prover, // Use this prover
// ...
});Instance prover takes precedence over global.
Proof Generation Performance
| Circuit | Browser (WASM) | Node.js |
|---|---|---|
| Transfer | 30-60 seconds | 15-30 seconds |
| Unshield | 20-40 seconds | 10-20 seconds |
Factors Affecting Speed
- CPU cores: More cores = faster proving
- Memory: Needs ~2GB available
- Browser: Chrome/Edge faster than Firefox
- Device: Desktop faster than mobile
Memory Requirements
The prover uses significant memory:
| Phase | Memory |
|---|---|
| Circuit loading | ~100MB |
| Proof generation | ~1.5-2GB |
| Peak | ~2.5GB |
Browser Considerations
- Close unnecessary tabs
- Avoid mobile devices for proving
- Consider relayer for constrained devices
Error Handling
typescript
try {
const prover = await createProver({
transferCircuit: '/circuits/transfer.json',
unshieldCircuit: '/circuits/unshield.json',
});
} catch (error) {
if (error.message.includes('Failed to fetch')) {
console.error('Circuit files not found');
} else if (error.message.includes('WASM')) {
console.error('WASM initialization failed');
}
}Checking Prover State
typescript
// Check if prover is ready
if (prover.isReady()) {
await client.transfer({ ... });
} else {
console.log('Prover still initializing');
}Circuit Files
Getting Circuit Files
- From deployed app: Download from
https://devtools.zkprivacy.dev/circuits/ - Build from source:
just build-circuits
Required Files
| File | Size | Purpose |
|---|---|---|
transfer.json | ~500KB | 2-in-2-out transfers |
unshield.json | ~400KB | Withdrawals |
Hosting
Place in your app's public folder:
public/
└── circuits/
├── transfer.json
└── unshield.jsonAdvanced: Manual Proof Generation
For advanced use cases, generate proofs directly:
typescript
const proof = await prover.generateTransferProof({
inputs: [...],
outputs: [...],
spendingKey: ...,
merkleRoot: ...,
// ... other params
});
// proof.proof - the ZK proof bytes
// proof.publicInputs - public inputs for verificationWARNING
Manual proof generation requires careful input construction. Use client.transfer() instead unless you have specific requirements.