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