go-snark/snark_test.go
snark_test.goRaw
1package snark
2
3import (
4 "encoding/json"
5 "fmt"
6 "math/big"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/arnaucube/go-snark/circuitcompiler"
12 "github.com/arnaucube/go-snark/r1csqap"
13 "github.com/stretchr/testify/assert"
14)
15
16/*
17func TestZkMultiplication(t *testing.T) {
18
19 // compile circuit and get the R1CS
20 flatCode := `
21 func test(a, b):
22 out = a * b
23 `
24
25 // parse the code
26 parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
27 circuit, err := parser.Parse()
28 assert.Nil(t, err)
29
30 b3 := big.NewInt(int64(3))
31 b4 := big.NewInt(int64(4))
32 inputs := []*big.Int{b3, b4}
33 // wittness
34 w, err := circuit.CalculateWitness(inputs)
35 assert.Nil(t, err)
36
37 fmt.Println("circuit")
38 fmt.Println(circuit.NPublic)
39
40 // flat code to R1CS
41 a, b, c := circuit.GenerateR1CS()
42 fmt.Println("\nR1CS:")
43 fmt.Println("a:", a)
44 fmt.Println("b:", b)
45 fmt.Println("c:", c)
46
47 // R1CS to QAP
48 alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
49 fmt.Println("qap")
50 fmt.Println("alphas", alphas)
51 fmt.Println("betas", betas)
52 fmt.Println("gammas", gammas)
53
54 ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
55
56 hx := Utils.PF.DivisorPolynomial(px, zx)
57
58 // hx==px/zx so px==hx*zx
59 assert.Equal(t, px, Utils.PF.Mul(hx, zx))
60
61 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
62 abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
63 assert.Equal(t, abc, px)
64 hz := Utils.PF.Mul(hx, zx)
65 assert.Equal(t, abc, hz)
66
67 div, rem := Utils.PF.Div(px, zx)
68 assert.Equal(t, hx, div)
69 assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(1))
70
71 // calculate trusted setup
72 setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
73 assert.Nil(t, err)
74
75 // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
76 proof, err := GenerateProofs(*circuit, setup, hx, w)
77 assert.Nil(t, err)
78
79 // assert.True(t, VerifyProof(*circuit, setup, proof, false))
80 b35 := big.NewInt(int64(35))
81 publicSignals := []*big.Int{b35}
82 assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
83}
84*/
85
86func TestZkFromFlatCircuitCode(t *testing.T) {
87
88 // compile circuit and get the R1CS
89 flatCode := `
90 func test(x):
91 aux = x*x
92 y = aux*x
93 z = x + y
94 out = z + 5
95 `
96 fmt.Print("\nflat code of the circuit:")
97 fmt.Println(flatCode)
98
99 // parse the code
100 parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
101 circuit, err := parser.Parse()
102 assert.Nil(t, err)
103 fmt.Println("\ncircuit data:", circuit)
104 circuitJson, _ := json.Marshal(circuit)
105 fmt.Println("circuit:", string(circuitJson))
106
107 b3 := big.NewInt(int64(3))
108 privateInputs := []*big.Int{b3}
109 // wittness
110 w, err := circuit.CalculateWitness(privateInputs)
111 assert.Nil(t, err)
112 fmt.Println("\nwitness", w)
113
114 // flat code to R1CS
115 fmt.Println("\ngenerating R1CS from flat code")
116 a, b, c := circuit.GenerateR1CS()
117 fmt.Println("\nR1CS:")
118 fmt.Println("a:", a)
119 fmt.Println("b:", b)
120 fmt.Println("c:", c)
121
122 // R1CS to QAP
123 alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
124 fmt.Println("qap")
125 fmt.Println("alphas", alphas)
126 fmt.Println("betas", betas)
127 fmt.Println("gammas", gammas)
128 fmt.Println("zx", zx)
129
130 ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
131 fmt.Println("ax", ax)
132 // fmt.Println("bx", bx)
133 // fmt.Println("cx", cx)
134 // fmt.Println("px", px)
135
136 hx := Utils.PF.DivisorPolynomial(px, zx)
137
138 // hx==px/zx so px==hx*zx
139 assert.Equal(t, px, Utils.PF.Mul(hx, zx))
140
141 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
142 abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
143 assert.Equal(t, abc, px)
144 hz := Utils.PF.Mul(hx, zx)
145 assert.Equal(t, abc, hz)
146
147 div, rem := Utils.PF.Div(px, zx)
148 assert.Equal(t, hx, div)
149 assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
150
151 // calculate trusted setup
152 setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
153 // setup, err := GenerateTrustedSetup(len(w), *circuit, ax, bx, cx, zx)
154 assert.Nil(t, err)
155 fmt.Println("\nt:", setup.Toxic.T)
156
157 // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
158 proof, err := GenerateProofs(*circuit, setup, hx, w)
159 assert.Nil(t, err)
160 fmt.Println("IC", setup.Vk.IC)
161
162 // fmt.Println("\n proofs:")
163 // fmt.Println(proof)
164
165 // fmt.Println("public signals:", proof.PublicSignals)
166 fmt.Println("\nwitness", w)
167 b35 := big.NewInt(int64(35))
168 publicSignals := []*big.Int{b35}
169 fmt.Println("public signals:", publicSignals)
170 before := time.Now()
171 assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
172 fmt.Println("verify proof time elapsed:", time.Since(before))
173}
174
175/*
176func TestZkFromHardcodedR1CS(t *testing.T) {
177 b0 := big.NewInt(int64(0))
178 b1 := big.NewInt(int64(1))
179 b3 := big.NewInt(int64(3))
180 b5 := big.NewInt(int64(5))
181 b9 := big.NewInt(int64(9))
182 b27 := big.NewInt(int64(27))
183 b30 := big.NewInt(int64(30))
184 b35 := big.NewInt(int64(35))
185 a := [][]*big.Int{
186 []*big.Int{b0, b0, b1, b0, b0, b0},
187 []*big.Int{b0, b0, b0, b1, b0, b0},
188 []*big.Int{b0, b0, b1, b0, b1, b0},
189 []*big.Int{b5, b0, b0, b0, b0, b1},
190 }
191 b := [][]*big.Int{
192 []*big.Int{b0, b0, b1, b0, b0, b0},
193 []*big.Int{b0, b0, b1, b0, b0, b0},
194 []*big.Int{b1, b0, b0, b0, b0, b0},
195 []*big.Int{b1, b0, b0, b0, b0, b0},
196 }
197 c := [][]*big.Int{
198 []*big.Int{b0, b0, b0, b1, b0, b0},
199 []*big.Int{b0, b0, b0, b0, b1, b0},
200 []*big.Int{b0, b0, b0, b0, b0, b1},
201 []*big.Int{b0, b1, b0, b0, b0, b0},
202 }
203 alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
204
205 // wittness = 1, 35, 3, 9, 27, 30
206 w := []*big.Int{b1, b35, b3, b9, b27, b30}
207 circuit := circuitcompiler.Circuit{
208 NVars: 6,
209 NPublic: 1,
210 NSignals: len(w),
211 }
212 ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
213
214 hx := Utils.PF.DivisorPolynomial(px, zx)
215
216 // hx==px/zx so px==hx*zx
217 assert.Equal(t, px, Utils.PF.Mul(hx, zx))
218
219 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
220 abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
221 assert.Equal(t, abc, px)
222 hz := Utils.PF.Mul(hx, zx)
223 assert.Equal(t, abc, hz)
224
225 div, rem := Utils.PF.Div(px, zx)
226 assert.Equal(t, hx, div)
227 assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
228
229 // calculate trusted setup
230 setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx)
231 assert.Nil(t, err)
232
233 // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
234 proof, err := GenerateProofs(circuit, setup, hx, w)
235 assert.Nil(t, err)
236
237 // assert.True(t, VerifyProof(circuit, setup, proof, true))
238 publicSignals := []*big.Int{b35}
239 assert.True(t, VerifyProof(circuit, setup, proof, publicSignals, true))
240}
241
242func TestZkMultiplication(t *testing.T) {
243
244 // compile circuit and get the R1CS
245 flatCode := `
246 func test(a, b):
247 out = a * b
248 `
249
250 // parse the code
251 parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
252 circuit, err := parser.Parse()
253 assert.Nil(t, err)
254
255 b3 := big.NewInt(int64(3))
256 b4 := big.NewInt(int64(4))
257 inputs := []*big.Int{b3, b4}
258 // wittness
259 w, err := circuit.CalculateWitness(inputs)
260 assert.Nil(t, err)
261
262 // flat code to R1CS
263 a, b, c := circuit.GenerateR1CS()
264
265 // R1CS to QAP
266 alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
267
268 ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
269
270 hx := Utils.PF.DivisorPolynomial(px, zx)
271
272 // hx==px/zx so px==hx*zx
273 assert.Equal(t, px, Utils.PF.Mul(hx, zx))
274
275 // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
276 abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
277 assert.Equal(t, abc, px)
278 hz := Utils.PF.Mul(hx, zx)
279 assert.Equal(t, abc, hz)
280
281 div, rem := Utils.PF.Div(px, zx)
282 assert.Equal(t, hx, div)
283 assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(1))
284
285 // calculate trusted setup
286 setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
287 assert.Nil(t, err)
288
289 // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
290 proof, err := GenerateProofs(*circuit, setup, hx, w)
291 assert.Nil(t, err)
292
293 // assert.True(t, VerifyProof(*circuit, setup, proof, false))
294 b35 := big.NewInt(int64(35))
295 publicSignals := []*big.Int{b35}
296 assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
297}
298*/