arnaucube
arnaucube/go-snarkPublic Self-hosted repository
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*/