import type { CircuitName } from "./prover.js"; /** * Pinned SHA-256 digests of the circuit artifacts. * * WHY THESE ARE PINNED * -------------------- * The witness for `transaction.circom` contains `inPrivateKey[2]` — the note * spending keys. That witness is computed by `transaction.wasm`. So a client * that fetches its witness generator at runtime from a server is trusting that * server with its spending keys just as surely as if it had posted them: a * substituted `.wasm` can copy the witness anywhere it likes, and nothing about * the resulting proof would look wrong. * * That makes artifact integrity the precondition for client-side proving, not a * hardening step after it. A `.zkey` swap is the weaker cousin — it does not * leak the witness, but a key from a setup someone else holds the toxic waste * for lets that person forge proofs. * * These digests were verified against the deployed program, not merely copied * from a build: * * transaction_final.zkey * -> `snarkjs zkey export verificationkey` * -> byte-identical to transaction_verification_key.json * -> alpha/beta/gamma/delta/IC and nPublic=8 all match * privacy-program/programs/privacy-pool/src/vk_constants.rs * * So the pinned zkey is provably the one whose proofs the deployed program * accepts. All eight copies across relayer-server, veilo-dapp and wallet-app * were byte-identical when pinned. * * WHEN A CIRCUIT CHANGES these values must be regenerated in the same pass that * redeploys the verifying key, or every client stops proving. That coupling is * the point: artifacts and on-chain verifier move together or not at all. */ export declare const CIRCUIT_ARTIFACT_SHA256: Record; /** Which artifact of a circuit is being checked. */ export type CircuitArtifactKind = "wasm" | "zkey"; /** Raised when an artifact's contents do not match its pinned digest. */ export declare class CircuitArtifactIntegrityError extends Error { readonly circuit: CircuitName; readonly kind: CircuitArtifactKind; readonly expected: string; readonly actual: string; constructor(circuit: CircuitName, kind: CircuitArtifactKind, expected: string, actual: string); } /** Lowercase hex digest of `bytes`. */ export declare function sha256Hex(bytes: Uint8Array): string; /** * Throw unless `bytes` matches the pinned digest for this artifact. * * Call it on the BYTES, at the point they arrive — a fetched buffer, a file * just read. Verifying a path and then handing the path to snarkjs leaves a * gap between the two reads; verifying the buffer you go on to use does not. */ export declare function assertCircuitArtifactIntegrity(circuit: CircuitName, kind: CircuitArtifactKind, bytes: Uint8Array): void; /** * Verify an artifact and hand back the same bytes, for use inline: * * ```ts * const wasm = checkedCircuitArtifact("transaction", "wasm", await fetchBytes(url)); * ``` */ export declare function checkedCircuitArtifact(circuit: CircuitName, kind: CircuitArtifactKind, bytes: Uint8Array): Uint8Array;