64

GitHub - arnaucube/go-snark: zkSNARK library implementation in Go

 4 years ago
source link: https://github.com/arnaucube/go-snark
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

README.md

go-snark Go Report Card

zkSNARK library implementation in Go

Caution & Warning

Implementation of the zkSNARK Pinocchio protocol from scratch in Go to understand the concepts. Do not use in production.

Not finished, implementing this in my free time to understand it better, so I don't have much time.

Currently allows to do the complete path with Pinocchio protocol :

  1. compile circuuit
  2. generate trusted setup
  3. calculate witness
  4. generate proofs
  5. verify proofs

Minimal complete flow implementation:

  • Finite Fields (1, 2, 6, 12) operations
  • G1 and G2 curve operations
  • BN128 Pairing
  • circuit flat code compiler
  • circuit to R1CS
  • polynomial operations
  • R1CS to QAP
  • generate trusted setup
  • generate proofs
  • verify proofs with BN128 pairing

Improvements from the minimal implementation:

  • allow import in circuits language
  • allow for in circuits language
  • code to flat code (improve circuit compiler)
  • move witness values calculation outside the setup phase
  • Groth16
  • multiple optimizations

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 test(private s0, public s1):
	s2 = s0 * s0
	s3 = s2 * 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

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.

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.

Library usage

Example:

// compile circuit and get the R1CS
flatCode := `
func test(private s0, public s1):
	s2 = s0 * s0
	s3 = s2 * 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 0 1 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 1 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] [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))

Test

go test ./... -v

vim/nvim circuit syntax highlighter

For more details and installation instructions see https://github.com/arnaucube/go-snark/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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK