> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.adid.dev/llms.txt.
> For full documentation content, see https://docs.adid.dev/llms-full.txt.

# ZK Proofs from Mobile

The wallet generates ZK proofs **on device** to keep claim values local. The flow is:

1. User taps **Prove** on a credential and selects a predicate template (e.g., "I am over 18", "I live in EU/UK/US").
2. The wallet calls `POST /api/v1/zkp/challenge` to obtain a fresh nonce (TTL 5 minutes; see `pkg/zkp` in the API).
3. The wallet computes the witness from the credential subject and the user's DID-control private key, then runs the prover (Airbender-compatible circuit; see §3.3.3 [Generating a Proof in the Browser](#generate-zkp) for the desktop counterpart).
4. The proof is submitted via `POST /api/v1/zkp/proofs` with the original challenge bound in.
5. If the user opted in, the wallet then calls the on-chain anchor path — `ZKProofVerifier.submitProof` — through the platform's signer to record an immutable timestamped record (§11.6 [ZKProofVerifier](#zk-proof-verifier)).

> **Note:** mobile devices have stricter memory than browsers; the wallet falls back to the **server-side prover** when the local prover would exceed 200 MB working memory (configurable in `Settings → Advanced → Generate proofs server-side`). When the server proves, the user's `privateKey` is encrypted client-side with the server's ephemeral X25519 key-agreement key from the platform DID Document and zeroed in memory after the request.