Generate Snakrjs-compatible R1CS and witness

Keelung is a language built by BTQ for quantum-safe zeko-kowledge proofs, thus for now our default backend is Aurora. However, we also recognize the need to support other industry-standard protocols such as Groth16 and PLONK. To meet this demand, we have worked on integrating Keelung with existing tools, with a primary focus on Snarkjs. In this section, we will explore how to integrate Snarkjs into your Keelung workflow or vice versa.

What is Snarkjs?

Snakrjs is primarily designed to work with circuits generated by Circom, another DSL for ZK circuits. it is capable of taking CIrcom-generated R1CS and supports the generation and verification of Groth16 and PLONK proofs. It's important to note that Snarkjs expects R1CS and witness data in Circom's default format, which differs from Keelung's representations. Thankfully, Keelung offers Circom/Snarkjs R1CS and witness formats starting from version 0.25.0.

To install Snarkjs to use it along with Keelung, see Snarkjs' README, especially section 1-8 for trusted setup and 15-24 for proof generation and verification.

To generate Snarkjs compatible R1CS and witness files, make sure you have the Keelung compiler installed and navigate to your Keelung project directory. Open the GHCi interface with the following command:

$ stack repl
ghci>

In the following sections, we will use a Keelung program quad as an example, the program can be found in Quad.hs in our examples repo:

quad :: Comp ()
quad = do
    _a :: Field <- input Public
    _b :: Field <- input Public
    _c :: Field <- input Public
    _x :: Field <- input Private
    assert (eq (_a * _x * _x + _b * _x + _c) 0)
    return ()

R1CS Generation

quad takes three public inputs and one private input, we can generate Snarkjs-compatible R1CS with an interface to the compiler, similar to how we generate Aurora proofs.

The command genCircuitBin will generate a file quad.r1cs which is in a binary format that can be accepted by Snarkjs, it is a command parallel to genCircuit which generates Keelung/Aurora compatible R1CS.

Witness Generation

Likewise, the command genWtns (in parallel with genWitness) can be invoked to compute and generate a witness file in the format that can be accepted by Snarkjs.

By providing the public and private inputs as the first and second lists respectively, this command generates a file quad.wtns. Notice that the inputs satisfy the assertion in quad, otherwise the command would fail.

Checking the validity of R1CS and witness

Snarkjs provides a functionality for us to check that the witness we generated satisfies the constraints in the R1CS file. Make sure snarkjs is installed on your machine, and run the following command in your shell:

If it succeeds, you should see the following result:

Generation and Verification of Groth16/PLONK proofs

Trusted setups are needed for Groth16 and PLONK, Snarkjs has provided functionalities for trusted setups, proof generation and verification, see Snarkjs' documentation for more in-depth usages, here we invoke them in simple forms for the purpose of a quick demonstration.

Assuming Snarkjs is installed,

  1. The following commands setups a powers of tau ceremony:

  1. Then you can run a trusted setup depending on your desired protocol, we use the quad program above and PLONK as example:

  1. The verification key can be exported as JSON and sent the verifier:

  1. To generate the proof for a circuit and its witness:

Here we obtain a proof.json along with the public inputs public.json, both of which can now be sent to the verifier.

  1. Snarkjs can be used to verify the proof as well, using the verification key we exported earlier:

Enjoy building with Keelung and Snarkjs!

Last updated