Consensys / gnark

gnark is a fast zk-SNARK library that offers a high-level API to design circuits. The library is open source and developed under the Apache 2.0 license
https://hackmd.io/@gnark
Apache License 2.0
1.43k stars 368 forks source link

Production proving/verifying keys setup for Groth16 BLS12-381 #838

Closed AnnaShaleva closed 1 year ago

AnnaShaleva commented 1 year ago

Problem

I've successfully created the Groth16 circuit and proving/verifying code for it using gnark API as described in https://docs.gnark.consensys.net/Tutorials/eddsa. In this code I've used Groth16 Setup, and the documentation states that:

Note that careful consideration must be given to this step in production environment. groth16.Setup uses some randomness to precompute the Proving and Verifying keys. If the process or machine leaks this randomness, an attacker could break the ZKP protocol. Two main solutions to this deployment issues are: running the Setup through a MPC (multi party computation) or using a ZKP backend like PLONK where the per-circuit Setup is deterministic.

Given the fact that I'm using the Groth16 proving system, the only option for me is to run an MPC ceremony for my circuit to securely generate proving and verifying keys in production environment. MPC ceremony consists of two phases: Phase 1 (Powers of Tau) and Phase 2 (curcuit-specific). For Phase 1 I'm allowed to grab the output of some trusted MPC ceremony that is suitable for my circuit (e.g. take the output of Zcash Powers of Tau ceremony).

When it comes to the circuit-specific Phase 2, a compiled constraint system is needed to generate proving and verifying keys for it. I'm aware of Phase 2 solutions like https://github.com/ebfull/phase2. Particularly, ebfull's solution allows to generate proving and verifying keys, but it needs the circuit to be implemented in Rust using bellman crate (see the https://github.com/ebfull/phase2/blob/master/examples/mimc.rs as an example). So here's my problem: I already have my circuit implemented via gnark's frontend.API in Go and it would be nice to avoid implementing it the second time in Rust to generate secure proving and verifying keys. This question becomes highly relevant for more complicated circuits.

The question

Is it possible to run the Phase 2 MPC with the existing Groth16 compiled constraint system implemented and generated via gnark library? In other words, is there any production implementation for Groth16 Setup that allows to re-use the circuit implementation written via gnark's frontend.API? It may be a silly question, and maybe I'm just not aware of such tool.

I also considered the following way: serialize the compiled constraint system and try to feed the serialized result to https://github.com/ebfull/phase2, but I didn't succeed:

    ccs, err := frontend.Compile(ecc.BLS12_381.ScalarField(), r1cs.NewBuilder, &circuit)
    require.NoError(t, err)

    var buf bytes.Buffer
    n, err := ccs.WriteTo(&buf)
    require.NoError(t, err)

Thank you for considering my question!

gbotrel commented 1 year ago

hi!; have a look at binance contribution in gnark: https://github.com/Consensys/gnark/blob/master/backend/groth16/bn254/mpcsetup/setup_test.go or their repo https://github.com/bnb-chain/zkbnb-setup (based on a slightly different gnark -- but mostly you should be able to play with phase 1 phase 2 steps and reach your goal 👍 )