Browse Source

minimal clean & update tests

pull/10/head
arnaucube 5 years ago
parent
commit
8ad8ae35f7
7 changed files with 229 additions and 292 deletions
  1. +47
    -48
      README.md
  2. +4
    -9
      circuitcompiler/circuit.go
  3. +49
    -59
      circuitcompiler/circuit_test.go
  4. +0
    -5
      circuitcompiler/parser.go
  5. +29
    -14
      cli/main.go
  6. +5
    -5
      snark.go
  7. +95
    -152
      snark_test.go

+ 47
- 48
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
```

+ 4
- 9
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 {

+ 49
- 59
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)

+ 0
- 5
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,

+ 29
- 14
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")

+ 5
- 5
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 {

+ 95
- 152
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))
}
*/

Loading…
Cancel
Save