From 8ad8ae35f7a1aca26973eee744e2a231b20cc475 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 12 May 2019 17:13:58 +0200 Subject: [PATCH] minimal clean & update tests --- README.md | 95 ++++++------ circuitcompiler/circuit.go | 13 +- circuitcompiler/circuit_test.go | 108 +++++++------- circuitcompiler/parser.go | 5 - cli/main.go | 43 ++++-- snark.go | 10 +- snark_test.go | 247 ++++++++++++-------------------- 7 files changed, 229 insertions(+), 292 deletions(-) diff --git a/README.md b/README.md index 354c59a..619aae8 100644 --- a/README.md +++ b/README.md @@ -43,11 +43,13 @@ Example: ```go // compile circuit and get the R1CS flatCode := ` -func test(x): - aux = x*x - y = aux*x - z = x + y - out = z + 5 +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 @@ -56,15 +58,19 @@ circuit, err := parser.Parse() assert.Nil(t, err) fmt.Println(circuit) -// witness + b3 := big.NewInt(int64(3)) -inputs := []*big.Int{b3} -w := circuit.CalculateWitness(inputs) -fmt.Println("\nwitness", w) -/* -now we have the witness: -w = [1 3 35 9 27 30] -*/ +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") @@ -72,42 +78,27 @@ a, b, c := circuit.GenerateR1CS() /* now we have the R1CS from the circuit: -a == [[0 1 0 0 0 0] [0 0 0 1 0 0] [0 1 0 0 1 0] [5 0 0 0 0 1]] -b == [[0 1 0 0 0 0] [0 1 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0]] -c == [[0 0 0 1 0 0] [0 0 0 0 1 0] [0 0 0 0 0 1] [0 0 1 0 0 0]] +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, zx := snark.Utils.PF.R1CSToQAP(a, b, c) - +alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c) -ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) -hx := snark.Utils.PF.DivisorPolinomial(px, zx) - -// hx==px/zx so px==hx*zx -assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx)) - -// p(x) = a(x) * b(x) - c(x) == h(x) * z(x) -abc := snark.Utils.PF.Sub(pf.Mul(ax, bx), cx) -assert.Equal(t, abc, px) -hz := snark.Utils.PF.Mul(hx, zx) -assert.Equal(t, abc, hz) - -div, rem := snark.Utils.PF.Div(px, zx) -assert.Equal(t, hx, div) -assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) +ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) // calculate trusted setup -setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx) -assert.Nil(t, err) -fmt.Println("t", setup.Toxic.T) +setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas) -// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) -proof, err := snark.GenerateProofs(circuit, setup, hx, w) -assert.Nil(t, err) +hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) + +proof, err := GenerateProofs(*circuit, setup, w, px) -assert.True(t, snark.VerifyProof(circuit, setup, proof)) +b35Verif := big.NewInt(int64(35)) +publicSignalsVerif := []*big.Int{b35Verif} +assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true)) ``` ### CLI usage @@ -115,18 +106,26 @@ assert.True(t, snark.VerifyProof(circuit, setup, proof)) #### Compile circuit Having a circuit file `test.circuit`: ``` -func test(x): - aux = x*x - y = aux*x - z = x + y - out = z + 5 +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 inputs file `inputs.json` +And a private inputs file `privateInputs.json` ``` [ 3 ] ``` +And a public inputs file `publicInputs.json` +``` +[ + 35 +] +``` In the command line, execute: ``` @@ -144,7 +143,7 @@ This will create the file `trustedsetup.json` with the TrustedSetup data, and al #### Generate Proofs -Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command: +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 ``` @@ -152,7 +151,7 @@ Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, w This will store the file `proofs.json`, that contains all the SNARK proofs. #### Verify Proofs -Having the `proofs.json`, `compiledcircuit.json`, `trustedsetup.json` files, we can now verify the `Pairings` of the proofs, in order to verify the 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 ``` diff --git a/circuitcompiler/circuit.go b/circuitcompiler/circuit.go index 220e989..7f4b0af 100644 --- a/circuitcompiler/circuit.go +++ b/circuitcompiler/circuit.go @@ -2,7 +2,6 @@ package circuitcompiler import ( "errors" - "fmt" "math/big" "strconv" @@ -96,10 +95,9 @@ func (circ *Circuit) GenerateR1CS() ([][]*big.Int, [][]*big.Int, [][]*big.Int) { cConstraint := r1csqap.ArrayOfBigZeros(len(circ.Signals)) // if existInArray(constraint.Out) { - if used[constraint.Out] { - // panic(errors.New("out variable already used: " + constraint.Out)) - fmt.Println("variable already used") - } + // if used[constraint.Out] { + // panic(errors.New("out variable already used: " + constraint.Out)) + // } used[constraint.Out] = true if constraint.Op == "in" { for i := 0; i <= len(circ.PublicInputs); i++ { @@ -152,7 +150,7 @@ func grabVar(signals []string, w []*big.Int, vStr string) *big.Int { type Inputs struct { Private []*big.Int - Publics []*big.Int + Public []*big.Int } // CalculateWitness calculates the Witness of a Circuit based on the given inputs @@ -167,12 +165,9 @@ func (circ *Circuit) CalculateWitness(privateInputs []*big.Int, publicInputs []* w := r1csqap.ArrayOfBigZeros(len(circ.Signals)) w[0] = big.NewInt(int64(1)) for i, input := range publicInputs { - fmt.Println(i + 1) - fmt.Println(input) w[i+1] = input } for i, input := range privateInputs { - fmt.Println(i + len(publicInputs) + 1) w[i+len(publicInputs)+1] = input } for _, constraint := range circ.Constraints { diff --git a/circuitcompiler/circuit_test.go b/circuitcompiler/circuit_test.go index 8293d85..485406b 100644 --- a/circuitcompiler/circuit_test.go +++ b/circuitcompiler/circuit_test.go @@ -1,8 +1,6 @@ package circuitcompiler import ( - "encoding/json" - "fmt" "math/big" "strings" "testing" @@ -11,74 +9,62 @@ import ( ) func TestCircuitParser(t *testing.T) { - /* - input: - def test(): - y = x**3 - return x + y + 5 - - flattened: - m1 = s1 * s1 - m2 = m1 * s1 - m3 = m2 + s1 - out = m3 + 5 - - */ - - // flat code, where er is expected_result - // equals(s5, s1) - // s1 = s5 * 1 + // y = x^3 + x + 5 flat := ` func test(private s0, public s1): - s2 = s0*s0 - s3 = s2*s0 - s4 = s0 + s3 + s2 = s0 * s0 + s3 = s2 * s0 + s4 = s3 + s0 s5 = s4 + 5 - s5 = s1 * one + equals(s1, s5) out = 1 * 1 ` parser := NewParser(strings.NewReader(flat)) circuit, err := parser.Parse() assert.Nil(t, err) - fmt.Println("circuit parsed: ", circuit) // flat code to R1CS - fmt.Println("generating R1CS from flat code") a, b, c := circuit.GenerateR1CS() - fmt.Println("private inputs: ", circuit.PrivateInputs) - fmt.Println("public inputs: ", circuit.PublicInputs) + assert.Equal(t, "s0", circuit.PrivateInputs[0]) + assert.Equal(t, "s1", circuit.PublicInputs[0]) - fmt.Println("signals:", circuit.Signals) + assert.Equal(t, []string{"one", "s1", "s0", "s2", "s3", "s4", "s5", "out"}, circuit.Signals) // expected result - // b0 := big.NewInt(int64(0)) - // b1 := big.NewInt(int64(1)) - // b5 := big.NewInt(int64(5)) - // aExpected := [][]*big.Int{ - // []*big.Int{b0, b0, b1, b0, b0, b0}, - // []*big.Int{b0, b0, b0, b1, b0, b0}, - // []*big.Int{b0, b0, b1, b0, b1, b0}, - // []*big.Int{b5, b0, b0, b0, b0, b1}, - // } - // bExpected := [][]*big.Int{ - // []*big.Int{b0, b0, b1, b0, b0, b0}, - // []*big.Int{b0, b0, b1, b0, b0, b0}, - // []*big.Int{b1, b0, b0, b0, b0, b0}, - // []*big.Int{b1, b0, b0, b0, b0, b0}, - // } - // cExpected := [][]*big.Int{ - // []*big.Int{b0, b0, b0, b1, b0, b0}, - // []*big.Int{b0, b0, b0, b0, b1, b0}, - // []*big.Int{b0, b0, b0, b0, b0, b1}, - // []*big.Int{b0, b1, b0, b0, b0, b0}, - // } - // - // assert.Equal(t, aExpected, a) - // assert.Equal(t, bExpected, b) - // assert.Equal(t, cExpected, c) - fmt.Println(a) - fmt.Println(b) - fmt.Println(c) + b0 := big.NewInt(int64(0)) + b1 := big.NewInt(int64(1)) + b5 := big.NewInt(int64(5)) + aExpected := [][]*big.Int{ + []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0}, + []*big.Int{b0, b0, b1, b0, b1, b0, b0, b0}, + []*big.Int{b5, b0, b0, b0, b0, b1, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0}, + []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + } + bExpected := [][]*big.Int{ + []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + } + cExpected := [][]*big.Int{ + []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0}, + []*big.Int{b0, b0, b0, b0, b1, b0, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b1, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0}, + []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b0, b1}, + } + + assert.Equal(t, aExpected, a) + assert.Equal(t, bExpected, b) + assert.Equal(t, cExpected, c) b3 := big.NewInt(int64(3)) privateInputs := []*big.Int{b3} @@ -87,10 +73,14 @@ func TestCircuitParser(t *testing.T) { // Calculate Witness w, err := circuit.CalculateWitness(privateInputs, publicInputs) assert.Nil(t, err) - fmt.Println("w", w) + b9 := big.NewInt(int64(9)) + b27 := big.NewInt(int64(27)) + b30 := big.NewInt(int64(30)) + wExpected := []*big.Int{b1, b35, b3, b9, b27, b30, b35, b1} + assert.Equal(t, wExpected, w) - circuitJson, _ := json.Marshal(circuit) - fmt.Println("circuit:", string(circuitJson)) + // circuitJson, _ := json.Marshal(circuit) + // fmt.Println("circuit:", string(circuitJson)) assert.Equal(t, circuit.NPublic, 1) assert.Equal(t, len(circuit.PublicInputs), 1) diff --git a/circuitcompiler/parser.go b/circuitcompiler/parser.go index d168669..70f074b 100644 --- a/circuitcompiler/parser.go +++ b/circuitcompiler/parser.go @@ -101,8 +101,6 @@ func (p *Parser) parseLine() (*Constraint, error) { insideParenthesis := rgx.FindStringSubmatch(line) varsString := strings.Replace(insideParenthesis[1], " ", "", -1) params := strings.Split(varsString, ",") - fmt.Println("params", params) - // TODO c.V1 = params[0] c.V2 = params[1] return c, nil @@ -162,7 +160,6 @@ func (p *Parser) Parse() (*Circuit, error) { if err != nil { break } - fmt.Println(constraint) if constraint.Literal == "func" { // one constraint for each input for _, in := range constraint.PublicInputs { @@ -189,8 +186,6 @@ func (p *Parser) Parse() (*Circuit, error) { continue } if constraint.Literal == "equals" { - // TODO - fmt.Println("circuit.Signals", circuit.Signals) constr1 := &Constraint{ Op: "*", V1: constraint.V2, diff --git a/cli/main.go b/cli/main.go index 0557efc..8d4b5b0 100644 --- a/cli/main.go +++ b/cli/main.go @@ -80,18 +80,22 @@ func CompileCircuit(context *cli.Context) error { panicErr(err) fmt.Println("\ncircuit data:", circuit) - // read inputs file - inputsFile, err := ioutil.ReadFile("inputs.json") + // read privateInputs file + privateInputsFile, err := ioutil.ReadFile("privateInputs.json") + panicErr(err) + // read publicInputs file + publicInputsFile, err := ioutil.ReadFile("publicInputs.json") panicErr(err) // parse inputs from inputsFile - // var inputs []*big.Int var inputs circuitcompiler.Inputs - json.Unmarshal([]byte(string(inputsFile)), &inputs) + err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) + panicErr(err) + err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) panicErr(err) // calculate wittness - w, err := circuit.CalculateWitness(inputs.Private) + w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) panicErr(err) fmt.Println("\nwitness", w) @@ -175,18 +179,18 @@ func TrustedSetup(context *cli.Context) error { json.Unmarshal([]byte(string(inputsFile)), &inputs) panicErr(err) // calculate wittness - w, err := circuit.CalculateWitness(inputs.Private) + w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) panicErr(err) // R1CS to QAP - alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C) + alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C) fmt.Println("qap") fmt.Println(alphas) fmt.Println(betas) fmt.Println(gammas) // calculate trusted setup - setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx) + setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas) panicErr(err) fmt.Println("\nt:", setup.Toxic.T) @@ -225,16 +229,21 @@ func GenerateProofs(context *cli.Context) error { json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup) panicErr(err) - // read inputs file - inputsFile, err := ioutil.ReadFile("inputs.json") + // read privateInputs file + privateInputsFile, err := ioutil.ReadFile("privateInputs.json") + panicErr(err) + // read publicInputs file + publicInputsFile, err := ioutil.ReadFile("publicInputs.json") panicErr(err) // parse inputs from inputsFile - // var inputs []*big.Int var inputs circuitcompiler.Inputs - json.Unmarshal([]byte(string(inputsFile)), &inputs) + err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) + panicErr(err) + err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) panicErr(err) + // calculate wittness - w, err := circuit.CalculateWitness(inputs.Private) + w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) panicErr(err) fmt.Println("\nwitness", w) @@ -293,7 +302,13 @@ func VerifyProofs(context *cli.Context) error { json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup) panicErr(err) - // TODO read publicSignals from file + // read publicInputs file + publicInputsFile, err := ioutil.ReadFile("publicInputs.json") + panicErr(err) + var publicSignals []*big.Int + err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals) + panicErr(err) + verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true) if !verified { fmt.Println("ERROR: proofs not verified") diff --git a/snark.go b/snark.go index e61191a..642fc54 100644 --- a/snark.go +++ b/snark.go @@ -105,8 +105,6 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al // } // } - fmt.Println("alphas[1]", alphas[1]) - // generate random t value setup.Toxic.T, err = Utils.FqR.Rand() if err != nil { @@ -226,7 +224,6 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al big.NewInt(int64(1)), }) } - fmt.Println("zpol", zpol) setup.Pk.Z = zpol zt := Utils.PF.Eval(zpol, setup.Toxic.T) @@ -243,7 +240,6 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al // tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T) tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T) } - fmt.Println("len(G1T)", len(gt1)) setup.G1T = gt1 return setup, nil @@ -293,6 +289,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka) pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G) if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) { + fmt.Println("❌ e(piA, Va) == e(piA', g2), valid knowledge commitment for A") return false } if debug { @@ -303,6 +300,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ pairingVbPib := Utils.Bn.Pairing(setup.Vk.Vkb, proof.PiB) pairingPibpG2 := Utils.Bn.Pairing(proof.PiBp, Utils.Bn.G2.G) if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) { + fmt.Println("❌ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B") return false } if debug { @@ -313,6 +311,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ pairingPicVc := Utils.Bn.Pairing(proof.PiC, setup.Vk.Vkc) pairingPicpG2 := Utils.Bn.Pairing(proof.PiCp, Utils.Bn.G2.G) if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) { + fmt.Println("❌ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C") return false } if debug { @@ -322,7 +321,6 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ // Vkx, to then calculate Vkx+piA vkxpia := setup.Vk.IC[0] for i := 0; i < len(publicSignals); i++ { - fmt.Println("pub sig", publicSignals[i]) vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i])) } @@ -332,6 +330,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ Utils.Bn.Fq12.Mul( Utils.Bn.Pairing(proof.PiH, setup.Vk.Vkz), Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) { + fmt.Println("❌ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked") return false } if debug { @@ -346,6 +345,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ pairingL := Utils.Bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB) pairingR := Utils.Bn.Pairing(proof.PiKp, setup.Vk.G2Kg) if !Utils.Bn.Fq12.Equal(pairingL, pairingR) { + fmt.Println("❌ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)") return false } if debug { diff --git a/snark_test.go b/snark_test.go index 147cf96..a1c070c 100644 --- a/snark_test.go +++ b/snark_test.go @@ -2,7 +2,6 @@ package snark import ( "bytes" - "encoding/json" "fmt" "math/big" "strings" @@ -35,9 +34,9 @@ func TestZkFromFlatCircuitCode(t *testing.T) { parser := circuitcompiler.NewParser(strings.NewReader(flatCode)) circuit, err := parser.Parse() assert.Nil(t, err) - fmt.Println("\ncircuit data:", circuit) - circuitJson, _ := json.Marshal(circuit) - fmt.Println("circuit:", string(circuitJson)) + // fmt.Println("\ncircuit data:", circuit) + // circuitJson, _ := json.Marshal(circuit) + // fmt.Println("circuit:", string(circuitJson)) b3 := big.NewInt(int64(3)) privateInputs := []*big.Int{b3} @@ -47,8 +46,6 @@ func TestZkFromFlatCircuitCode(t *testing.T) { // wittness w, err := circuit.CalculateWitness(privateInputs, publicSignals) assert.Nil(t, err) - fmt.Println("\n", circuit.Signals) - fmt.Println("witness", w) // flat code to R1CS fmt.Println("\ngenerating R1CS from flat code") @@ -59,25 +56,23 @@ func TestZkFromFlatCircuitCode(t *testing.T) { fmt.Println("c:", c) // R1CS to QAP - // TODO zxQAP is not used and is an old impl, bad calculated. TODO remove + // TODO zxQAP is not used and is an old impl, TODO remove alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c) fmt.Println("qap") - fmt.Println("alphas", len(alphas)) - fmt.Println("alphas[1]", alphas[1]) - fmt.Println("betas", len(betas)) - fmt.Println("gammas", len(gammas)) - fmt.Println("zx length", len(zxQAP)) + assert.Equal(t, 8, len(alphas)) + assert.Equal(t, 8, len(alphas)) + assert.Equal(t, 8, len(alphas)) + assert.Equal(t, 7, len(zxQAP)) assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes())) ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) - fmt.Println("ax length", len(ax)) - fmt.Println("bx length", len(bx)) - fmt.Println("cx length", len(cx)) - fmt.Println("px length", len(px)) - fmt.Println("px[last]", px[0]) + assert.Equal(t, 7, len(ax)) + assert.Equal(t, 7, len(bx)) + assert.Equal(t, 7, len(cx)) + assert.Equal(t, 13, len(px)) hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP) - fmt.Println("hx length", len(hxQAP)) + assert.Equal(t, 7, len(hxQAP)) // hx==px/zx so px==hx*zx assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP)) @@ -98,11 +93,10 @@ func TestZkFromFlatCircuitCode(t *testing.T) { fmt.Println("\nt:", setup.Toxic.T) // zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation - // assert.Equal(t, zxQAP, setup.Pk.Z) + assert.Equal(t, zxQAP, setup.Pk.Z) - fmt.Println("hx pk.z", hxQAP) hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) - fmt.Println("hx pk.z", hx) + assert.Equal(t, hx, hxQAP) // assert.Equal(t, hxQAP, hx) div, rem = Utils.PF.Div(px, setup.Pk.Z) assert.Equal(t, hx, div) @@ -116,9 +110,6 @@ func TestZkFromFlatCircuitCode(t *testing.T) { assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1) assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1) - // fmt.Println("pk.Z", len(setup.Pk.Z)) - // fmt.Println("zxQAP", len(zxQAP)) - proof, err := GenerateProofs(*circuit, setup, w, px) assert.Nil(t, err) @@ -126,8 +117,8 @@ func TestZkFromFlatCircuitCode(t *testing.T) { // fmt.Println(proof) // fmt.Println("public signals:", proof.PublicSignals) - fmt.Println("\n", circuit.Signals) - fmt.Println("\nwitness", w) + fmt.Println("\nsignals:", circuit.Signals) + fmt.Println("witness:", w) b35Verif := big.NewInt(int64(35)) publicSignalsVerif := []*big.Int{b35Verif} before := time.Now() @@ -147,16 +138,12 @@ func TestZkMultiplication(t *testing.T) { equals(c, d) out = 1 * 1 ` - fmt.Print("\nflat code of the circuit:") - fmt.Println(flatCode) + fmt.Println("flat code", flatCode) // parse the code parser := circuitcompiler.NewParser(strings.NewReader(flatCode)) circuit, err := parser.Parse() assert.Nil(t, err) - fmt.Println("\ncircuit data:", circuit) - circuitJson, _ := json.Marshal(circuit) - fmt.Println("circuit:", string(circuitJson)) b3 := big.NewInt(int64(3)) b4 := big.NewInt(int64(4)) @@ -167,8 +154,6 @@ func TestZkMultiplication(t *testing.T) { // wittness w, err := circuit.CalculateWitness(privateInputs, publicSignals) assert.Nil(t, err) - fmt.Println("\n", circuit.Signals) - fmt.Println("witness", w) // flat code to R1CS fmt.Println("\ngenerating R1CS from flat code") @@ -179,25 +164,22 @@ func TestZkMultiplication(t *testing.T) { fmt.Println("c:", c) // R1CS to QAP - // TODO zxQAP is not used and is an old impl, bad calculated. TODO remove + // TODO zxQAP is not used and is an old impl. TODO remove alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c) - fmt.Println("qap") - fmt.Println("alphas", len(alphas)) - fmt.Println("alphas[1]", alphas[1]) - fmt.Println("betas", len(betas)) - fmt.Println("gammas", len(gammas)) - fmt.Println("zx length", len(zxQAP)) + assert.Equal(t, 6, len(alphas)) + assert.Equal(t, 6, len(betas)) + assert.Equal(t, 6, len(betas)) + assert.Equal(t, 5, len(zxQAP)) assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes())) ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) - fmt.Println("ax length", len(ax)) - fmt.Println("bx length", len(bx)) - fmt.Println("cx length", len(cx)) - fmt.Println("px length", len(px)) - fmt.Println("px[last]", px[0]) + assert.Equal(t, 4, len(ax)) + assert.Equal(t, 4, len(bx)) + assert.Equal(t, 4, len(cx)) + assert.Equal(t, 7, len(px)) hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP) - fmt.Println("hx length", len(hxQAP)) + assert.Equal(t, 3, len(hxQAP)) // hx==px/zx so px==hx*zx assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP)) @@ -215,15 +197,15 @@ func TestZkMultiplication(t *testing.T) { // calculate trusted setup setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas) assert.Nil(t, err) - fmt.Println("\nt:", setup.Toxic.T) + // fmt.Println("\nt:", setup.Toxic.T) // zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation - // assert.Equal(t, zxQAP, setup.Pk.Z) + assert.Equal(t, zxQAP, setup.Pk.Z) - fmt.Println("hx pk.z", hxQAP) hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) - fmt.Println("hx pk.z", hx) - // assert.Equal(t, hxQAP, hx) + assert.Equal(t, 3, len(hx)) + assert.Equal(t, hx, hxQAP) + div, rem = Utils.PF.Div(px, setup.Pk.Z) assert.Equal(t, hx, div) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) @@ -236,9 +218,6 @@ func TestZkMultiplication(t *testing.T) { assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1) assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1) - // fmt.Println("pk.Z", len(setup.Pk.Z)) - // fmt.Println("zxQAP", len(zxQAP)) - proof, err := GenerateProofs(*circuit, setup, w, px) assert.Nil(t, err) @@ -247,7 +226,7 @@ func TestZkMultiplication(t *testing.T) { // fmt.Println("public signals:", proof.PublicSignals) fmt.Println("\n", circuit.Signals) - fmt.Println("\nwitness", w) + fmt.Println("witness", w) b12Verif := big.NewInt(int64(12)) publicSignalsVerif := []*big.Int{b12Verif} before := time.Now() @@ -260,80 +239,20 @@ func TestZkMultiplication(t *testing.T) { assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true)) } -/* -func TestZkFromHardcodedR1CS(t *testing.T) { - b0 := big.NewInt(int64(0)) - b1 := big.NewInt(int64(1)) - b3 := big.NewInt(int64(3)) - b5 := big.NewInt(int64(5)) - b9 := big.NewInt(int64(9)) - b27 := big.NewInt(int64(27)) - b30 := big.NewInt(int64(30)) - b35 := big.NewInt(int64(35)) - a := [][]*big.Int{ - []*big.Int{b0, b0, b1, b0, b0, b0}, - []*big.Int{b0, b0, b0, b1, b0, b0}, - []*big.Int{b0, b0, b1, b0, b1, b0}, - []*big.Int{b5, b0, b0, b0, b0, b1}, - } - b := [][]*big.Int{ - []*big.Int{b0, b0, b1, b0, b0, b0}, - []*big.Int{b0, b0, b1, b0, b0, b0}, - []*big.Int{b1, b0, b0, b0, b0, b0}, - []*big.Int{b1, b0, b0, b0, b0, b0}, - } - c := [][]*big.Int{ - []*big.Int{b0, b0, b0, b1, b0, b0}, - []*big.Int{b0, b0, b0, b0, b1, b0}, - []*big.Int{b0, b0, b0, b0, b0, b1}, - []*big.Int{b0, b1, b0, b0, b0, b0}, - } - alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c) - - // wittness = 1, 35, 3, 9, 27, 30 - w := []*big.Int{b1, b35, b3, b9, b27, b30} - circuit := circuitcompiler.Circuit{ - NVars: 6, - NPublic: 1, - NSignals: len(w), - } - ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) - - hx := Utils.PF.DivisorPolynomial(px, zx) - - // hx==px/zx so px==hx*zx - assert.Equal(t, px, Utils.PF.Mul(hx, zx)) - - // p(x) = a(x) * b(x) - c(x) == h(x) * z(x) - abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx) - assert.Equal(t, abc, px) - hz := Utils.PF.Mul(hx, zx) - assert.Equal(t, abc, hz) - - div, rem := Utils.PF.Div(px, zx) - assert.Equal(t, hx, div) - assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) - - // calculate trusted setup - setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx) - assert.Nil(t, err) - - // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) - proof, err := GenerateProofs(circuit, setup, hx, w) - assert.Nil(t, err) - - // assert.True(t, VerifyProof(circuit, setup, proof, true)) - publicSignals := []*big.Int{b35} - assert.True(t, VerifyProof(circuit, setup, proof, publicSignals, true)) -} - -func TestZkMultiplication(t *testing.T) { - - // compile circuit and get the R1CS +func TestMinimalFlow(t *testing.T) { + // circuit function + // y = x^3 + x + 5 flatCode := ` - func test(a, b): - out = a * b + func test(private s0, public s1): + s2 = s0 * s0 + s3 = s2 * s0 + s4 = s3 + s0 + s5 = s4 + 5 + equals(s1, s5) + out = 1 * 1 ` + fmt.Print("\nflat code of the circuit:") + fmt.Println(flatCode) // parse the code parser := circuitcompiler.NewParser(strings.NewReader(flatCode)) @@ -341,46 +260,70 @@ func TestZkMultiplication(t *testing.T) { assert.Nil(t, err) b3 := big.NewInt(int64(3)) - b4 := big.NewInt(int64(4)) - inputs := []*big.Int{b3, b4} + privateInputs := []*big.Int{b3} + b35 := big.NewInt(int64(35)) + publicSignals := []*big.Int{b35} + // wittness - w, err := circuit.CalculateWitness(inputs) + w, err := circuit.CalculateWitness(privateInputs, publicSignals) assert.Nil(t, err) // flat code to R1CS + fmt.Println("\ngenerating R1CS from flat code") a, b, c := circuit.GenerateR1CS() + fmt.Println("\nR1CS:") + fmt.Println("a:", a) + fmt.Println("b:", b) + fmt.Println("c:", c) // R1CS to QAP - alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c) + // TODO zxQAP is not used and is an old impl, TODO remove + alphas, betas, gammas, _ := Utils.PF.R1CSToQAP(a, b, c) + fmt.Println("qap") + assert.Equal(t, 8, len(alphas)) + assert.Equal(t, 8, len(alphas)) + assert.Equal(t, 8, len(alphas)) + assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes())) ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) + assert.Equal(t, 7, len(ax)) + assert.Equal(t, 7, len(bx)) + assert.Equal(t, 7, len(cx)) + assert.Equal(t, 13, len(px)) - hx := Utils.PF.DivisorPolynomial(px, zx) + // calculate trusted setup + setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas) + assert.Nil(t, err) + fmt.Println("\nt:", setup.Toxic.T) - // hx==px/zx so px==hx*zx - assert.Equal(t, px, Utils.PF.Mul(hx, zx)) + hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) + div, rem := Utils.PF.Div(px, setup.Pk.Z) + assert.Equal(t, hx, div) + assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6)) - // p(x) = a(x) * b(x) - c(x) == h(x) * z(x) - abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx) - assert.Equal(t, abc, px) - hz := Utils.PF.Mul(hx, zx) - assert.Equal(t, abc, hz) + // hx==px/zx so px==hx*zx + assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z)) - div, rem := Utils.PF.Div(px, zx) - assert.Equal(t, hx, div) - assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(1)) + // check length of polynomials H(x) and Z(x) + assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1) - // calculate trusted setup - setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx) + proof, err := GenerateProofs(*circuit, setup, w, px) assert.Nil(t, err) - // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) - proof, err := GenerateProofs(*circuit, setup, hx, w) - assert.Nil(t, err) + // fmt.Println("\n proofs:") + // fmt.Println(proof) - // assert.True(t, VerifyProof(*circuit, setup, proof, false)) - b35 := big.NewInt(int64(35)) - publicSignals := []*big.Int{b35} - assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true)) + // fmt.Println("public signals:", proof.PublicSignals) + fmt.Println("\nsignals:", circuit.Signals) + fmt.Println("witness:", w) + b35Verif := big.NewInt(int64(35)) + publicSignalsVerif := []*big.Int{b35Verif} + before := time.Now() + assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true)) + fmt.Println("verify proof time elapsed:", time.Since(before)) + + // check that with another public input the verification returns false + bOtherWrongPublic := big.NewInt(int64(34)) + wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic} + assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true)) } -*/