coCircom and coNoir are tools for building coSNARKs, a new technology that enables multiple distrusting parties to collaboratively compute a zero-knowledge proof (ZKP). They leverage the existing domain-specific languages circom and Noir to define arithmetic circuits. With coCircom, all existing circom circuits can be promoted to coSNARKs without any modification to the original circuit.
Additionally, coCircom is fully compatible with the Groth16 and Plonk backends of snarkjs, the native proving systems for circom. Proofs built with coCircom can be verified using snarkjs, and vice versa.
The project is built with pure Rust and consists of multiple libraries:
- circom-mpc-vm: A MPC-VM that executes the circom file in a distributed manner (building the extended witness).
- circom-mpc-compiler: A compiler that generates the MPC-VM code from the circom file.
- circom-types: A library for serialization and deserialization of snarkjs artifacts, such as ZKeys and R1CS files.
- co-groth16: A library for verifying and proving a Groth16 coSNARK, verifiable by snarkjs.
- co-plonk: A library for verifying and proving a Plonk coSNARK, verifiable by snarkjs.
- co-circom-snarks: A library for the shared code of co-plonk and co-groth16.
The following libraries are agnostic to coCircom and will be used in the future for other coSNARKs:
- mpc-core: Implementation of MPC protocols.
- mpc-net: Network library for MPC protocols.
The binary co-circom
is a CLI tool that uses the libraries to build a coSNARK
(source found in the co-circom folder).
- Install Rust. You can find the instructions here.
- Install the circom ecosystem. You can find the instructions here.
-
You can find the latest release here.
-
Download the binary for your operating system.
-
Extract the binary from the archive
tar xf co-circom-YOUR_ARCHITECTURE.tar.gz
- Make the binary executable (if necessary):
chmod +x co-circom
- Clone the repository:
git clone https://github.com/TaceoLabs/co-snarks
- Build the project:
cd co-circom && cargo build --release
- You can find the binary in the
target/release
directory.
You can find the documentation of coCircom here.
This section covers the necessary steps to build a Groth16 coSNARK using the previously
installed coCircom binary. For demonstration purposes, we will use a simple
circuit called adder.circom
.
pragma circom 2.0.0;
template Adder() {
signal input a;
signal input b;
signal output c;
c <== a + b;
}
component main = Adder();
With this circuit, we can prove that we know two numbers that sum up to c
.
While this is a basic example, it is sufficient for demonstration purposes. We
will use a replicated secret sharing scheme with 3 parties for all steps
(denoted as REP3 in the commands).
First, we need to generate the R1CS file from the circom file. We use circom for this step:
circom adder.circom --r1cs
Next, we need to perform the Groth16 setup using circom and snarkjs. Refer to the circom documentation for detailed instructions up to the "Generating a Proof" section.
For the following steps, we call the ZKey file adder.zkey
.
This step involves handling inputs from either a single party or multiple distrusting parties.
If the input comes from a single party, we simply split (secret-share) the
input. Assume we have a file named input.json
with the following content:
{
"a": "3",
"b": "4"
}
To split the input, use the following command:
mkdir out && ./co-circom split-input --circuit adder.circom --input input.json --protocol REP3 --curve BN254 --out-dir out/
This command will generate secret-shared inputs in the out
directory, creating separate files for each party. These files will be named input.json.0.shared
, input.json.1.shared
, and input.json.2.shared
, corresponding to the shares for each respective party.
Note: In practice, it is crucial that each party has exclusive access to their respective file. Sharing these files across parties compromises the security of the shared witness.
When the input comes from multiple parties, each party first secret-shares their
respective inputs locally. For example, consider two input files: input0.json
:
{
"a": "3"
}
input1.json
:
{
"b": "4"
}
In practice, these files would typically reside on different machines. Each party secret-shares their input individually:
mkdir out && ./co-circom split-input --circuit adder.circom --input input0.json --protocol REP3 --curve BN254 --out-dir out/
The parties then send their shares to the computing nodes, which can merge the shares. All computing nodes execute the following command (provided here for the first party):
./co-circom merge-input-shares --inputs out/input0.json.0.shared --inputs out/input1.json.0.shared --protocol REP3 --curve BN254 --out out/input.json.0.shared
To generate the witness, we execute the circuit with the secret-shared input obtained from the previous step. Additionally, computing nodes require networking configuration files and TLS key material. Examples of these configurations can be found in the configs and key materials in the keys directory. Refer to our documentation for detailed configuration instructions.
All parties execute the following command (provided here for the first party):
./co-circom generate-witness --input out/input.json.0.shared --circuit adder.circom --protocol REP3 --curve BN254 --config configs/party1.toml --out out/witness.wtns.0.shared
Note: You need to execute three nodes in parallel. This command will block until all nodes have finished, so you will likely need three separate terminals ;)
Next, we generate the proof. Each computing node executes the following command:
./co-circom generate-proof groth16 --witness out/witness.wtns.0.shared --zkey adder.zkey --protocol REP3 --curve BN254 --config configs/party1.toml --out proof.0.json --public-input public_input.0.json
Remember to execute this command on all three nodes.
You can verify the proof using either coCircom or snarkjs. Here's the command for using coCircom:
./co-circom verify groth16 --proof proof.0.json --vk verification_key.json --public-input public_input.0.json --curve BN254
Note: The verification_key.json
was generated in Step 2.
For more examples, please refer to the examples folder. You'll find bash scripts there that demonstrate all the necessary steps, as well as scripts for using Plonk instead of Groth16.
If you would like to contribute to the project, please refer to the contribution page.
This project is licensed under either the MIT License or the Apache, at your choice.
SPDX-License-Identifier: Apache-2.0 OR MIT
Select sub-libraries within this project have different licenses, reflecting their dependencies on circom.
- co-circom: Licensed under GPL-3.0
SPDX-License-Identifier: GPL-3.0-only
. - circom-mpc-compiler: Licensed under GPL-3.0
SPDX-License-Identifier: GPL-3.0-only
.
This software is experimental and un-audited, provided on an "as is" and "as available" basis. We do not provide any warranties, express or implied, including but not limited to warranties of merchantability or fitness for a particular purpose. We will not be liable for any losses, damages, or issues arising from the use of this software, whether direct or indirect.
Users are encouraged to exercise caution and conduct their own independent assessments and testing. By using this software, you acknowledge and accept the risks associated with its experimental nature and agree that the developers and contributors are not responsible for any consequences resulting from its use.