You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
arnaucube 478006134d Archive repository 2 years ago
bn128 Archive repository 2 years ago
circuitcompiler Archive repository 2 years ago
circuitexamples add wasm for Groth16 proof generation & verification 4 years ago
cli Archive repository 2 years ago
externalVerif Archive repository 2 years ago
fields add Groth16 setup calculation 4 years ago
groth16 Archive repository 2 years ago
r1csqap Archive repository 2 years ago
r1csqapFloat doing trusted setup 5 years ago
utils Archive repository 2 years ago
vim-syntax Archive repository 2 years ago
wasm Archive repository 2 years ago
.gitignore update cli, update readme 5 years ago
.travis.yml wasm proof generation from browser working. Added cli wasm exporters, html&js browser example, wasm wrapper from go 4 years ago
LICENSE Initial commit 5 years ago
README.md Archive repository 2 years ago
build-cli.sh update cli, update readme 5 years ago
go-snark-cli add wasm snark proof verification function (Pinocchio) 4 years ago
go.mod Archive repository 2 years ago
go.sum cli 5 years ago
snark.go Archive repository 2 years ago
snark_test.go Archive repository 2 years ago

README.md

Warning

Implementation of the zkSNARK Pinocchio protocol and Groth16 protocol from scratch in Go done in my free time to understand the concepts. Do not use in production.

If you want to generate proofs & verify them from Go, you can try https://github.com/vocdoni/go-snark, which is implemented using the bn256 for the Pairing curve operations for the Groth16 zkSNARK, and it is compatible with circom.

go-snark-study Go Report Card GoDoc

zkSNARK library implementation in Go

Features

Currently allows to do the complete path with Pinocchio protocol and Groth16 protocol :

  1. write circuit
  2. compile circuit
  3. generate trusted setup
  4. calculate witness
  5. generate proofs
  6. verify proofs

Minimal complete flow implementation:

WASM usage

Experimentation with go-snark-study compiled to wasm: https://github.com/arnaucube/go-snark-study/tree/master/wasm

Usage

CLI usage

The cli still needs some improvements, such as seting input files, etc.

In this example we will follow the equation example from Vitalik's article: y = x^3 + x + 5, where y==35 and x==3. So we want to prove that we know a secret x such as the result of the equation is 35.

Compile circuit

Having a circuit file test.circuit:

func exp3(private a):
	b = a * a
	c = a * b
	return c

func main(private s0, public s1):
	s3 = exp3(s0)
	s4 = s3 + s0
	s5 = s4 + 5
	equals(s1, s5)
	out = 1 * 1

And a private inputs file privateInputs.json

[
	3
]

And a public inputs file publicInputs.json

[
	35
]

In the command line, execute:

> ./go-snark-cli compile test.circuit

If you want to have the wasm input ready also, add the flag wasm

> ./go-snark-cli compile test.circuit wasm

This will output the compiledcircuit.json file.

Trusted Setup

Having the compiledcircuit.json, now we can generate the TrustedSetup:

> ./go-snark-cli trustedsetup

This will create the file trustedsetup.json with the TrustedSetup data, and also a toxic.json file, with the parameters to delete from the Trusted Setup.

If you want to have the wasm input ready also, add the flag wasm

> ./go-snark-cli trustedsetup wasm

Generate Proofs

Assumming that we have the compiledcircuit.json, trustedsetup.json, privateInputs.json and the publicInputs.json we can now generate the Proofs with the following command:

> ./go-snark-cli genproofs

This will store the file proofs.json, that contains all the SNARK proofs.

Verify Proofs

Having the proofs.json, compiledcircuit.json, trustedsetup.json publicInputs.json files, we can now verify the Pairings of the proofs, in order to verify the proofs.

> ./go-snark-cli verify

This will return a true if the proofs are verified, or a false if the proofs are not verified.

Cli using Groth16

All this process can be done using Groth16 protocol protocol:

> ./go-snark-cli compile test.circuit
> ./go-snark-cli groth16 trustedsetup
> ./go-snark-cli groth16 genproofs
> ./go-snark-cli verify

Library usage

Example:

// compile circuit and get the R1CS
flatCode := `
func exp3(private a):
	b = a * a
	c = a * b
	return c

func main(private s0, public s1):
	s3 = exp3(s0)
	s4 = s3 + s0
	s5 = s4 + 5
	equals(s1, s5)
	out = 1 * 1
`

// parse the code
parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
circuit, err := parser.Parse()
assert.Nil(t, err)
fmt.Println(circuit)


b3 := big.NewInt(int64(3))
privateInputs := []*big.Int{b3}
b35 := big.NewInt(int64(35))
publicSignals := []*big.Int{b35}

// witness
w, err := circuit.CalculateWitness(privateInputs, publicSignals)
assert.Nil(t, err)
fmt.Println("witness", w)

// now we have the witness:
// w = [1 35 3 9 27 30 35 1]

// flat code to R1CS
fmt.Println("generating R1CS from flat code")
a, b, c := circuit.GenerateR1CS()

/*
now we have the R1CS from the circuit:
a: [[0 0 1 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 1 0 1 0 0 0] [5 0 0 0 0 1 0 0] [0 0 0 0 0 0 1 0] [0 1 0 0 0 0 0 0] [1 0 0 0 0 0 0 0]]
b: [[0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0] [1 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0]]
c: [[0 0 0 1 0 0 0 0] [0 0 0 0 1 0 0 0] [0 0 0 0 0 1 0 0] [0 0 0 0 0 0 1 0] [0 1 0 0 0 0 0 0] [0 0 0 0 0 0 1 0] [0 0 0 0 0 0 0 1]]
*/


alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c)


ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)

// calculate trusted setup
setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)

hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)

proof, err := GenerateProofs(*circuit, setup, w, px)

b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif}
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
Verify Proof generated from snarkjs

Is possible with go-snark-study to verify proofs generated by snarkjs

Example:

verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json")
assert.Nil(t, err)
assert.True(t, verified)

Versions

History of versions & tags of this project:

  • v0.0.1: zkSnark complete flow working with Pinocchio protocol
  • v0.0.2: circuit language improved (allow function calls and file imports)
  • v0.0.3: Groth16 zkSnark protocol added

Test

go test ./... -v

vim/nvim circuit syntax highlighter

For more details and installation instructions see https://github.com/arnaucube/go-snark-study/tree/master/vim-syntax


Thanks to @jbaylina, @bellesmarta, @adriamb for their explanations that helped to understand this a little bit. Also thanks to @vbuterin for all the published articles explaining the zkSNARKs.