Giter Site home page Giter Site logo

consensys / gnark Goto Github PK

View Code? Open in Web Editor NEW
1.4K 37.0 347.0 26.82 MB

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

Home Page: https://hackmd.io/@gnark

License: Apache License 2.0

Go 100.00%
zkp zksnark zk-snarks gnark r1cs golang

gnark's Introduction

gnark zk-SNARK library

Twitter URL License Go Report Card PkgGoDev Documentation Status DOI

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

Useful Links

gnark Users

To get started with gnark and write your first circuit, follow these instructions.

Checkout the online playground to compile circuits and visualize constraint systems.

Warning

gnark has been partially audited and is provided as-is, we make no guarantees or warranties to its safety and reliability. In particular, gnark makes no security guarantees such as constant time implementation or side-channel attack resistance.

gnark and gnark-crypto packages are optimized for 64bits architectures (x86 amd64) and tested on Unix (Linux / macOS).

Issues

gnark issues are tracked in the GitHub issues tab.

To report a security bug, please refer to gnark Security Policy.

If you have any questions, queries or comments, GitHub discussions is the place to find us.

You can also get in touch directly: [email protected]

Release Notes

Release Notes

Proving schemes and curves

Refer to Proving schemes and curves for more details.

gnark support the following zk-SNARKs:

which can be instantiated with the following curves

  • BN254
  • BLS12-381
  • BLS12-377
  • BW6-761
  • BLS24-315
  • BW6-633
  • BLS24-317

Example

Refer to the gnark User Documentation

Here is what x**3 + x + 5 = y looks like

package main

import (
	"github.com/consensys/gnark-crypto/ecc"
	"github.com/consensys/gnark/backend/groth16"
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gnark/frontend/cs/r1cs"
)

// 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(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
}

func main() {
	// compiles our circuit into a R1CS
	var circuit CubicCircuit
	ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)

	// groth16 zkSNARK: Setup
	pk, vk, _ := groth16.Setup(ccs)

	// witness definition
	assignment := CubicCircuit{X: 3, Y: 35}
	witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField())
	publicWitness, _ := witness.Public()

	// groth16: Prove & Verify
	proof, _ := groth16.Prove(ccs, pk, witness)
	groth16.Verify(proof, vk, publicWitness)
}

GPU Support

Icicle Library

The following schemes and curves support experimental use of Ingonyama's Icicle GPU library for low level zk-SNARK primitives such as MSM, NTT, and polynomial operations:

instantiated with the following curve(s)

  • BN254

To use GPUs, add the icicle buildtag to your build/run commands, e.g. go run -tags=icicle main.go.

You can then toggle on or off icicle acceleration by providing the WithIcicleAcceleration backend ProverOption:

    // toggle on
    proofIci, err := groth16.Prove(ccs, pk, secretWitness, backend.WithIcicleAcceleration())
    
    // toggle off
    proof, err := groth16.Prove(ccs, pk, secretWitness)

For more information about prerequisites see the Icicle repo.

Citing

If you use gnark in your research a citation would be appreciated. Please use the following BibTeX to cite the most recent release.

