Generate Snakrjs-compatible R1CS and witness

Keelung is a language built by BTQ for quantum-safe zeko-kowledge proofs, for now our default backend is Aurora. However, we also recognize the need to support other industry-standard protocols like Groth16 and PLONK. To meet this demand, we are working 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.

What is Snarkjs?

Snakrjs is primarily designed to work with circuits generated by Circom, another DSL for ZK circuits. it takes CIrcom-generated R1CS and enables the generation and verification of Groth16 and PLONK proofs. As a result, it takes R1CS and witness in Circom's default format, which are different from Keelung's representations. 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 now offers compatibility with Circom/Snarkjs R1CS and witness formats starting from version 0.17.0.

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

$ stack repl

In the following sections, we will use a Keelung program qand 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 ()

Gerating R1CS

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.

ghci> genCircuitBin "quad.r1cs" bn128 quad
Generated binary circuit file at: quad.r1cs
Right "Success"

The command genCircuitBin will generate a file quad.r1cs which is in a binary format that can be accepted by Snarkjs.

Generate Witness

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

ghci> genWtns "quad.wtns" bn128 quad [3,5,-22] [2]
Generated wtns file at: quad.wtns
Right "Success"

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 will fail.

Checking the validity of R1CS and witness

Snarkjs also provide a way for us to check that the .wtns file 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:

snarkjs wtns check quad.r1cs quad.wtns

If succeeds, you should see the following result:


(In Progress) Generate and Verify Groth16/PLONK proofs

Trusted setups are needed for Groth16 and PLONK, Snarkjs has provided functionalities for trusted setups, proof generation and verification. It's worth noting that even though Keelung is capable of generating R1CS and witness that can be validated by Snarkjs, proof generation is still very unstable with zero-knowledge keys (zkeys) produced by Snarkjs.

To install Snarkjs and reproduce our results, run trusted setups, keys generation and proof generation and verification, see the Snarkjs' README (especially the section about trusted setup ceremony and proof generations). We're currently running into some open issues (for example, if we try to verify the zkeys generated with snarkjs zkey verify, we get an error Invalid L section size whereas there's no zkey specification to be found yet), feel free to contact us or suggest solutions in the Keelung compiler repo.

Last updated


Copyright © 2023 BTQ