Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/Concepts/circuits.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

# Circuit

From a user perspective, a circuit is like a program, which can be written in a programming language like Go. However, internally a circuit is a constraint system; that is, a list of constraints which have an algebraic form.

Check failure on line 9 in docs/Concepts/circuits.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/circuits.md:9:201 MD013/line-length Line length [Expected: 200; Actual: 224] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

For [Groth16](schemes_curves.md#groth16), a constraint looks like $(\sum_ia_ix_i)(\sum_ib_iy_i)=\sum_ic_iz_i$ where $a,b,c$ are constants and $x,y,z$ are variables which depend on the secret inputs known by a prover.

Check failure on line 11 in docs/Concepts/circuits.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/circuits.md:11:201 MD013/line-length Line length [Expected: 200; Actual: 216] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

Translating a circuit, written with [gnark API](../HowTo/write/circuit_api.md) to such a constraint system is called the "arithmetization" of a circuit.

An important point is that every component of a constraint (variables, inputs and constants) live in $\mathbb{F}_p$, a finite field of characteristic $p$. To write a circuit which contains a reasonable number of constraints, it is important to work on the field $\mathbb{F}_p$, so that the field in which the circuits variables live is the same as the field on which the constraint system reasons.

Check failure on line 15 in docs/Concepts/circuits.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/circuits.md:15:201 MD013/line-length Line length [Expected: 200; Actual: 397] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

On the other hand, a circuit reasoning on variables which live in $\mathbb{F}_r$ where $r\neq p$, has a high number of constraints because of the algebraic constraints needed to emulate the arithmetic modulo $r$ on a field of characteristic $p$.

Check failure on line 17 in docs/Concepts/circuits.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/circuits.md:17:201 MD013/line-length Line length [Expected: 200; Actual: 245] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

Finally, the number of constraints in a circuit is limited; you cannot write arbitrarily large circuits. For example, using Groth16 on BN254, you cannot exceed ~$250M$ constraints.
Finally, the number of constraints in a circuit is limited by proving time, memory, and the parameters of the proving system. Measure and profile a representative circuit before assuming it fits your deployment budget.

Check failure on line 19 in docs/Concepts/circuits.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/circuits.md:19:201 MD013/line-length Line length [Expected: 200; Actual: 218] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md
18 changes: 6 additions & 12 deletions docs/Concepts/schemes_curves.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
sidebar_position: 3
---

# Prove schemes and curves
# Proving schemes and curves

`gnark` supports two proving schemes [Groth16](https://eprint.iacr.org/2016/260.pdf) and [PlonK](https://eprint.iacr.org/2019/953.pdf). These schemes can be instantiated with any of the following elliptic curves: _BN254_, _BLS12-381_, _BLS12-377_, _BLS24-315_, _BW6-633_ or _BW6-761_.
`gnark` supports two proving schemes: [Groth16](https://eprint.iacr.org/2016/260.pdf) and [PlonK](https://eprint.iacr.org/2019/953.pdf) with KZG commitments. These schemes can be instantiated with any of the following elliptic curves: _BN254_, _BLS12-381_, _BLS12-377_, or _BW6-761_.

Check failure on line 9 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/schemes_curves.md:9:201 MD013/line-length Line length [Expected: 200; Actual: 283] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

An ID is supplied to `gnark` to choose the proving scheme and the instantiating curve.

Expand All @@ -21,13 +21,13 @@
| prover work | :star::star: | :star: |
| verifier work | :star::star: | :star: |

Groth16 is best suited when an application needs to generate many proofs for the same circuit (for instance a single logic computation) and performance is critical, while PlonK is best suited when it needs to handle many different circuits (for example different arbitrary business logics) with reasonably fast performance.

Check failure on line 24 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/schemes_curves.md:24:201 MD013/line-length Line length [Expected: 200; Actual: 323] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

:::

### Groth16

Groth16 is a circuit-specific preprocessing general-purpose zk-SNARK construction. It has become a de-facto standard used in several blockchain projects due to the constant size of its proof, and its appealing verifier time. On the downside, Groth16 needs a circuit-specific trusted setup for its preprocessing phase.

Check failure on line 30 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/schemes_curves.md:30:201 MD013/line-length Line length [Expected: 200; Actual: 317] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

:::info

Expand Down Expand Up @@ -73,7 +73,7 @@

## Choosing an elliptic curve

Both Groth16 and PlonK (with KZG scheme) need to be instantiated with an elliptic curve. `gnark` supports six elliptic curves: BN254, BLS12-381, BLS12-377, BW6-761, BLS24-315, and BW6-633. All these curves are defined over a finite field $\mathbb{F}_p$ and have an equation of the form $y^2=x^3+b$ ($b\in \mathbb{F}_p$).
Both Groth16 and PlonK (with KZG) need to be instantiated with an elliptic curve. `gnark` supports BN254, BLS12-381, BLS12-377, and BW6-761 for these proving backends. All these curves are defined over a finite field $\mathbb{F}_p$ and have an equation of the form $y^2=x^3+b$ ($b\in \mathbb{F}_p$).

Check failure on line 76 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/schemes_curves.md:76:201 MD013/line-length Line length [Expected: 200; Actual: 299] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

To work with Groth16 and PlonK, the curves must:

Expand All @@ -97,7 +97,7 @@

For applications that target Ethereum 2.0, use BLS12-381.

For platform-agnostic applications, the choice requires a tradeoff between performance (BN254) and security (BLS12-381). We recommend choosing BLS12-381 as it is more secure, still fast enough to be practical, but slower than BN254.

Check failure on line 100 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Lint

Line length

docs/Concepts/schemes_curves.md:100:201 MD013/line-length Line length [Expected: 200; Actual: 232] https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/md013.md

### BLS12-377 and BW6-761 curves

Expand Down Expand Up @@ -126,14 +126,8 @@

:::

### BLS24-315 and BW6-633 curves
## Small and emulated fields

In Groth16, elliptic curve operations take place in three different groups: $G_1$, $G_2$ and $G_T$, whereas in PlonK (with KZG) operations take place only in $G_1$ and $G_T$. While BN254, BLS12-381 and BLS12-377 are optimized for all the three groups, BLS24-315 is better optimized for $G_1$ only while still competitively optimized for $G_T$. Moreover, it comes in a 2-chain setting with BW6-633 to enable PlonK one-layer proof composition efficiently.
`gnark` also has constraint-system implementations for several small fields, including Babybear, Koalabear, Grumpkin, and Tinyfield. These are useful for specialized systems and some recursion workloads, but they are not the pairing-friendly Groth16/PlonK proving curves above.

Check warning on line 131 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Spelling

[vale] reported by reviewdog 🐶 [Consensys.Spelling] Did you really mean 'Tinyfield'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary. Raw Output: {"message": "[Consensys.Spelling] Did you really mean 'Tinyfield'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary.", "location": {"path": "docs/Concepts/schemes_curves.md", "range": {"start": {"line": 131, "column": 123}}}, "severity": "WARNING"}

Check warning on line 131 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Spelling

[vale] reported by reviewdog 🐶 [Consensys.Spelling] Did you really mean 'Grumpkin'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary. Raw Output: {"message": "[Consensys.Spelling] Did you really mean 'Grumpkin'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary.", "location": {"path": "docs/Concepts/schemes_curves.md", "range": {"start": {"line": 131, "column": 109}}}, "severity": "WARNING"}

Check warning on line 131 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Spelling

[vale] reported by reviewdog 🐶 [Consensys.Spelling] Did you really mean 'Koalabear'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary. Raw Output: {"message": "[Consensys.Spelling] Did you really mean 'Koalabear'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary.", "location": {"path": "docs/Concepts/schemes_curves.md", "range": {"start": {"line": 131, "column": 98}}}, "severity": "WARNING"}

Check warning on line 131 in docs/Concepts/schemes_curves.md

View workflow job for this annotation

GitHub Actions / Spelling

[vale] reported by reviewdog 🐶 [Consensys.Spelling] Did you really mean 'Babybear'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary. Raw Output: {"message": "[Consensys.Spelling] Did you really mean 'Babybear'? Ignore this alert if this is a false positive, or ask Cursor to add the term to the Vale dictionary.", "location": {"path": "docs/Concepts/schemes_curves.md", "range": {"start": {"line": 131, "column": 88}}}, "severity": "WARNING"}

In summary, (BLS24-315, BW6-633) is a pair of elliptic curves that:

- Are secure, for proof soundness.
- Are pairing-friendly, for proof verification.
- Are optimized for KZG-based SNARKs (for example, PlonK).
- Have a highly 2-adic subgroup order, for efficient proof generation.
- For efficient proof composition, BW6-633 has a subgroup order equal to BLS24-315's field characteristic.
For arithmetic over a field different from the circuit's native field, use [`std/math/emulated`](https://pkg.go.dev/github.com/consensys/gnark/std/math/emulated). Emulated arithmetic is the foundation for gadgets such as ECDSA, pairing checks, and EVM precompiles.
30 changes: 21 additions & 9 deletions docs/HowTo/debug_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

## Test

You can implement tests as Go unit tests, in a `_test.go` file. For example:
You can implement tests as Go unit tests in a `_test.go` file. The preferred pattern is `assert.CheckCircuit`, which can exercise both valid and invalid assignments and limit the test matrix to the curves and backends you care about:

```go
// assert object wrapping testing.T
Expand All @@ -65,18 +65,30 @@
// declare the circuit
var cubicCircuit Circuit

assert.ProverFailed(&cubicCircuit, &Circuit{
PreImage: 42,
Hash: 42,
})
assert.CheckCircuit(&cubicCircuit,
test.WithValidAssignment(&Circuit{
PreImage: "16130099170765464552823636852555369511329944820189892919423002775646948828469",
Hash: "12886436712380113721405259596386800092738845035233065858332878701083870690753",
}),
test.WithInvalidAssignment(&Circuit{
PreImage: 42,
Hash: 42,
}),
test.WithCurves(ecc.BN254),
)
```

The older `assert.ProverSucceeded` and `assert.ProverFailed` helpers remain useful for simple cases:

```go
assert.ProverSucceeded(&cubicCircuit, &Circuit{
PreImage: 35,
Hash: "16130099170765464552823636852555369511329944820189892919423002775646948828469",
PreImage: "16130099170765464552823636852555369511329944820189892919423002775646948828469",
Hash: "12886436712380113721405259596386800092738845035233065858332878701083870690753",
}, test.WithCurves(ecc.BN254))

```

See the [test package documentation](https://pkg.go.dev/github.com/consensys/gnark/test@v0.7.0) for more details.
Use `test.WithBackends(backend.GROTH16, backend.PLONK)` to restrict the backends under test. The `debug` build tag is still available for more verbose circuit diagnostics. There are also `prover_checks` and `release_checks` build tags that enable additional prover-side checks while debugging.

Check warning on line 90 in docs/HowTo/debug_test.md

View workflow job for this annotation

GitHub Actions / Spelling

[vale] reported by reviewdog 🐶 [write-good.ThereIs] Don't start a sentence with 'There are'. Raw Output: {"message": "[write-good.ThereIs] Don't start a sentence with 'There are'.", "location": {"path": "docs/HowTo/debug_test.md", "range": {"start": {"line": 90, "column": 173}}}, "severity": "WARNING"}

See the [test package documentation](https://pkg.go.dev/github.com/consensys/gnark/test) for more details.

In particular, the default behavior of the assert helper is to test the circuit across all supported curves and backends, ensure correct serialization, and cross-test the constraint system solver against a `big.Int` test execution engine.
8 changes: 1 addition & 7 deletions docs/HowTo/get_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,8 @@ sidebar_position: 1
go get github.com/consensys/gnark@latest
```

:::note

If you use Go modules, in `go.mod` the module path is case sensitive (use `consensys` and not `ConsenSys`).

:::

:::info

`gnark` is optimized for `amd64` targets (`x86 64bits`) and tested on Unix (Linux / macOS).
`gnark` targets Go 1.25 or newer. It is optimized for `amd64` and also supports experimental GPU acceleration for Groth16 through the ICICLE backend.

:::
67 changes: 53 additions & 14 deletions docs/HowTo/prove.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Once the [circuit](write/circuit_structure.md) is [compiled](compile.md), you ca

:::note

Supported zk-SNARK backends are under `gnark/backend`. `gnark` currently implements `Groth16` and an experimental version of `PlonK`.
Supported zk-SNARK backends are under `gnark/backend`. `gnark` currently implements `Groth16` and `PlonK` with KZG commitments.

:::

Expand All @@ -36,21 +36,38 @@ proof, err := groth16.Prove(cs, pk, witness)

// 3. Proof verification
err := groth16.Verify(proof, vk, publicWitness)

```

</TabItem>
<TabItem value="PlonK" label="PlonK" >

```go
// Compile a circuit with the PlonK arithmetization.
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit)
if err != nil {
return err
}

// For development and tests only. In production, load a securely generated SRS.
srs, srsLagrange, err := unsafekzg.NewSRS(ccs.(*cs.SparseR1CS))
if err != nil {
return err
}

// 1. One time setup
publicData, _ := plonk.Setup(cs, ...) // WIP
pk, vk, err := plonk.Setup(ccs, srs, srsLagrange)
if err != nil {
return err
}

// 2. Proof creation
proof, err := plonk.Prove(r1cs, publicData, witness)
proof, err := plonk.Prove(ccs, pk, witness)
if err != nil {
return err
}

// 3. Proof verification
err := plonk.Verify(proof, publicData, publicWitness)
return plonk.Verify(proof, vk, publicWitness)

```

Expand All @@ -73,10 +90,21 @@ assignment := &Circuit {
X: 3,
Y: 35,
}
witness, _ := frontend.NewWitness(assignment, ecc.BN254)
witness, err := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
if err != nil {
return err
}
publicWitness, err := frontend.NewWitness(assignment, ecc.BN254.ScalarField(), frontend.PublicOnly())
if err != nil {
return err
}

// use the witness directly in zk-SNARK backend APIs
groth16.Prove(cs, pk, witness)
// test file --> assert.ProverSucceeded(cs, &witness)
proof, err := groth16.Prove(cs, pk, witness)
if err != nil {
return err
}
return groth16.Verify(proof, vk, publicWitness)
```

:::tip
Expand All @@ -87,17 +115,28 @@ If witness is not built within the same process, or in another programming langu

## Verify a `Proof` on Ethereum

On `ecc.BN254` + `Groth16`, `gnark` can export the `groth16.VerifyingKey` as a solidity smart contract.

Refer to [the code example](https://github.com/Consensys-Incorporated/gnark-tests/blob/main/solidity/contract/main.go) and [end-to-end integration test](https://github.com/Consensys-Incorporated/gnark-tests/blob/47873ce8e146c1f74477a15972ec63cbfd73c888/solidity/solidity_test.go#L81) using a `geth` simulated blockchain.
On `ecc.BN254` + `Groth16`, `gnark` can export the `groth16.VerifyingKey` as a Solidity smart contract. Solidity export is also available for `PlonK` on BN254.

```go
// 1. Compile (Groth16 + BN254)
cs, err := frontend.Compile(ecc.BN254, r1cs.NewBuilder, &myCircuit)
cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &myCircuit)
if err != nil {
return err
}

// 2. Setup
pk, vk, err := groth16.Setup(cs)
if err != nil {
return err
}

// 3. Write solidity smart contract into a file
err = vk.ExportSolidity(f)
// 3. Write a Solidity smart contract into a file.
//
// In production, create proofs and verify native proofs with the Solidity-compatible
// options:
// proof, err := groth16.Prove(cs, pk, witness,
// solidity.WithProverTargetSolidityVerifier(backend.GROTH16))
// err := groth16.Verify(proof, vk, publicWitness,
// solidity.WithVerifierTargetSolidityVerifier(backend.GROTH16))
return vk.ExportSolidity(f, solidity.WithPragmaVersion("^0.8.0"))
```
58 changes: 43 additions & 15 deletions docs/HowTo/serialize.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ To serialize a `gnark` object:

```go
// compile a circuit
cs, err := frontend.Compile(ecc.BN254, r1cs.NewBuilder, &circuit)
cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)

// cs implements io.WriterTo
var buf bytes.Buffer
Expand Down Expand Up @@ -115,29 +115,57 @@ If the witness creation and proof creation live in the same process, refer to [C

:::

```go title="Full witness in Go"
```go title="Witness binary encoding"
// witness
var assignment cubic.Circuit
assignment.X = 3
assignment.Y = 35
witness, _ := frontend.NewWitness(&assignment, ecc.BN254)
witness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField())
if err != nil {
return err
}

// Binary marshalling
// Binary encoding
data, err := witness.MarshalBinary()

// JSON marshalling
json, err := witness.MarshalJSON()
if err != nil {
return err
}

...
// recreate a witness
witness, err := witness.New(ecc.BN254, ccs.GetSchema()) // note that schema is optional for binary encoding
// Recreate an empty witness for the circuit's field and decode it.
decoded, err := witness.New(ecc.BN254.ScalarField())
if err != nil {
return err
}
if err := decoded.UnmarshalBinary(data); err != nil {
return err
}

// Binary unmarshalling
err := witness.UnmarshalBinary(data)
// extract the public part only
publicWitness, err := decoded.Public()
if err != nil {
return err
}
```

// JSON unmarshalling
err := witness.UnmarshalJSON(json)
JSON encoding and decoding require the circuit schema. Build it directly from the circuit structure:

// extract the public part only
publicWitness, _ := witness.Public()
```go title="Witness JSON encoding"
schema, err := frontend.NewSchema(ecc.BN254.ScalarField(), &assignment)
if err != nil {
return err
}

json, err := witness.ToJSON(schema)
if err != nil {
return err
}

decoded, err := witness.New(ecc.BN254.ScalarField())
if err != nil {
return err
}
if err := decoded.FromJSON(schema, json); err != nil {
return err
}
```
69 changes: 52 additions & 17 deletions docs/HowTo/write/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,64 @@ sidebar_position: 6

# Compiler hints

Instead of computing some value within a circuit, it's sometimes more optimal to compute the value off-circuit and only verify the correctness of the computation in a circuit. `gnark` allows you to do this through _hints_. From the prover's point of view, hints are essentially input variables provided by a hint function instead of the user.
Instead of computing every value inside a circuit, it is sometimes more efficient to compute a value outside the circuit and verify only the properties required for soundness. `gnark` calls these off-circuit computations _hints_. During solving, the prover obtains hint outputs from a hint function and then uses those outputs in constraints.

For example, consider a decomposition of an integer `a` into bits. A naive way to decompose it is to look at the binary representation of the integer and extract bits from this representation, but `gnark` doesn't currently provide native bit operations. Instead, the hint function `hint.IthBit` can provide the bits as variables and the user must constrain these variables as a weighted sum which equals to `a`. In a circuit it would look like:
For example, the circuit API can decompose an integer into bits directly:

```go
var b []frontend.Variable
var Σbi frontend.Variable
base := 1
for i := 0; i < nBits; i++ {
b[i] = cs.NewHint(hint.IthBit, a, i)
cs.AssertIsBoolean(b[i])
Σbi = api.Add(Σbi, api.Mul(b[i], base))
base = base << 1
}
cs.AssertIsEqual(Σbi, a)
bits := api.ToBinary(circuit.Value, nBits)
```

This method is also implemented in the front end as `ToBinary(...)` interface method.
This is preferable to hand-rolling a decomposition with a hint.

`gnark` provides a [list of built-in hint functions](https://pkg.go.dev/github.com/consensys/gnark/backend/hint#Function).
## Implement a hint

## Implement hint functions
A hint is a Go function of type `solver.Hint`:

You can define your own hint functions in addition to built-in hint functions. You can provide any instance satisfying the [`hint.Function`](https://pkg.go.dev/github.com/consensys/gnark/backend/hint#Function) to `api.NewHint(...)` method to compute the hint value. Additionally, you must provide the hint function as a [`backend.WithHints`](https://pkg.go.dev/github.com/consensys/gnark/backend#WithHints) option to the back end, so the back end can access the hint function.
```go
func bitsHint(field *big.Int, inputs []*big.Int, outputs []*big.Int) error {
if len(inputs) != 1 {
return fmt.Errorf("unexpected hint arity")
}

a := inputs[0]
for i := range outputs {
outputs[i].SetUint64(uint64(a.Bit(i)))
}
return nil
}
```

Use `api.Compiler().NewHint` in the circuit to request outputs, then constrain them:

```go
b, err := api.Compiler().NewHint(bitsHint, nBits, circuit.Value)
if err != nil {
return err
}

var weightedSum frontend.Variable

for i, bit := range b {
api.AssertIsBoolean(bit)
weightedSum = api.Add(weightedSum, api.Mul(bit, 1<<i))
}

api.AssertIsEqual(weightedSum, circuit.Value)
```

## Register hints

The backend solver can execute a hint only if the function is available to it. Pass it explicitly when proving:

```go
proof, err := groth16.Prove(ccs, pk, witness,
backend.WithSolverOptions(solver.WithHints(bitsHint)),
)
```

The corresponding verifier option is `backend.WithSolverOptions(solver.WithHints(bitsHint))`. To replace an already registered hint, use `solver.OverrideHint`.

Gadgets in `gnark/std` register their required hints automatically when the package is imported. If a serialized constraint system is loaded by a process that does not import the gadget package, call the gadget's registration function (for example, `std.RegisterHints()`) during initialization.

`gnark` also provides a constructor [`hint.NewStaticHint`](https://pkg.go.dev/github.com/consensys/gnark/backend/hint#NewStaticHint) for constructing simple hint functions, which takes a constant number of inputs and returns a constant number of outputs.
For the built-in hint registry, see the [`constraint/solver` package documentation](https://pkg.go.dev/github.com/consensys/gnark/constraint/solver).
Loading
Loading