@software{gnark-v0.9.0,
  author       = {Gautam Botrel and
                  Thomas Piellard and
                  Youssef El Housni and
                  Ivo Kubjas and
                  Arya Tabaie},
  title        = {ConsenSys/gnark: v0.9.0},
  month        = feb,
  year         = 2023,
  publisher    = {Zenodo},
  version      = {v0.9.0},
  doi          = {10.5281/zenodo.5819104},
  url          = {https://doi.org/10.5281/zenodo.5819104}
}

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

License

This project is licensed under the Apache 2 License - see the LICENSE file for details

gnark's People

Contributors

ahmetyalp avatar alexandrebelling avatar aybehrouz avatar bernard-wagner avatar dependabot[bot] avatar gbotrel avatar ggutoski avatar gooddaisy avatar hsg88 avatar ivokub avatar lightning-li avatar liyue201 avatar miles-six avatar mottla avatar nkeywal avatar omahs avatar readygo67 avatar secure12 avatar sherlzp avatar shramee avatar tabaie avatar thedarkjester avatar thomaspiellard avatar threehonor avatar tinywell avatar tudorpintea999 avatar winderica avatar wzmuda avatar xiaolou86 avatar yelhousni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gnark's Issues

groth16: deserialization from io.Reader

Currently, it does not seem to be possible for users to restore ProvingKey, VerifyingKey, or Proof structures that have been saved to anything other than a file. This makes it difficult to store proving/verifying keys in app resources or transmit proofs over a network, among many other potential uses. Ideally, it should be possible to deserialize these structures from an arbitrary io.Reader.

Currently, the groth16 package provides ReadProvingKey, ReadVerifyingKey, and ReadProof, but these functions only work for reading from files. A simple way to resolve this issue is to modify these functions to take an io.Reader instead of a path string, and then use Gnark's gnark/io.Read instead of gnark/io.ReadFile internally. Alternatively, a second set of functions could be added with the generalized behavior.

It is not possible for users to call gnark/io.Read manually, because the decoder requires the target to be a pointer to a concrete struct, and these are all defined in internal packages. For example, there appears to be no way for a user to create a struct of type internal/backend/bls381/groth16.Proof without either performing a new proof, or using groth16.ReadProof to read one from a file. Passing in an interface (the usual type exposed to users) as the target also does not work, because it will be nil and Read calls GetCurveID on the target before attempting to decode it.

Conditionals statements in circuit definition

In an imperative programming language, that would be a if / else.

However, it doesn't translate well in a declarative API to define the circuit, as the output of the frontend.Compile method is an arithmetic representation that must encode the various branches.

gnark offers cs.Select(...) API, which is similar to Prolog-like languages.

// Select if b is true, yields i1 else yields i2
func (cs *ConstraintSystem) Select(b Variable, i1, i2 interface{}) Variable {

At a minimum, gnark should provide some syntactic sugar to wrap several instructions, maybe in a lambda, into a a if-like statement.

Add a way to build a specific constraint returning a boolean value according to whether or not a value is zero

Provide a step-by-step description of the suggested enhancement in as much detail as possible:

In implementing an OR statement, it is necessary to evaluate all branches before adding an assertion that ensures the OR is satisfied.
For example, suppose one wants to test if a given variable x is either equal to 3 or 5. One could do the following
provided the following API:

  • IsEqual(i1, i2 interface{}) Variable returns a variable whose value is 1 is i1=i2,0 otherwise
  • Or(a, b Variable) Variable computes the OR between two boolean variables
// Return a variable containing 'true' if X=3, 'false' otherwise
tmp1 := cs.IsEqual(X, cs.Constant(3))
// Return a variable containing 'true' if X=5, 'false' otherwise
tmp2 := cs.IsEqual(X, cs.Constant(5))
cs.AssertIsEqual(cs.Or(tmp1, tmp2), cs.Constant(1))

Describe the current behavior and explain the behavior you expect instead and why.

Currently, it is not possible to get the behaviour described above.
This ticket asks to add the required APIs to make the above behaviour possible.

Please, notice that, I don't want to stress which form these APIs should assume. Above is just an example.

Explain why this enhancement would be useful to other users.

This new API would allow other users to build OR statements of any sorts.
OR statements are very powerful and can be used in multiple situations.

Specify the name and version of the OS you're using.

macOS Big Sur

ToBinary constraint sometimes fails to verify

I've been having problems with valid proofs about scalar multiplications on Twisted Edwards curves occasionally failing to verify. While trying to locate precisely what constraints are causing it to fail, I've encountered similar behavior with the ToBinary constraint, which happens to be the first step of scalar multiplication. The following is the minimum working example:

package main

import (
	"fmt"

	"github.com/consensys/gnark/backend/groth16"
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gurvy"
)

type simpleCircuit struct {
	X frontend.Variable
}

func (circuit *simpleCircuit) Define(_ gurvy.ID, cs *frontend.ConstraintSystem) error {
	cs.ToBinary(circuit.X, 64)
	return nil
}

func main() {
	var circuit simpleCircuit
	r1cs, err := frontend.Compile(gurvy.BN256, &circuit)
	if err != nil {
		fmt.Printf("Failed to compile circuit: %v\n", err)
		return
	}
	provingKey, verifyingKey := groth16.Setup(r1cs)

	for {
		var proverAssignment simpleCircuit
		proverAssignment.X.Assign(uint64(1234))
		proof, err := groth16.Prove(r1cs, provingKey, &proverAssignment)
		if err != nil {
			fmt.Printf("Failed to prove statement: %v\n", err)
			return
		}

		var verifierAssignment simpleCircuit
		verifierAssignment.X.Assign(0)
		if err := groth16.Verify(proof, verifyingKey, &verifierAssignment); err != nil {
			fmt.Printf("Proof failed to verify: %v\n", err)
			return
		}
	}
}

This proof doesn't actually show anything useful, as the variables created by ToBinary are simply ignored. Nonetheless, groth16.Verify returns a pairing doesn't match error after being run for long enough. On my machine, a proof will fail to verify typically within a few minutes, after thousands have been successfully verified. I would expect this proof to always verify.

Proofs still fail in the same way if I change gurvy.BN256 to BLS377, BLS381, or BW761. They also fail if the circuit generation and setup is moved inside the loop (but of course that makes each iteration run slower). There seems to be some setups that don't fail even after a while—when encountering those I restart the experiment. This either suggests that this problem only affects certain setups, or I simply did not let it run long enough in those cases.

Running a similar experiment with the "cubic" example does not seem to show this non-deterministic failure, suggesting that it's something to do with the more complex constraints involved in ToBinary.

Interestingly, I've never seen this code reproduce the problem when being run through the Delve debugger. It only happens when running a compiled binary normally. Perhaps this suggests that there might be some sort of memory corruption going on and this circuit is more susceptible to it than the "cubic" example.

Tested with Gnark 0.3.3 and Go 1.15.2 on linux/amd64.

Module path should be "github.com/ConsenSys/gnark", not "github.com/consensys/gnark"

Background

Module path is inconsistent with go import path.
GO111MODULE=on, run go get github.com/ConsenSys/gnark:

go: downloading github.com/ConsenSys/gnark v0.2.1-alpha
go: github.com/ConsenSys/gnark upgrade => v0.2.1-alpha
go get: github.com/ConsenSys/[email protected]: parsing go.mod:
        module declares its path as: github.com/consensys/gnark
                but was required as: github.com/ConsenSys/gnark

Solution

Fix the module path:

  1. Consider reverting the consensys -> ConsenSys rename.
  2. Rename the module path to ”github.com/ConsenSys/gnark”: https://github.com/ConsenSys/gnark/blob/master/go.mod#L1
module github.com/ConsenSys/gnark
go 1.14
require (
	…
) 
  1. Example go get github.com/consensys/gnark commands or others in the READMEs of all the go repos to guide consumers.

architecture: move ecc/ package into its own repository

Once #15 and #13 are done would be a good time to move ecc into its own repository.

gnark would only contain Constraint Systems and Proving protocols. The crypto primitives they rely on would be reference in go.mod .

Current cs pacakge needs refactoring (move out subpackages, etc).

gnark should be able to export a Solidity verifier

All needed informations should be in the VerifyingKey data structure.

The export / convert function takes as input the VerifyingKey and a io.Writer . Writes on the io.Writer a solidity smart contract that takes as input a proof and a set of public inputs (as defined in the VerifyingKey).

Low priority task.

WebAssembly binary can be built and loaded successfully but it makes "panic: runtime error: integer divide by zero" error"

I understand gnark does not support wasm env officially yet.
Nevertheless, I guess it can do by updating small portion of codes.
A sample code (mimc prove and verify) can be built as an wasm binary and loaded by a javascript (i.e., WebAssembly.instantiateStreaming) successfully due to the absence of cgo usages.
But on executing the wasm binary, the following errors occur immediately:

panic: runtime error: integer divide by zero
github.com/consensys/gnark/internal/backend/bn256/fft.precomputeExpTable(0x9a42b93a4388ee4f, 0x16c835b156abb91e, 0x5fcd5d77a3b49b70, 0x1d24a254e5e81852, 0x904000, 0x200, 0x200)
github.com/consensys/gnark/internal/backend/bn256/fft/domain.go:156 +0x16
github.com/consensys/gnark/internal/backend/bn256/fft.(*Domain).preComputeTwiddles.func2(0x9a42b93a4388ee4f, 0x16c835b156abb91e, 0x5fcd5d77a3b49b70, 0x1d24a254e5e81852, 0x904000, 0x200, 0x200)

I guess the errors would be removed with some new zero value handling logics in your new version.
I hope I can use your excellent gnark in my WebAssembly projects soon.

Thanks.

Importing circuits from bellman

Hello from the Filecoin team!

We would like to be able to use this library to ship a pure go version of filecoin that does not need to depend on bellman. We have existing circuits defined in bellman, but i'm not sure what the best way to go about using gnark to verify their outputs is.

Automated continuous fuzz testing pipeline

Unit tests do some limited fuzz testing.

frontend/fuzz.go or backend/groth16/fuzz.go are experimental integration of gofuzz.

This need to be better defined to ensure good coverage, + setup of a Clusterfuzz node.

cs: (experimental) add support for IF and FOR

Idea:

// signature
func (cs *CS) IF(condition *Constraint, ifBlock func(), elseBlock ...func())
	// example: 
	circuit.IF(condition, func() {
		circuit.IF(circuit.NOT(condition2), func() {
			// if block
			circuit.MUL(...)
		}, func() {
			// optional else block
			circuit.DIV(...)
		})		
	})
        const maxLoops = 100
	for i := 0; i < maxLoops; i++ {
		circuit.IF(circuit.IS_SMALLER(myContraint, i), func() {
		})
                myConstraint = circuit.ADD(myConstraint, 1)
	}

Work in progress. Likely needs better syntax, may need new type of constraints / "boolean predicates".

Efficient PLONK support

See also #67 .

gnark must support, through API options, instantiating PLONK with:

  • KZG polynomial commitment scheme
  • "fast-prover-but-slow-verifier" setting
  • "slow-prover-but-fast-verifier" setting

Similarly to the work done previously on gnark/backend/groth16, gnark/backend/plonk should be optimized-enough to be competitive with other implementations.

Needs:
Consensys/gnark-crypto#38
Consensys/gnark-crypto#37

Eddsa gadget circuit is not correctly solved

In r1cs.go, In the solveR1c method, when solving for a binary decomposition the solver checks if one of the bit is not already instantiated (it can be the case if we enforce a certain bit to be 1 for instance). In eddsa gadget, when solving the circuit, for the scalar multiplications, all the bits are falsely instantiated, so solveR1c does not solve them, and they all end up being 0.

Note: when removing the check if a wire is instantiate in solveR1c, the solver works.

unable to install on Ubuntu 18 with go version go1.10.4 linux/amd64

Running go get github.com/consensys/gnark
results in an error log:

github.com/consensys/gnark/backend/r1cs/r1c

../../../../go/src/github.com/consensys/gnark/backend/r1cs/r1c/term.go:27:31: syntax error: unexpected b000, expecting semicolon or newline or )
../../../../go/src/github.com/consensys/gnark/backend/r1cs/r1c/term.go:35:31: syntax error: unexpected b00, expecting semicolon or newline or )

