Library / SDK
Consensys-Incorporated/gnark avatar
Consensys-Incorporated/gnark

gnark makes a zk-SNARK a Go struct with a Define method

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

1,742 stars555 forksGoApache-2.0

At a glance

What is it?
gnark is Consensys' Apache-2.0 zk-SNARK library for Go, where a circuit is a struct, constraints are declared in a Define method, and Groth16 or PLONK over four curves handles proving. The README states plainly that it does not guarantee constant-time behaviour, which is the constraint to read before anything else.
Who is it for?
gnark is the right library if your team writes Go and needs a proving system already used in production by the Linea zk-rollup, since circuit definition, standard gadgets in `std/` and Solidity verifier export are all in one repository.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • Consensys-Incorporated/gnark1,742 ★ · +1
Star history
Repository2026-10-162026-10-23
Consensys-Incorporated/gnark1.7k1.7k

1 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

A circuit is a Go struct, and Define declares the constraints

The API design is the project. A circuit in gnark is a struct whose fields are `frontend.Variable`, and one method, `Define`, receives a `frontend.API` through which you declare constraints. No separate DSL, no external schema file.

The README's example encodes `x**3 + x + 5 == y`:

go
type CubicCircuit struct {
	X frontend.Variable `gnark:"x"`
	Y frontend.Variable `gnark:",public"`
}

func (circuit *CubicCircuit) Define(api frontend.API) error {
	x3 := api.Mul(circuit.X, circuit.X, circuit.X)
	api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5))
	return nil
}

Two struct tags carry the semantics. `gnark:"x"` names the variable, and `gnark:",public"` marks Y as part of the public witness. Everything else is private by default, which is the correct default for a system where getting it wrong leaks your input.

The rest of the flow is four calls. `frontend.Compile` with a curve's scalar field and a builder such as `r1cs.NewBuilder` produces a compiled circuit. `groth16.Setup` returns a proving key and verifying key. `frontend.NewWitness` builds the witness, `witness.Public()` extracts the public part, `groth16.Prove` produces the proof, and `groth16.Verify` checks it.

Everything returns an error, which the example discards with `_`. In real code you handle them, because a failed constraint or a witness that does not satisfy the circuit is a normal return and not a panic.

Two proving systems, four curves, one primary export target

gnark supports two proving systems, Groth16 and PLONK, and four curves: BN254, BLS12-381, BLS12-377 and BW6-761.

The choice is not free and the README flags where the edges are. Solidity verifier export support is curve-dependent, with BN254 named as the primary target. If your plan involves verifying on-chain, that single sentence narrows your options considerably, and choosing a curve first for other reasons and then discovering the export path is awkward is an avoidable sequence.

The second flag is more serious for anything long-lived: serialized formats are not guaranteed to be stable across versions. Serialized proofs, verifying keys and compiled circuits can change shape between gnark releases. If you are persisting artifacts produced by one version and consuming them with another, you need a migration story, and the library will not promise you compatibility.

Groth16 and PLONK differ in setup requirements and proof shape, but the README does not compare them or give guidance on which to choose for a given situation. That decision is left to you, and the choice is effectively permanent because it determines the shape of your verifier.

Go 1.26 and a module target that tracks it exactly

The stated requirement is Go 1.26 or later, and `go.mod` names the target precisely:

code
module github.com/consensys/gnark

go 1.26.8

That is a recent toolchain requirement. The README's install line is unremarkable:

bash
go get github.com/consensys/gnark@latest

and the first thing to run is one of the bundled examples:

bash
go run ./examples/cubic

The `examples/` directory is a catalogue of what the library covers: `cubic` for the basics, `mimc` for the hash gadget, `plonk` for the PLONK path, `rollup` for a rollup-shaped circuit, `pubkeyhashing` for a real use, `emulated` for emulated field arithmetic, `inputpacking`, `serialization`, `witness`, `print_constraints`, `exponentiate`, `sudoku` and `accelerated_gpu`. Reading that list tells you more about the library's intended use than the feature list does.

The dependency list in `go.mod` shows the shape of the project. `gnark-crypto` provides field arithmetic and is pinned to a pseudo-version rather than a release tag. `fxamacker/cbor` handles serialization, which tells you CBOR is the format in play. `rs/zerolog` is the logger, `leanovate/gopter` is a property-based testing library, and `google/pprof` provides profiling. The `tool` directive pins `gnark-solidity-checker`, `asmfmt` and `goimports` as Go tools, which is the modern way to make tool versions reproducible inside a module.

The README disclaims constant-time behaviour outright

This is the sentence in the README that should decide whether you use the library, and it is in bold in the Security section:

> `gnark` does not guarantee constant-time implementations or side-channel resistance.

The framing is that both gnark and gnark-crypto have been extensively audited, and are provided as-is with no guarantees or warranties. The disclaimer is about side channels, not about the correctness of the circuits or the proving systems.

For a circuit that proves a public statement, or one where the witness contains nothing an attacker can learn from timing, this may not matter. For a circuit that proves knowledge of a discrete log, or handles a private key, or commits to a value that a timing signal would leak, it matters a great deal, and you would need to reason about your own circuit and your threat model rather than rely on the library.

Vulnerability reporting is documented: SECURITY.md exists, and the README asks that security reports not be opened as public issues. Published advisories are tracked on GitHub's security advisories page for the project. Release and security announcements go out through a `gnark-announce` Google Group, which is how you find out about a version that has a known issue.

