Skip to content

Computing our witness

What is a witness?

Before creating the proof, we need to calculate all the signals of the circuit that match all the constraints of the circuit. For that, we will use the Wasm module generated bycircom that helps to do this job. It can also be done with the C++ code in a similar way (see below).

Let us start with the Wasm code. Using the generated Wasm binary and three JavaScript files, we simply need to provide a file with the inputs and the module will execute the circuit and calculate all the intermediate signals and the output. The set of inputs, intermediate signals and output is called witness.

In our case, we want to prove that we are able to factor the number 33. So, we assign a = 3 and b = 11.

Note that we could assign the number 1 to one of the inputs and the number 33 to the other. So, our proof does not really show that we are able to factor the number 33.

We need to create a file named input.json containing the inputs written in the standard json format.

We use strings instead of numbers because JavaScript does not work accurately with integers larger than 253.

{"a": "3", "b": "11"}

Now, we calculate the witness and generate a binary file witness.wtns containing it in a format accepted by snarkjs.

After calling the circom compiler with the flag --wasm and the circuit multiplier2.circom we can find a multiplier2_js folder that contains the Wasm code in multiplier2.wasm and all the needed JavaScript files.

Computing the witness with WebAssembly

Enter in the directory multiplier2_js, add the input in a file input.json and execute:

node generate_witness.js multiplier2.wasm input.json witness.wtns

Computing the witness with C++

As a faster alternative, we can use the C++ directory to compute the witness using the previous file input.json. This directory is created when using the circom compiler with the flag --c. In our example, the compiler creates a multiplier2_cpp folder that contains all the C++ code needed to compute the witness and a Makefile to easily generate the corresponding executable program.

To do so, enter the directory multiplier2_cpp and execute:

make

The previous command creates an executable called multiplier2.

Note. To compile the C++ source, we rely on some libraries that you need to have installed in your system. In particular, we use nlohmann-json3-dev, libgmp-dev and nasm.

After the executable is created, we execute it indicating the input file and the name for the witness file:

./multiplier2 input.json witness.wtns

The Witness file

The two programs will generate the same ẁitness.wtns file. This file is encoded in a binary format compatible with snarkjs, which is the tool that we use to create the actual proofs.

Note. For big circuits, the C++ witness calculator is significantly faster than the WASM calculator.