github.com/consensys/gurvy/bn256/fr

../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fr/arith.go:51:14: too many errors

github.com/consensys/gurvy/bls377/fr

../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fr/arith.go:51:14: too many errors

github.com/consensys/gurvy/bls381/fr

../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fr/arith.go:51:14: too many errors

github.com/consensys/gurvy/bw761/fr

../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fr/arith.go:51:14: too many errors

github.com/consensys/gurvy/bls377/fp

../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls377/fp/arith.go:51:14: too many errors

github.com/consensys/gurvy/bls381/fp

../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bls381/fp/arith.go:51:14: too many errors

github.com/consensys/gurvy/bn256/fp

../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bn256/fp/arith.go:51:14: too many errors

github.com/fxamacker/cbor

../../../../go/src/github.com/fxamacker/cbor/encode.go:867:11: v.MapRange undefined (type reflect.Value has no field or method MapRange)
../../../../go/src/github.com/fxamacker/cbor/encode.go:948:11: v.MapRange undefined (type reflect.Value has no field or method MapRange)

github.com/consensys/gurvy/bw761/fp

../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:30:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:31:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:32:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:39:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:40:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:41:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:48:11: undefined: bits.Mul64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:49:13: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:50:10: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:51:14: undefined: bits.Add64
../../../../go/src/github.com/consensys/gurvy/bw761/fp/arith.go:51:14: too many errors

