go-snark/snark_test.go
snark_test.goRaw
1package snark
2
3import (
4 "fmt"
5 "math/big"
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/arnaucube/go-snark/circuitcompiler"
11 "github.com/arnaucube/go-snark/r1csqap"
12 "github.com/stretchr/testify/assert"
13)
14
15func TestZkFromFlatCircuitCode(t *testing.T) {
16
17 // compile circuit and get the R1CS
18 flatCode := `
19 func test(x):
20 aux = x*x
21 y = aux*x
22 z = x + y
23 out = z + 5
24 `
25 fmt.Print("\nflat code of the circuit:")
26 fmt.Println(flatCode)
27
28 // parse the code
29 parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
30 circuit, err := parser.Parse()
31 assert.Nil(t, err)
32 fmt.Println("\ncircuit data:", circuit)
33
34 b3 := big.NewInt(int64(3))
35 inputs := []*big.Int{b3}
36 // wittness
37 w := circuit.CalculateWitness(inputs)
38 fmt.Println("\nwitness", w)
39
40 // flat code to R1CS
41 fmt.Println("\ngenerating R1CS from flat code")
42 a, b, c := circuit.GenerateR1CS()
43 fmt.Println("\nR1CS:")
44 fmt.Println("a:", a)
45 fmt.Println("b:", b)
46 fmt.Println("c:", c)
47
48 // R1CS to QAP
49 alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
50 fmt.Println("qap")
51 fmt.Println(alphas)
52 fmt.Println(betas)
53 fmt.Println(gammas)
54
55 ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
56
57 hx := Utils.PF.DivisorPolynomial(px, zx)
58
59 // hx==px/zx so px==hx*zx
60 assert.Equal(t, px, Utils.PF.Mul(hx, zx))
61
62 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
63 abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
64 assert.Equal(t, abc, px)
65 hz := Utils.PF.Mul(hx, zx)
66 assert.Equal(t, abc, hz)
67
68 div, rem := Utils.PF.Div(px, zx)
69 assert.Equal(t, hx, div)
70 assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
71
72 // calculate trusted setup
73 setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
74 assert.Nil(t, err)
75 fmt.Println("\nt:", setup.Toxic.T)
76
77 // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
78 proof, err := GenerateProofs(*circuit, setup, hx, w)
79 assert.Nil(t, err)
80
81 fmt.Println("\n proofs:")
82 fmt.Println(proof)
83 before := time.Now()
84 assert.True(t, VerifyProof(*circuit, setup, proof))
85 fmt.Println("verify proof time elapsed:", time.Since(before))
86}
87
88func TestZkFromHardcodedR1CS(t *testing.T) {
89
90 b0 := big.NewInt(int64(0))
91 b1 := big.NewInt(int64(1))
92 b3 := big.NewInt(int64(3))
93 b5 := big.NewInt(int64(5))
94 b9 := big.NewInt(int64(9))
95 b27 := big.NewInt(int64(27))
96 b30 := big.NewInt(int64(30))
97 b35 := big.NewInt(int64(35))
98 a := [][]*big.Int{
99 []*big.Int{b0, b1, b0, b0, b0, b0},
100 []*big.Int{b0, b0, b0, b1, b0, b0},
101 []*big.Int{b0, b1, b0, b0, b1, b0},
102 []*big.Int{b5, b0, b0, b0, b0, b1},
103 }
104 b := [][]*big.Int{
105 []*big.Int{b0, b1, b0, b0, b0, b0},
106 []*big.Int{b0, b1, b0, b0, b0, b0},
107 []*big.Int{b1, b0, b0, b0, b0, b0},
108 []*big.Int{b1, b0, b0, b0, b0, b0},
109 }
110 c := [][]*big.Int{
111 []*big.Int{b0, b0, b0, b1, b0, b0},
112 []*big.Int{b0, b0, b0, b0, b1, b0},
113 []*big.Int{b0, b0, b0, b0, b0, b1},
114 []*big.Int{b0, b0, b1, b0, b0, b0},
115 }
116 alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
117
118 // wittness = 1, 3, 35, 9, 27, 30
119 w := []*big.Int{b1, b3, b35, b9, b27, b30}
120 circuit := circuitcompiler.Circuit{
121 NVars: 6,
122 NPublic: 0,
123 NSignals: len(w),
124 }
125 ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
126
127 hx := Utils.PF.DivisorPolynomial(px, zx)
128
129 // hx==px/zx so px==hx*zx
130 assert.Equal(t, px, Utils.PF.Mul(hx, zx))
131
132 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
133 abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
134 assert.Equal(t, abc, px)
135 hz := Utils.PF.Mul(hx, zx)
136 assert.Equal(t, abc, hz)
137
138 div, rem := Utils.PF.Div(px, zx)
139 assert.Equal(t, hx, div)
140 assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
141
142 // calculate trusted setup
143 setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx)
144 assert.Nil(t, err)
145 fmt.Println("t", setup.Toxic.T)
146
147 // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
148 proof, err := GenerateProofs(circuit, setup, hx, w)
149 assert.Nil(t, err)
150
151 assert.True(t, VerifyProof(circuit, setup, proof))
152}