Prepare ZK proof generation

Before users can create a ZK proofs, the following parts need to be prepared. Some of it can be skipped if the user has already completed a verification. This can be checked by querying verification soul-bound-tokens from the blockchain (see Handle Verification SBTs).

Preparation on user side

The user needs to hold zkCerts in the wallet before they can be used in a proof. The Galactica passport portal guides the user through the setup process. It lists KYC providers for issuing the zkKYC issued and offers management options to import zkKYCs in the Galactica Snap.

Other kinds of zkCerts that are not managed by by the passport portal yet, can also be imported through the JSON-RPC API.

Preparation on developer side

Data in zkCerts can prove a wide range of statements. The Galactica Snap provides a generalized prove method that can be parameterized for the ZK proof that you need.

First you need to decide what kind of statements the users of your DApp should proof to be able to use it:

  • Galactica provides common use cases, such as a zkKYC and zkKYC+age proof For these common proofs, you might be able to reuse an already completed verification (See the section on "Handle Verification SBTs"). Specifications for standardization can be found as Galactica improvement proposals.

  • Custom ZK statements can be proven by building a ZK circuit for it using the circom2 framework. You can find various component templates in the Galactica ZK circuit library to build upon.

According to the kind of statement the user is going to prove we need to provide the following parameters to the Galactica Snap:

 * Parameter for requests to generate a zkKYC proof.
export type GenZkProofParams<ProofInputType> = {
  // An object, containing public ZKP input for the statements to be shown by the generated proof.
  input: ProofInputType;

  requirements: {
    // For the standard of the zkCertificate that should be used for the proof.
    zkCertStandard: ZkCertStandard;
    // EVM address where the zkCertificate is registered.
    registryAddress: string;

  // Prover to generate the ZKP.
  prover: ProverData;

  // String with the account address the user is going to use to submit the proof.
  userAddress: string;

  // Description of disclosures made by the proof
  // This is provided by the front-end. The snap can not verify if the prover matches this description.
  // General description of the ZKP
  description: string;
  // Short description of each public input the proof is disclosing
  publicInputDescriptions: string[];

input and requirements are derived from the ZK circuit you use and the type of zkCert it requires as input.

The prover contains ZK circuit specific generation code (as wasm) and the cryptographic setup (zkeyHeader and zkeySections). These are not in the usual circom format, because they have to be passed in JSON through the RPC API and because of restrictions in the secure Snap execution environment. Therefore we use the base64 encoding.

Compiling the ZK circuit yields the data for those fields. You can check out the galactica-monorepo and follow follow the install and compile instructions in the README of the zk-certificate package. Afterwards you can find the .wasm and .zkey files in circuits/build and the test input file in circuits/input.

The following script generates the JSON data file for the front-end from the compiled circom output. It takes a test input file to check that the prover works correctly.

cd packages/snap
yarn run proofPrep --circuitName <name>

This generates the file packages/galactica-dapp/public/provers/<name>.json which can be imported in the front-end to get the wasm, zkeyHeader and zkeySections we need.

Please note that, depending on the type of proof, the file can get quite large. For an zkKYC+age proof, the file is 31MB large.

For the example, the prover JSON file is already provided for simplicity, so you do not have to compile the circom circuit first.

Last updated