github.com/stretchr/testify/assert

../../../../go/src/github.com/stretchr/testify/assert/assertions.go:1703:5: undefined: errors.Is
../../../../go/src/github.com/stretchr/testify/assert/assertions.go:1726:6: undefined: errors.Is
../../../../go/src/github.com/stretchr/testify/assert/assertions.go:1749:5: undefined: errors.As
../../../../go/src/github.com/stretchr/testify/assert/assertions.go:1766:7: undefined: errors.Unwrap
../../../../go/src/github.com/stretchr/testify/assert/assertions.go:1770:7: undefined: errors.Unwrap

`frontend.ConstraintSystem` needs a lifting

frontend.ConstraintSystem can be converted to R1CS (Groth16) and SparseR1CS (PLONK) arithmetic representations.

However, it needs a revisit to have more abstractions allowing other proving schemes that radically different arithmetic representation (hello GKR) and to allow for fine-grain constraint optimization at the arithmetic representation level.

Is it possible to define a circuit at runtime (using a map, etc)?

Hello, and thank you for your work!
I am trying to define circuit variables at runtime, rather than at compile time using a struct. For instance, I'd like to do something like

type CubicCircuit struct {
	Inner map[string]frontend.Variable
}
...
func (circuit *CubicCircuit) Define(curveID gurvy.ID, cs *frontend.ConstraintSystem) error {
	x3 := cs.Mul(circuit.Inner["X"], circuit.Inner["X"], circuit.Inner["X"])
	cs.AssertIsEqual(circuit.Inner["Y"], x3)
	return nil
}

