Getting Started

This document contains a guide to writing your first Circom circuit with CircomJS.

Creating your project

You can clone the circomjs-starter repository to get started.

The repository looks like this:

All of our project's circuits are grouped inside the ./circuits directory. We have two circuits inside this repository.

  • addition.circom: checks valid addition of two private inputs.

  • multiplication.circom: checks valid multiplication of two private inputs.

There is a src/index.js file that will be executed as a node js program.

circuit.config.json

There is a circuit.config.json file inside the project root, it is the configuration file for CircomJS. This file helps the framework to find your circuits inside the project and build them. The default path for this file is circuit.config.json relative to the current working directory.

You can read more about this file here.

Compiling Circuits

To compile your circuit with CircomJS, you need to instantiate a circuit by calling circomjs.getCircuit() function, the function takes in a unique cID { declared inside the config file } and returns the corresponding circuit as a Circuit instance.

You can then call the circuit.compile() method to compile your circuit. Update your src/index.js to reflect the following code.

src/index.js
const {CircomJS} = require("@zefi/circomjs")

const main = async() => {
    const circomjs = new CircomJS()
    const circuit =  circomjs.getCircuit("mul")
    await circuit.compile()
}

main()

Running the javascript { node src/index.js } file will result in the circuit being compiled and its artifacts being present inside outputDir/circuitFilename directory.

You can try changing the id in circomjs.getCircuit() to add

and you will see the build artifacts of the addition.circom circuit being added to the output directory.

Generating Proof

Once you have compiled your circuit, you can then start generating proofs out of them.

Every Circuit instance has a generateProof method associated with it, which takes a dynamic input in the following format.

input = {
[key: input signal name]: number
}

In our multiplication.circom circuit, x and y are the name of our input signals.

You can continue with the following snippet in src/index.js to generate your first proof.

src/index.js
const main = async() => {av
    const circomjs = new CircomJS()
    const circuit =  circomjs.getCircuit("mul")

    // important to await compilation, before running circuit.genProof()
    await circuit.compile()

    const input = {
        x: 3,
        y: 5
    }
    const proof = await circuit.genProof(input);
    console.log(proof)

}

main()

Run the javascript file again, and you will see ZK proof being logged onto your terminal emulator. The proof is of the following structure.

ZKPROOF = {
    proof: {
        pi_a: any,
        pi_b: any,
        pi_c: any,

            protocol: string
        curve: string
    }
    publicSignals: Array<string>
}

Verifying the generated proof

Circuit instances also has an accompanying verifyProof() function that takes as input a ZKProof generated from the generateProof() function and returns a boolean indicating the validity of the ZK Proof.

You can continue with the following snippet in src/index.js to see the verification in action.

const main = async() => {
    const circomjs = new CircomJS()
    const circuit =  circomjs.getCircuit("mul")

    // important to await compilation, before running circuit.genProof()
    await circuit.compile()

    const input = {
        x: 3,
        y: 5
    }
    
    const proof = await circuit.genProof(input);
    
    const res = await circuit.verifyProof(input);
    if(res){
        console.log("verification succeed")
    }
    else{
        console.log("verification failed")
    }

}

main()

You can now run this javascript file, and you will see "verification succeed" logged onto your terminal emulator!

CircomJS in your workflow

This section marks the end of this tutorial, but we want to leave you with some ideas on how you can use CircomJS in your daily workflow.

Building Circuits

You can use it to build your circuits, rather than relying on writing shell scripts to setup your build, you can declare them in a circuit.config.json file, and then make a simple call to circuit.compile() to get your builds.

We are working on adding support for the C-runtime, automatic compilation optimizations and more granular control over the compilation process.

Proof generation & verification

CircomJS gives you the ability to generate proofs in a high-level programming language { we also provide typescript types for the framework } and make it simple to consume in applications and verify them!

Testing

CircomJS makes way for easy testing of circuits, you can use the library to test your circuits in a framework of your choice, be it jest , mocha or any else.

Thanks for going through this page, you can head to the other sections of this Gitbook for more info about CircomJS. Feel free to reach out to us at { contact@zefi.io } if you have any feedback.

Last updated