The audit list covers the library, the standard library and the verifiers

The audits section is unusually specific about scope, and reading it as scope rather than as a list of logos tells you what has actually been reviewed.

`gnark-crypto` was audited by Kudelski Security in October 2022, contracted by the Algorand Foundation, and its KZG component by Sigma Prime in May 2024, contracted by the Ethereum Foundation. The standard library in `std/` was audited by ZKSecurity.xyz in May 2024. The general code and the GKR component were audited by LeastAuthority in September 2024.

Then there is a separate set covering the Linea zkEVM work: the PLONK prover and verifier by OpenZeppelin in June 2024, the Linea zkEVM by LeastAuthority in November 2024, the PLONK Solidity verifier by Consensys Diligence in June 2023, the Groth16 Solidity verifier template by LeastAuthority in August 2023 contracted by Worldcoin, and the PLONK Solidity verifier template by OpenZeppelin in November 2023.

So the on-chain verifier path and the rollup path are separately audited from the core library. The audit PDFs live in an `audits/` directory in the repository, which is where you would read them before relying on any of this.

Five test commands, and two of them are slow on purpose

CI runs formatting, generated-file, lint and test checks on pull requests and pushes. The local commands are listed separately and they are tiered:

bash
go test -short ./...
go test -tags=release_checks,solccheck .
go test -tags=prover_checks ./test/... ./examples/...
go test -run=NONE -fuzz=FuzzIntcomp -fuzztime=30s ./internal/backend/ioutils
go generate ./...

`go test -short ./...` is the fast loop. The `release_checks` and `solccheck` build tags gate what you would run before a release, and `prover_checks` gates the heavier prover and example tests. The fuzz line runs a single fuzz target, `FuzzIntcomp`, for 30 seconds, which is the interpreter component in `internal/backend/ioutils`.

That fuzz target is a signal. A zk library that interprets witness or constraint data is parsing untrusted-shaped input, and a fuzz target on the interpreter is what you would expect to see.

The tooling around it is visible in the root: `.golangci.yml` for linting, `.gitlint` for commit message conventions, `.chglog/` for changelog generation, `.gotestfmt/` for test output formatting, and an `AGENTS.md` for coding agents working in the repository. `debug_test.go` and `integration_test.go` at the root suggest the test entry points are deliberately visible.

GPU acceleration is experimental and Groth16 only

There is a GPU path through Ingonyama's ICICLE backend, and the README marks it experimental. It supports Groth16, not PLONK, on BN254, BLS12-377, BLS12-381 and BW6-761.

The dependency is `github.com/ingonyama-zk/icicle-gnark/v3 v3.2.2`, a major version three, pinned in `go.mod`.

So the GPU option covers exactly one of the two proving systems, on all four curves. If your design depends on PLONK, hardware acceleration through this path is not available to you today.

The mechanism is a backend abstraction, documented in `backend/accelerated/icicle/doc.go`, and the upstream project is at https://github.com/ingonyama-zk/icicle-gnark. There is an `examples/accelerated_gpu/` directory, which is the place to look for what using it looks like.

Behind the public API, the repository layout shows how much of a system this is: `backend/`, `constraint/`, `frontend/`, `gkr/`, `internal/`, `std/`, `io/`, `logger/`, `profile/` and `debug/`. GKR is a separate proof technique from the two public proving systems, and it is one of the things LeastAuthority reviewed in September 2024.

Editorial conclusion

gnark is the right library if your team writes Go and needs a proving system already used in production by the Linea zk-rollup, since circuit definition, standard gadgets in `std/` and Solidity verifier export are all in one repository. It is the wrong choice if your threat model includes side channels on secret-dependent values, because the README disclaims constant-time implementations, and it is wrong for a team that cannot absorb a library tracking a Go 1.26 module target. Before building, pick your proving system and curve deliberately, and re-export your verifier after every gnark version bump, since serialized formats are not guaranteed stable across versions.

Frequently asked questions

How do I install gnark and run my first circuit?

You need Go 1.26 or later. Run go get github.com/consensys/gnark@latest, then go run ./examples/cubic to execute the bundled cubic circuit example, which encodes x**3 + x + 5 == y.

Which proving systems and curves does gnark support?

Groth16 and PLONK, on BN254, BLS12-381, BLS12-377 and BW6-761. Solidity verifier export is curve-dependent, with BN254 named as the primary target.

Does gnark guarantee constant-time execution?

No. The README states that gnark does not guarantee constant-time implementations or side-channel resistance, and that the library is provided as-is with no warranties. The standard library in std/ was audited by ZKSecurity.xyz in May 2024.

Can I use GPU acceleration with gnark?

There is experimental support through Ingonyama's ICICLE backend, covering Groth16 on BN254, BLS12-377, BLS12-381 and BW6-761. PLONK is not covered by that path.

Are gnark serialized proofs and keys stable across versions?

The README states that serialized formats are not guaranteed to be stable across versions, so anything persisted should be regenerated or migrated when you change gnark versions.

Official sources

  1. Consensys-Incorporated/gnark on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/consensys-incorporated-gnark.svg)](https://hysenlabs.com/projects/consensys-incorporated-gnark)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/consensys-incorporated-gnark.svg)](https://hysenlabs.com/projects/consensys-incorporated-gnark)

Was this useful?