Rather than

type CubicCircuit struct {
	X frontend.Variable `gnark:"x"`
	Y frontend.Variable `gnark:"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, x3)
	return nil
}

The circuit compilation, setup, and proving steps appear to compile (in the former case), but creating a witness fails to compile as follows:

solution := CubicCircuit{}
solution.Inner["X"].Assign(2) // fails to compile with Assign is not in method set of frontend.Variable

Is this type of thing possible at all? Thanks!

Witness construction, in non-Go codebases

backend/groth16 and backend/plonk may take a witness that is either:

  1. the same struct used for circuit definition
  2. a []byte slice

For 2. , backend/witness offers serialization apis (witness.WriteFullTo, witness.WritePublicTo) but the witness may be constructed in a non-Go process.

Documentation (#68 ) addresses that and the binary protocol that must be respected.

However, it is worth it to revisit this topic and provide maximum "type/variable-ordering" safety as possible in other languages, maybe through some minimal SDK or generated test vector. TBD.

Question

Hi, gnark team. I have a stupid question. What does nb stand for in readme benchamrk? It is a abbr for word number?

looking forward to u reply.

Experimental PLONK support

In a first iteration, gnark needs to offer experimental support for PLONK proving system.

It will be instantiated with a "mock" polynomial commitment scheme, and with no particular effort on performance.

See also #52

circuit.MUSTBE_LESS_OR_EQ should accept constraints and big integers

Currently circuit.MUSTBE_LESS_OR_EQ requires two arguments, one of which is a constraint, the other being a hardcoded int. As such one can only compare a wire value to a fixed integer. There are two associated issues:

  • it is desirable to be able to compare two wire values directly, say a secret input against a public input for range checks.
  • int is limited to 64 bit integers on most systems. This becomes a problem when comparing, say, a constraint representing a leaf index in a sparse Merkle Tree of depth 256 (or anything > 64) to the maximally allowed maxIndex.

Support PLONK

PLONK is a new zk-snarks algorithm, which is based on Sonic. It can realize SRS (no longer need to generate CRS for each circuit separately), and it is very practical compared to Sonic. Can we modify gnark to support PLONK? I want to make some contributions to the project, so I have the following issues:

  • PLONK's circuit construction method is not based on R1CS. Will we make a big modification on the existing code ?
  • If the modifications are not significant, how will they be modified? Which parts of the code should be modified? Now gnark uses ConstraintSystem to define the Groth16 circuit, whether it is necessary to construct a new class or based on the existing ConstraintSystem.

Failed to generate code

Hello,
I've failed to re-generate generated code for the curves arithmetics.

Steps to reproduce

  1. goff updated to current master and built with make.
  2. gnark updated to current master.
  3. In gnark folder cd ecc/bls381
  4. and execute go generate
  5. command fails with following output:
running goff version 0.1.0-alpha

generating fp/element.go
generating fp/arith.go
generating fp/element_test.go

running goff version 0.1.0-alpha

generating fr/element.go
generating fr/arith.go
generating fr/element_test.go
generating e2.go
generating e2_test.go
generating e6.go
generating e6_test.go
generating e12.go
error: template: :593:7: executing "" at <(eq .Fp6NonResidue "0,1") and (eq .Fp "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177")>: can't give argument to non-function eq .Fp6NonResidue "0,1"
exit status 255
bls381.go:14: running "go": exit status 1

Support programmatic pairing selection instead of build constraints

Currently, choosing between BN256, BLS377, and BLS381 is a compile-time decision controlled by build constraints. If none of bn256, bls377, or bls381 are provided as build tags, the library is currently unusable.

The current situation is undesirable for several reasons:

  • Go libraries should be usable with a simple go get and without the need for a Makefile or adding custom build tags. Relying on the Go toolchain to handle all of this allows the project to be painlessly used as a (possibly transitive) dependency.
  • Users of the library may need to work with a specific pairing. For example, proving statements about a custom twisted Edwards curve requires that the curve's field is the order of G1, and so users that provide such curves and make assumptions about them must also have a guarantee that gnark is using the correct pairing.
  • Build constraints in Go are primarily meant for including architecture-specific optimizations (see for example the use in big and other uses in the standard library). The infrastructure is built around this intended use. Because of this, gnark is currently difficult to use as a transitive dependency. For example, if a developer writing an application depends on a networking library, that networking library depends on a crypto library, and that crypto library depends on gnark, then the application developer is now responsible for choosing the pairing used by gnark even though they are likely in no position to make an informed choice.
  • If Library 1 depends on gnark and requires BLS381, and Library 2 depends on gnark and requires BLS377, then no application can depend on both Library 1 and Library 2.

While most of these issues could be solved by simply making one pairing the default (e.g., BLS381) when the other build tags are not present, that would pose a problem in the future if the default option is shown to have a security flaw, because then the default could not be changed without breaking old users.

The behavior that I would expect as a library user after this enhancement would be:

  • Expose all of the different pairing choices in the API and let the user choose between them based on which packages they import.
  • In cases where exported functions need to access the underlying pairing, allow the user to pass in the pairing that is in use (either with an interface implemented by other parts of the library or, less desirably, with a constant) or extract that information from the unexported contents of other parameters.
  • If a default is provided, then ensure that there is some way to detect that an old default is in use and behave accordingly if the default is changed in the future.
  • Export information about the different pairing choices (e.g., the order of the groups). It would be convenient for users requiring a specific pairing to ask the library for the modulus rather than assigning a big.Int themselves.

Circuit for proof of ownership of private key

I have been working on a circuit for a proof of ownership of a private key.
The circuit computes the public key given the input private key and matches the computed public key with the input public key.

package gnark

import (
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gnark/std/algebra/twistededwards"
	"github.com/consensys/gnark/std/signature/eddsa"
	"github.com/consensys/gurvy"
)

// OwnershipSkCircuit defines circuit for proof of ownership of sk
type OwnershipSkCircuit struct {
	Pk eddsa.PublicKey `gnark:",public"`
	Sk frontend.Variable
}

// Define declares the circuit's constraints
func (circuit *OwnershipSkCircuit) Define(curveID gurvy.ID, cs *frontend.ConstraintSystem) error {
	params, err := twistededwards.NewEdCurve(curveID)
	if err != nil {
		return err
	}
	circuit.Pk.Curve = params

	computedPk := twistededwards.Point{}
	computedPk.ScalarMulFixedBase(cs, circuit.Pk.Curve.BaseX, circuit.Pk.Curve.BaseY, circuit.Sk, circuit.Pk.Curve)
	computedPk.MustBeOnCurve(cs, circuit.Pk.Curve)

	cs.AssertIsEqual(circuit.Pk.A.X, computedPk.X)
	cs.AssertIsEqual(circuit.Pk.A.Y, computedPk.Y)

	return nil
}

I wrote tests for the circuit similar to the tests of the std lib eddsa tests here, see below.
To my surprise, the tests pass for curve bn256 and bls381 but fail for bls377 and bw761.
Cannot find the issue in the circuit and tests, any suggestion would be greatly appreciated.

package gnark

import (
	"math/rand"
	"testing"

	"github.com/consensys/gnark/backend/groth16"
	"github.com/consensys/gnark/crypto/signature"

	eddsabls377 "github.com/consensys/gnark/crypto/signature/eddsa/bls377"
	eddsabls381 "github.com/consensys/gnark/crypto/signature/eddsa/bls381"
	eddsabn256 "github.com/consensys/gnark/crypto/signature/eddsa/bn256"
	eddsabw761 "github.com/consensys/gnark/crypto/signature/eddsa/bw761"
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gurvy"
	edwardsbls377 "github.com/consensys/gurvy/bls377/twistededwards"
	edwardsbls381 "github.com/consensys/gurvy/bls381/twistededwards"
	edwardsbn256 "github.com/consensys/gurvy/bn256/twistededwards"
	edwardsbw761 "github.com/consensys/gurvy/bw761/twistededwards"
)

func parseKeys(id gurvy.ID, pubKeyBuf []byte, privKeyBuf []byte) ([]byte, []byte, []byte) {
	var pointbn256 edwardsbn256.PointAffine
	var pointbls381 edwardsbls381.PointAffine
	var pointbls377 edwardsbls377.PointAffine
	var pointbw761 edwardsbw761.PointAffine

	switch id {
	case gurvy.BN256:
		pointbn256.SetBytes(pubKeyBuf[:32])
		aX := pointbn256.X.Bytes()
		aY := pointbn256.Y.Bytes()
		scalar := privKeyBuf[32:64]
		return aX[:], aY[:], scalar
	case gurvy.BLS381:
		pointbls381.SetBytes(pubKeyBuf[:32])
		aX := pointbls381.X.Bytes()
		aY := pointbls381.Y.Bytes()
		scalar := privKeyBuf[32:64]
		return aX[:], aY[:], scalar
	case gurvy.BLS377:
		pointbls377.SetBytes(pubKeyBuf[:32])
		aX := pointbls377.X.Bytes()
		aY := pointbls377.Y.Bytes()
		scalar := privKeyBuf[32:64]
		return aX[:], aY[:], scalar
	case gurvy.BW761:
		pointbw761.SetBytes(pubKeyBuf[:48])
		aX := pointbw761.X.Bytes()
		aY := pointbw761.Y.Bytes()
		scalar := privKeyBuf[48:96]
		return aX[:], aY[:], scalar
	default:
		return pubKeyBuf, pubKeyBuf, privKeyBuf
	}
}

func TestOwnershipSk(t *testing.T) {
	assert := groth16.NewAssert(t)

	signature.Register(signature.EDDSA_BN256, eddsabn256.GenerateKeyInterfaces)
	signature.Register(signature.EDDSA_BLS381, eddsabls381.GenerateKeyInterfaces)
	signature.Register(signature.EDDSA_BLS377, eddsabls377.GenerateKeyInterfaces)
	signature.Register(signature.EDDSA_BW761, eddsabw761.GenerateKeyInterfaces)

	confs := map[gurvy.ID]signature.SignatureScheme{
		gurvy.BN256:  signature.EDDSA_BN256,
		gurvy.BLS381: signature.EDDSA_BLS381,
		gurvy.BLS377: signature.EDDSA_BLS377,
		gurvy.BW761:  signature.EDDSA_BW761,
	}

	for id, ss := range confs {
		var ownershipSkCircuit OwnershipSkCircuit
		r1cs, err := frontend.Compile(id, &ownershipSkCircuit)
		assert.NoError(err)

		// Correct sk, pk
		{
			// Generate eddsa sk, pk
			src := rand.NewSource(0)
			r := rand.New(src)
			privKey, err := ss.New(r)
			assert.NoError(err)
			pubKey := privKey.Public()

			// Parse sk, pk
			pubkeyAx, pubkeyAy, privkeyScalar := parseKeys(id, pubKey.Bytes(), privKey.Bytes())

			var witness OwnershipSkCircuit
			witness.Pk.A.X.Assign(pubkeyAx)
			witness.Pk.A.Y.Assign(pubkeyAy)
			witness.Sk.Assign(privkeyScalar)

			assert.SolvingSucceeded(r1cs, &witness)
			//assert.ProverSucceeded(r1cs, &witness)
		}

		// Incorrect sk, pk
		{
			var witness OwnershipSkCircuit
			witness.Pk.A.X.Assign(42)
			witness.Pk.A.Y.Assign(42)
			witness.Sk.Assign(42)

			assert.SolvingFailed(r1cs, &witness)
			//assert.ProverFailed(r1cs, &witness)
		}
	}
}

gnark version: v0.3.9-0.20210121051139-4078ebfe99fc
gurvy version: v0.3.8-0.20210118135515-02bca07c2b11

how to set the seed for mimc hash

hi, could you tell me how to select the seed for mimc hash? what principle should be followed or noticed? thanks!

hash.MIMC_BN256.New("seed1")

`gnark/std` needs some love

gnark/std started as ad-hoc proof of concepts to validate gnark design choices and use cases like rollups.

Needs a re-visit to ensure the packages under gnark/std:

  • are rock solid
  • have coherent APIs names and patterns
  • are well documented

ecc: point compression

Points should be compressed when serialized, storing only the X coordinate and a parity bit.

How gnark is compatible with bellman?

Hello!

I've tried to verify Groth16 proof created with bellman using gnark. But soon I realised that my VK, Proof and Inputs are represented in form of compressed points.

So, here is my questions:

  1. Do you have any plans to support bellman's binary formats as inputs for hight level functions?
  2. Can you outline what I have to do to convert bellman's format to gnark's structures? (I've tried to it myself but failed, because it seems to me like goff lacks some functions, or may be I'm wrong).

Thank you in advance!

Ecosystem of gadgets

WIP
"gadgets" (ie circuit functions) are normal Go code. They can be used and imported like any other Go project.

gnark should facilitate discovery of community-developed gadgets, and should examplify / enforce a consistant way to write gadgets to ensure homogeneity and code-quality in circuits.

Issue with gnark installation on go1.14.5 darwin/amd64

I am getting the following errors while trying to get the gnark library using go get -u

github.com/consensys/gnark/backend/bn256

src/github.com/consensys/gnark/backend/bn256/fft.go:139:28: cannot use expo (type uint64) as type *big.Int in argument to subGroup.GeneratorSqRt.Exp

github.com/consensys/gnark/backend/bls377

src/github.com/consensys/gnark/backend/bls377/fft.go:139:28: cannot use expo (type uint64) as type *big.Int in argument to subGroup.GeneratorSqRt.Exp

github.com/consensys/gnark/backend/bls381

src/github.com/consensys/gnark/backend/bls381/fft.go:139:28: cannot use expo (type uint64) as type *big.Int in argument to subGroup.GeneratorSqRt.Exp

ecc: MultiExp code clean up

Different code paths exists to perform scalar multiplications:
ScalarMul, ScalarMulByGen, WindowedMultiExp and MultiExp . Adding to the internal methods multiExp and pippenger .

  1. Current MultiExp doesn't scale as well as it could with available CPUs and number of constraints.
  2. The Setup would benefit from having a fixed based MultiExp (see pippenger algorithm).
  3. The ScalarMul would likely benefit from taking advantage of the endomorphism described in Pairing for beginners

Once these are addressed, we need to clean up the APIs, then would be a good time to extract the ecc package from gnark.

Speed up proving time with a `gnarkd` cluster

gnarkd (experimental) currently uses one machine to (sequentially) generate proofs.

Proof generation could be distributed; one proof per node or splitting the multi exponentiation (prover work) on several worker.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.