go-circom-prover-verifier/parsers.go
parsers.goRaw
1package gocircomprover
2
3import (
4 "bytes"
5 "encoding/hex"
6 "encoding/json"
7 "fmt"
8 "math/big"
9 "strconv"
10 "strings"
11
12 bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
13)
14
15// PkString is the equivalent to the Pk struct in string representation, containing the ProvingKey
16type PkString struct {
17 A [][]string `json:"A"`
18 B2 [][][]string `json:"B2"`
19 B1 [][]string `json:"B1"`
20 C [][]string `json:"C"`
21 NVars int `json:"nVars"`
22 NPublic int `json:"nPublic"`
23 VkAlpha1 []string `json:"vk_alfa_1"`
24 VkDelta1 []string `json:"vk_delta_1"`
25 VkBeta1 []string `json:"vk_beta_1"`
26 VkBeta2 [][]string `json:"vk_beta_2"`
27 VkDelta2 [][]string `json:"vk_delta_2"`
28 HExps [][]string `json:"hExps"`
29 DomainSize int `json:"domainSize"`
30 PolsA []map[string]string `json:"polsA"`
31 PolsB []map[string]string `json:"polsB"`
32 PolsC []map[string]string `json:"polsC"`
33}
34
35// WitnessString contains the Witness in string representation
36type WitnessString []string
37
38// ProofString is the equivalent to the Proof struct in string representation
39type ProofString struct {
40 A []string `json:"pi_a"`
41 B [][]string `json:"pi_b"`
42 C []string `json:"pi_c"`
43 Protocol string `json:"protocol"`
44}
45
46// VkString is the Verification Key data structure in string format (from json)
47type VkString struct {
48 Alpha []string `json:"vk_alfa_1"`
49 Beta [][]string `json:"vk_beta_2"`
50 Gamma [][]string `json:"vk_gamma_2"`
51 Delta [][]string `json:"vk_delta_2"`
52 IC [][]string `json:"IC"`
53}
54
55// ParseWitness parses the json []byte data into the Witness struct
56func ParseWitness(wJson []byte) (Witness, error) {
57 var ws WitnessString
58 err := json.Unmarshal(wJson, &ws)
59 if err != nil {
60 return nil, err
61 }
62
63 var w Witness
64 for i := 0; i < len(ws); i++ {
65 bi, err := stringToBigInt(ws[i])
66 if err != nil {
67 return nil, err
68 }
69 w = append(w, bi)
70 }
71 return w, nil
72}
73
74// ParsePk parses the json []byte data into the Pk struct
75func ParsePk(pkJson []byte) (*Pk, error) {
76 var pkStr PkString
77 err := json.Unmarshal(pkJson, &pkStr)
78 if err != nil {
79 return nil, err
80 }
81 pk, err := pkStringToPk(pkStr)
82 return pk, err
83}
84
85func pkStringToPk(ps PkString) (*Pk, error) {
86 var p Pk
87 var err error
88
89 p.A, err = arrayStringToG1(ps.A)
90 if err != nil {
91 return nil, err
92 }
93 p.B2, err = arrayStringToG2(ps.B2)
94 if err != nil {
95 return nil, err
96 }
97 p.B1, err = arrayStringToG1(ps.B1)
98 if err != nil {
99 return nil, err
100 }
101 p.C, err = arrayStringToG1(ps.C)
102 if err != nil {
103 return nil, err
104 }
105
106 p.NVars = ps.NVars
107 p.NPublic = ps.NPublic
108
109 p.VkAlpha1, err = stringToG1(ps.VkAlpha1)
110 if err != nil {
111 return nil, err
112 }
113
114 p.VkDelta1, err = stringToG1(ps.VkDelta1)
115 if err != nil {
116 return nil, err
117 }
118
119 p.VkBeta1, err = stringToG1(ps.VkBeta1)
120 if err != nil {
121 return nil, err
122 }
123 p.VkBeta2, err = stringToG2(ps.VkBeta2)
124 if err != nil {
125 return nil, err
126 }
127 p.VkDelta2, err = stringToG2(ps.VkDelta2)
128 if err != nil {
129 return nil, err
130 }
131
132 p.HExps, err = arrayStringToG1(ps.HExps)
133 if err != nil {
134 return nil, err
135 }
136
137 p.DomainSize = ps.DomainSize
138
139 p.PolsA, err = polsStringToBigInt(ps.PolsA)
140 if err != nil {
141 return nil, err
142 }
143 p.PolsB, err = polsStringToBigInt(ps.PolsB)
144 if err != nil {
145 return nil, err
146 }
147 p.PolsC, err = polsStringToBigInt(ps.PolsC)
148 if err != nil {
149 return nil, err
150 }
151
152 return &p, nil
153}
154
155func proofStringToProof(pr ProofString) (*Proof, error) {
156 var p Proof
157 var err error
158 p.A, err = stringToG1(pr.A)
159 if err != nil {
160 return nil, err
161 }
162
163 p.B, err = stringToG2(pr.B)
164 if err != nil {
165 return nil, err
166 }
167
168 p.C, err = stringToG1(pr.C)
169 if err != nil {
170 return nil, err
171 }
172
173 return &p, nil
174}
175
176// ParseProof takes a json []byte and outputs the *Proof struct
177func ParseProof(pj []byte) (*Proof, error) {
178 var pr ProofString
179 err := json.Unmarshal(pj, &pr)
180 if err != nil {
181 return nil, err
182 }
183 p, err := proofStringToProof(pr)
184 return p, err
185}
186
187// ParsePublicSignals takes a json []byte and outputs the []*big.Int struct
188func ParsePublicSignals(pj []byte) ([]*big.Int, error) {
189 var pr []string
190 err := json.Unmarshal(pj, &pr)
191 if err != nil {
192 return nil, err
193 }
194 var public []*big.Int
195 for _, s := range pr {
196 sb, err := stringToBigInt(s)
197 if err != nil {
198 return nil, err
199 }
200 public = append(public, sb)
201 }
202 return public, nil
203}
204
205// ParseVk takes a json []byte and outputs the *Vk struct
206func ParseVk(vj []byte) (*Vk, error) {
207 var vr VkString
208 err := json.Unmarshal(vj, &vr)
209 if err != nil {
210 return nil, err
211 }
212 v, err := vkStringToVk(vr)
213 return v, err
214}
215
216func vkStringToVk(vr VkString) (*Vk, error) {
217 var v Vk
218 var err error
219 v.Alpha, err = stringToG1(vr.Alpha)
220 if err != nil {
221 return nil, err
222 }
223
224 v.Beta, err = stringToG2(vr.Beta)
225 if err != nil {
226 return nil, err
227 }
228
229 v.Gamma, err = stringToG2(vr.Gamma)
230 if err != nil {
231 return nil, err
232 }
233
234 v.Delta, err = stringToG2(vr.Delta)
235 if err != nil {
236 return nil, err
237 }
238
239 for i := 0; i < len(vr.IC); i++ {
240 p, err := stringToG1(vr.IC[i])
241 if err != nil {
242 return nil, err
243 }
244 v.IC = append(v.IC, p)
245 }
246
247 return &v, nil
248}
249
250// polsStringToBigInt is for taking string polynomials and converting it to *big.Int polynomials
251func polsStringToBigInt(s []map[string]string) ([]map[int]*big.Int, error) {
252 var o []map[int]*big.Int
253 for i := 0; i < len(s); i++ {
254 // var oi map[int]*big.Int
255 oi := make(map[int]*big.Int)
256 for j, v := range s[i] {
257 si, err := stringToBigInt(v)
258 if err != nil {
259 return o, err
260 }
261 // oi = append(oi, si)
262 jInt, err := strconv.Atoi(j)
263 if err != nil {
264 return o, err
265 }
266 oi[jInt] = si
267 }
268 o = append(o, oi)
269 }
270 return o, nil
271}
272
273// ArrayBigIntToString converts an []*big.Int into []string, used to output the Public Signals
274func ArrayBigIntToString(bi []*big.Int) []string {
275 var s []string
276 for i := 0; i < len(bi); i++ {
277 s = append(s, bi[i].String())
278 }
279 return s
280}
281
282func arrayStringToBigInt(s []string) ([]*big.Int, error) {
283 var o []*big.Int
284 for i := 0; i < len(s); i++ {
285 si, err := stringToBigInt(s[i])
286 if err != nil {
287 return o, nil
288 }
289 o = append(o, si)
290 }
291 return o, nil
292}
293
294func stringToBigInt(s string) (*big.Int, error) {
295 base := 10
296 if bytes.HasPrefix([]byte(s), []byte("0x")) {
297 base = 16
298 s = strings.TrimPrefix(s, "0x")
299 }
300 n, ok := new(big.Int).SetString(s, base)
301 if !ok {
302 return nil, fmt.Errorf("Can not parse string to *big.Int: %s", s)
303 }
304 return n, nil
305}
306
307func addZPadding(b []byte) []byte {
308 var z [32]byte
309 var r []byte
310 r = append(r, z[len(b):]...) // add padding on the left
311 r = append(r, b...)
312 return r[:32]
313}
314
315func stringToBytes(s string) ([]byte, error) {
316 if s == "1" {
317 s = "0"
318 }
319 bi, ok := new(big.Int).SetString(s, 10)
320 if !ok {
321 return nil, fmt.Errorf("error parsing bigint stringToBytes")
322 }
323 b := bi.Bytes()
324 if len(b) != 32 {
325 b = addZPadding(b)
326 }
327 return b, nil
328
329}
330
331func arrayStringToG1(h [][]string) ([]*bn256.G1, error) {
332 var o []*bn256.G1
333 for i := 0; i < len(h); i++ {
334 hi, err := stringToG1(h[i])
335 if err != nil {
336 return o, err
337 }
338 o = append(o, hi)
339 }
340 return o, nil
341}
342
343func arrayStringToG2(h [][][]string) ([]*bn256.G2, error) {
344 var o []*bn256.G2
345 for i := 0; i < len(h); i++ {
346 hi, err := stringToG2(h[i])
347 if err != nil {
348 return o, err
349 }
350 o = append(o, hi)
351 }
352 return o, nil
353}
354
355func stringToG1(h []string) (*bn256.G1, error) {
356 if len(h) <= 2 {
357 return nil, fmt.Errorf("not enought data for stringToG1")
358 }
359 h = h[:2]
360 hexa := false
361 if len(h[0]) > 1 {
362 if "0x" == h[0][:2] {
363 hexa = true
364 }
365 }
366 in := ""
367
368 var b []byte
369 var err error
370 if hexa {
371 for i := range h {
372 in += strings.TrimPrefix(h[i], "0x")
373 }
374 b, err = hex.DecodeString(in)
375 if err != nil {
376 return nil, err
377 }
378 } else {
379 // TODO TMP
380 // TODO use stringToBytes()
381 if h[0] == "1" {
382 h[0] = "0"
383 }
384 if h[1] == "1" {
385 h[1] = "0"
386 }
387 bi0, ok := new(big.Int).SetString(h[0], 10)
388 if !ok {
389 return nil, fmt.Errorf("error parsing stringToG1")
390 }
391 bi1, ok := new(big.Int).SetString(h[1], 10)
392 if !ok {
393 return nil, fmt.Errorf("error parsing stringToG1")
394 }
395 b0 := bi0.Bytes()
396 b1 := bi1.Bytes()
397 if len(b0) != 32 {
398 b0 = addZPadding(b0)
399 }
400 if len(b1) != 32 {
401 b1 = addZPadding(b1)
402 }
403
404 b = append(b, b0...)
405 b = append(b, b1...)
406 }
407 p := new(bn256.G1)
408 _, err = p.Unmarshal(b)
409
410 return p, err
411}
412
413func stringToG2(h [][]string) (*bn256.G2, error) {
414 if len(h) <= 2 {
415 return nil, fmt.Errorf("not enought data for stringToG2")
416 }
417 h = h[:2]
418 hexa := false
419 if len(h[0][0]) > 1 {
420 if "0x" == h[0][0][:2] {
421 hexa = true
422 }
423 }
424 in := ""
425 var b []byte
426 var err error
427 if hexa {
428 for i := 0; i < len(h); i++ {
429 for j := 0; j < len(h[i]); j++ {
430 in += strings.TrimPrefix(h[i][j], "0x")
431 }
432 }
433 b, err = hex.DecodeString(in)
434 if err != nil {
435 return nil, err
436 }
437 } else {
438 // TODO TMP
439 bH, err := stringToBytes(h[0][1])
440 if err != nil {
441 return nil, err
442 }
443 b = append(b, bH...)
444 bH, err = stringToBytes(h[0][0])
445 if err != nil {
446 return nil, err
447 }
448 b = append(b, bH...)
449 bH, err = stringToBytes(h[1][1])
450 if err != nil {
451 return nil, err
452 }
453 b = append(b, bH...)
454 bH, err = stringToBytes(h[1][0])
455 if err != nil {
456 return nil, err
457 }
458 b = append(b, bH...)
459 }
460
461 p := new(bn256.G2)
462 _, err = p.Unmarshal(b)
463 return p, err
464}
465
466// ProofToJson outputs the Proof i Json format
467func ProofToJson(p *Proof) ([]byte, error) {
468 var ps ProofString
469 ps.A = make([]string, 3)
470 ps.B = make([][]string, 3)
471 ps.B[0] = make([]string, 2)
472 ps.B[1] = make([]string, 2)
473 ps.B[2] = make([]string, 2)
474 ps.C = make([]string, 3)
475
476 a := p.A.Marshal()
477 ps.A[0] = new(big.Int).SetBytes(a[:32]).String()
478 ps.A[1] = new(big.Int).SetBytes(a[32:64]).String()
479 ps.A[2] = "1"
480
481 b := p.B.Marshal()
482 ps.B[0][1] = new(big.Int).SetBytes(b[:32]).String()
483 ps.B[0][0] = new(big.Int).SetBytes(b[32:64]).String()
484 ps.B[1][1] = new(big.Int).SetBytes(b[64:96]).String()
485 ps.B[1][0] = new(big.Int).SetBytes(b[96:128]).String()
486 ps.B[2][0] = "1"
487 ps.B[2][1] = "0"
488
489 c := p.C.Marshal()
490 ps.C[0] = new(big.Int).SetBytes(c[:32]).String()
491 ps.C[1] = new(big.Int).SetBytes(c[32:64]).String()
492 ps.C[2] = "1"
493
494 ps.Protocol = "groth"
495
496 return json.Marshal(ps)
497}