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// ProvingKeyString is the equivalent to the ProvingKey struct in string representation
16type ProvingKeyString 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// ParseWitness parses the json []byte data into the Witness struct
39func ParseWitness(wJson []byte) (Witness, error) {
40 var ws WitnessString
41 err := json.Unmarshal(wJson, &ws)
42 if err != nil {
43 return nil, err
44 }
45
46 var w Witness
47 for i := 0; i < len(ws); i++ {
48 bi, err := stringToBigInt(ws[i])
49 if err != nil {
50 return nil, err
51 }
52 w = append(w, bi)
53 }
54 return w, nil
55}
56
57// ParseProvingKey parses the json []byte data into the ProvingKey struct
58func ParseProvingKey(pkJson []byte) (*ProvingKey, error) {
59 var pkStr ProvingKeyString
60 err := json.Unmarshal(pkJson, &pkStr)
61 if err != nil {
62 return nil, err
63 }
64 pk, err := provingKeyStringToProvingKey(pkStr)
65 return pk, err
66}
67
68func provingKeyStringToProvingKey(ps ProvingKeyString) (*ProvingKey, error) {
69 var p ProvingKey
70 var err error
71
72 p.A, err = arrayStringToG1(ps.A)
73 if err != nil {
74 return nil, err
75 }
76 p.B2, err = arrayStringToG2(ps.B2)
77 if err != nil {
78 return nil, err
79 }
80 p.B1, err = arrayStringToG1(ps.B1)
81 if err != nil {
82 return nil, err
83 }
84 p.C, err = arrayStringToG1(ps.C)
85 if err != nil {
86 return nil, err
87 }
88
89 p.NVars = ps.NVars
90 p.NPublic = ps.NPublic
91
92 p.VkAlpha1, err = stringToG1(ps.VkAlpha1)
93 if err != nil {
94 return nil, err
95 }
96
97 p.VkDelta1, err = stringToG1(ps.VkDelta1)
98 if err != nil {
99 return nil, err
100 }
101
102 p.VkBeta1, err = stringToG1(ps.VkBeta1)
103 if err != nil {
104 return nil, err
105 }
106 p.VkBeta2, err = stringToG2(ps.VkBeta2)
107 if err != nil {
108 return nil, err
109 }
110 p.VkDelta2, err = stringToG2(ps.VkDelta2)
111 if err != nil {
112 return nil, err
113 }
114
115 p.HExps, err = arrayStringToG1(ps.HExps)
116 if err != nil {
117 return nil, err
118 }
119
120 p.DomainSize = ps.DomainSize
121
122 p.PolsA, err = polsStringToBigInt(ps.PolsA)
123 if err != nil {
124 return nil, err
125 }
126 p.PolsB, err = polsStringToBigInt(ps.PolsB)
127 if err != nil {
128 return nil, err
129 }
130 p.PolsC, err = polsStringToBigInt(ps.PolsC)
131 if err != nil {
132 return nil, err
133 }
134
135 return &p, nil
136}
137
138// polsStringToBigInt is for taking string polynomials and converting it to *big.Int polynomials
139func polsStringToBigInt(s []map[string]string) ([]map[int]*big.Int, error) {
140 var o []map[int]*big.Int
141 for i := 0; i < len(s); i++ {
142 // var oi map[int]*big.Int
143 oi := make(map[int]*big.Int)
144 for j, v := range s[i] {
145 si, err := stringToBigInt(v)
146 if err != nil {
147 return o, err
148 }
149 // oi = append(oi, si)
150 jInt, err := strconv.Atoi(j)
151 if err != nil {
152 fmt.Println(j)
153 return o, err
154 }
155 fmt.Println(jInt, si)
156 oi[jInt] = si
157 }
158 o = append(o, oi)
159 }
160 return o, nil
161}
162
163func arrayStringToBigInt(s []string) ([]*big.Int, error) {
164 var o []*big.Int
165 for i := 0; i < len(s); i++ {
166 si, err := stringToBigInt(s[i])
167 if err != nil {
168 return o, nil
169 }
170 o = append(o, si)
171 }
172 return o, nil
173}
174
175func stringToBigInt(s string) (*big.Int, error) {
176 base := 10
177 if bytes.HasPrefix([]byte(s), []byte("0x")) {
178 base = 16
179 s = strings.TrimPrefix(s, "0x")
180 }
181 n, ok := new(big.Int).SetString(s, base)
182 if !ok {
183 return nil, fmt.Errorf("Can not parse string to *big.Int: %s", s)
184 }
185 return n, nil
186}
187
188func addZPadding(b []byte) []byte {
189 var z [32]byte
190 var r []byte
191 r = append(r, z[len(b):]...) // add padding on the left
192 r = append(r, b...)
193 return r[:32]
194}
195
196func stringToBytes(s string) ([]byte, error) {
197 if s == "1" {
198 s = "0"
199 }
200 bi, ok := new(big.Int).SetString(s, 10)
201 if !ok {
202 return nil, fmt.Errorf("error parsing bigint stringToBytes")
203 }
204 b := bi.Bytes()
205 if len(b) != 32 {
206 b = addZPadding(b)
207 }
208 return b, nil
209
210}
211
212func arrayStringToG1(h [][]string) ([]*bn256.G1, error) {
213 var o []*bn256.G1
214 for i := 0; i < len(h); i++ {
215 hi, err := stringToG1(h[i])
216 if err != nil {
217 return o, err
218 }
219 o = append(o, hi)
220 }
221 return o, nil
222}
223
224func arrayStringToG2(h [][][]string) ([]*bn256.G2, error) {
225 var o []*bn256.G2
226 for i := 0; i < len(h); i++ {
227 hi, err := stringToG2(h[i])
228 if err != nil {
229 return o, err
230 }
231 o = append(o, hi)
232 }
233 return o, nil
234}
235
236func stringToG1(h []string) (*bn256.G1, error) {
237 if len(h) <= 2 {
238 return nil, fmt.Errorf("not enought data for stringToG1")
239 }
240 h = h[:2]
241 hexa := false
242 if len(h[0]) > 1 {
243 if "0x" == h[0][:2] {
244 hexa = true
245 }
246 }
247 in := ""
248
249 var b []byte
250 var err error
251 if hexa {
252 for i := range h {
253 in += strings.TrimPrefix(h[i], "0x")
254 }
255 b, err = hex.DecodeString(in)
256 if err != nil {
257 return nil, err
258 }
259 } else {
260 // TODO TMP
261 // TODO use stringToBytes()
262 if h[0] == "1" {
263 h[0] = "0"
264 }
265 if h[1] == "1" {
266 h[1] = "0"
267 }
268 bi0, ok := new(big.Int).SetString(h[0], 10)
269 if !ok {
270 return nil, fmt.Errorf("error parsing stringToG1")
271 }
272 bi1, ok := new(big.Int).SetString(h[1], 10)
273 if !ok {
274 return nil, fmt.Errorf("error parsing stringToG1")
275 }
276 b0 := bi0.Bytes()
277 b1 := bi1.Bytes()
278 if len(b0) != 32 {
279 b0 = addZPadding(b0)
280 }
281 if len(b1) != 32 {
282 b1 = addZPadding(b1)
283 }
284
285 b = append(b, b0...)
286 b = append(b, b1...)
287 }
288 p := new(bn256.G1)
289 _, err = p.Unmarshal(b)
290
291 return p, err
292}
293
294func stringToG2(h [][]string) (*bn256.G2, error) {
295 if len(h) <= 2 {
296 return nil, fmt.Errorf("not enought data for stringToG2")
297 }
298 h = h[:2]
299 hexa := false
300 if len(h[0][0]) > 1 {
301 if "0x" == h[0][0][:2] {
302 hexa = true
303 }
304 }
305 in := ""
306 var b []byte
307 var err error
308 if hexa {
309 for i := 0; i < len(h); i++ {
310 for j := 0; j < len(h[i]); j++ {
311 in += strings.TrimPrefix(h[i][j], "0x")
312 }
313 }
314 b, err = hex.DecodeString(in)
315 if err != nil {
316 return nil, err
317 }
318 } else {
319 // TODO TMP
320 bH, err := stringToBytes(h[0][1])
321 if err != nil {
322 return nil, err
323 }
324 b = append(b, bH...)
325 bH, err = stringToBytes(h[0][0])
326 if err != nil {
327 return nil, err
328 }
329 b = append(b, bH...)
330 bH, err = stringToBytes(h[1][1])
331 if err != nil {
332 return nil, err
333 }
334 b = append(b, bH...)
335 bH, err = stringToBytes(h[1][0])
336 if err != nil {
337 return nil, err
338 }
339 b = append(b, bH...)
340 }
341
342 p := new(bn256.G2)
343 _, err = p.Unmarshal(b)
344 return p, err
345}