gnark
: a fast zero-knowledge proof librarygnark
–-a fast, open-source library for zero-knowledge proof protocols written in Go.gnark
at a glance:gnark
offers a high-level API and CLI that makes it easy for developers to write functions and produce zero-knowledge proofs for those functions.gnark
currently supports the Groth16 zk-SNARK protocol. We intend to add support for other protocols in the future.gnark
is faster than bellman, which is a popular state-of-the-art implementation of Groth16. (See our benchmarks below.)gnark
is available on GitHub under the Apache 2.0 License.gnark
has not been independently audited and is provided "as-is". Use gnark
at your own risk. gnark
offers no security guarantees such as constant-time implementation or side-channel attack resistance.
A zero-knowledge proof (ZKP) provides cryptographic assurance of computational integrity and privacy.
Let's unpack those terms:
These features are well-suited to decentralized finance. For example:
You may have heard the term zk-SNARK (zero-knowledge Succinct Non-interactive ARgument of Knowledge). It refers to a class of ZKPs that meet certain specific conditions on the costs borne by the parties in a ZKP protocol. For simplicity in this article we prefer the term zero-knowledge proof (ZKP).
ZKP is a very active area of academic research with improvments and new protocols announced week-by-week. For example, according to this overview article we saw the following new ZKP protocols in 2019: Libra, Sonic, SuperSonic, PLONK, SLONK, Halo, Marlin, Fractal, Spartan, Succinct Aurora, RedShift, AirAssembly.
There are many good expositions of ZKPs. We recommend this explainer by the fine people behind ZCash and this curated list of references.
gnark
?In our discussions on ZKPs with clients, solutions architects, and applied cryptographers we consistently heard:
gnark
aims to address these issues and propose an enterprise-grade library, enabling a normal development cycle for ZKPs, with flexible integration into complex solutions.
gnark
: a simple exampleThe gnark
source code includes several examples.
In the /examples/cubic
directory you'll find an implementation of the very simple example used by Vitalik Buterin in his ZKP explainer from 2016. Given some publicly known number
You'll find here a code walkthrough, but here is what this circuit definition looks like:
// CubicCircuit defines a simple circuit
// x**3 + x + 5 == y
type CubicCircuit struct {
// struct tags on a variable is optional
// default uses variable name and secret visibility.
X frontend.Variable `gnark:"x"`
Y frontend.Variable `gnark:",public"`
}
// Define declares the circuit constraints
// x**3 + x + 5 == y
func (circuit *CubicCircuit) Define(curveID gurvy.ID, cs *frontend.ConstraintSystem) error {
x3 := cs.Mul(circuit.X, circuit.X, circuit.X)
cs.AssertIsEqual(circuit.Y, cs.Add(x3, circuit.X, 5))
return nil
}
gnark
exposes the conventional ZKP algorithms (Setup, Prove, Verify) through a command-line interface (gnark setup
, gnark prove
, gnark verify
) and through a Go API as follows:
pk, vk := groth16.Setup(r1cs)
proof, err := groth16.Prove(r1cs, pk, solution)
err := groth16.Verify(proof, vk, solution)
cd examples/cubic
go run cubic.go
gnark setup circuit.r1cs
gnark prove circuit.r1cs --pk circuit.pk --input input.json
gnark verify circuit.proof --vk circuit.vk --input input.json
gnark
in your project.gnark
is fast!We compare our work to bellman, a state-of-the-art implementation of the Groth16 ZKP protocol developed for ZCash and used in multiple projects such as Filecoin, Matter Labs, ZoKrates.
It is difficult to fairly and accurately compare benchmarks among libraries. Some implementations may excel in conditions where others may not: target (web assembly, embedded, …) or available instruction set, CPUs and RAM may have significant impact.
Nonetheless, it appears that gnark
is faster than state-of-the-art.
Here are our measurements for the Prover. These benchmarks ran on a AWS c5a.24xlarge instance, with hyperthreading disabled.
The same circuit is benchmarked using gnark
, bellman
(bls381, ZCash), bellman_ce
(bn256, matterlabs).
nb constraints | 100000 | 32000000 | 64000000 |
---|---|---|---|
bellman_ce (s/op) | 0.43 | 106 | 214.8 |
gnark (s/op) | 0.16 | 33.9 | 63.4 |
speedup | x2.6 | x3.1 | x3.4 |
On large circuits, that's over 1M constraints per second.
nb constraints | 100000 | 32000000 | 64000000 |
---|---|---|---|
bellman (s/op) | 0.6 | 158 | 316.8 |
gnark (s/op) | 0.23 | 47.6 | 90.7 |
speedup | x2.7 | x3.3 | x3.5 |
Some of these performance improvements come from goff
, a blazingly fast field arithmetics library we built in Go. For more information check out our announcement article on goff
.
gnark
users write their ZKP functions in plain Go. In contrast to other ZKP libraries, we chose to not develop our own language and compiler. Here's why:
Moreover, gnark
exposes its APIs like any conventional cryptographic library (think aes.encrypt([]byte)
). Complex solutions need this flexibility –- gRPC/REST APIs, serialization protocols, monitoring, logging, are all few lines of code away!
We released gnark
in 0.3.0
. Expect significant changes as we add new ZKP schemes and complete our preliminary work on security / threat model. Future work includes:
gnark
standard library (aka gadgets)gnark
was written by Gautam Botrel, Gus Gutoski, and Thomas Piellard.We’re a research team at ConsenSys. If you are interested in our work (fast finite field arithmetic, elliptic curve pairings, zero-knowledge proofs), give us a shout.