arnaucube
arnaucube/go-bellman-verifierPublic Self-hosted repository
go-bellman-verifier/verifier.go
verifier.goRaw
  1package bellmanverifier
  2
  3import (
  4	"bytes"
  5	"encoding/hex"
  6	"encoding/json"
  7	"fmt"
  8	"math/big"
  9	"strings"
 10
 11	bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
 12)
 13
 14var q *big.Int
 15
 16func init() {
 17	var err error
 18	q, err = stringToBigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617")
 19	if err != nil {
 20		panic(err)
 21	}
 22}
 23
 24// Vk is the Verification Key data structure
 25type Vk struct {
 26	Alpha    *bn256.G1
 27	Beta     *bn256.G2
 28	Gamma    *bn256.G2
 29	Delta    *bn256.G2
 30	GammaABC []*bn256.G1
 31}
 32
 33// VkRaw is the Verification Key data structure in string format (from json)
 34type VkRaw struct {
 35	Alpha    []string   `json:"alpha_g1"`
 36	Beta     [][]string `json:"beta_g2"`
 37	Gamma    [][]string `json:"gamma_g2"`
 38	Delta    [][]string `json:"delta_g2"`
 39	GammaABC [][]string `json:"ic"`
 40}
 41
 42// Proof is the Groth16 Proof data structure
 43type Proof struct {
 44	A *bn256.G1
 45	B *bn256.G2
 46	C *bn256.G1
 47}
 48
 49// ProofRaw is the Groth16 Proof data structure in string format (from json)
 50type ProofRaw struct {
 51	A      []string   `json:"a"`
 52	B      [][]string `json:"b"`
 53	C      []string   `json:"c"`
 54	Inputs []string   `json:"inputs"`
 55}
 56
 57func hexToG1(h []string) (*bn256.G1, error) {
 58	in := ""
 59	for i := range h {
 60		in += strings.TrimPrefix(h[i], "0x")
 61	}
 62
 63	b, err := hex.DecodeString(in)
 64	if err != nil {
 65		return nil, err
 66	}
 67	p := new(bn256.G1)
 68	_, err = p.Unmarshal(b)
 69
 70	return p, err
 71}
 72
 73func hexToG2Regular(h [][]string) (*bn256.G2, error) {
 74	in := ""
 75	for i := 0; i < len(h); i++ {
 76		for j := 0; j < len(h[i]); j++ {
 77			in += strings.TrimPrefix(h[i][j], "0x")
 78		}
 79	}
 80
 81	b, err := hex.DecodeString(in)
 82	if err != nil {
 83		return nil, err
 84	}
 85	p := new(bn256.G2)
 86	_, err = p.Unmarshal(b)
 87	return p, err
 88}
 89
 90func hexToG2(h [][]string) (*bn256.G2, error) {
 91	in := ""
 92	in += strings.TrimPrefix(h[0][1], "0x") // note that values are switched
 93	in += strings.TrimPrefix(h[0][0], "0x")
 94	in += strings.TrimPrefix(h[1][1], "0x")
 95	in += strings.TrimPrefix(h[1][0], "0x")
 96
 97	b, err := hex.DecodeString(in)
 98	if err != nil {
 99		return nil, err
100	}
101	p := new(bn256.G2)
102	_, err = p.Unmarshal(b)
103	return p, err
104}
105
106func stringToBigInt(s string) (*big.Int, error) {
107	base := 10
108	if bytes.HasPrefix([]byte(s), []byte("0x")) {
109		base = 16
110		s = strings.TrimPrefix(s, "0x")
111	}
112	n, ok := new(big.Int).SetString(s, base)
113	if !ok {
114		return nil, fmt.Errorf("Can not parse string to *big.Int: %s", s)
115	}
116	return n, nil
117}
118
119// ParsePublicRaw takes a json []byte and outputs the []*big.Int struct
120func ParsePublicRaw(pj []byte) ([]*big.Int, error) {
121	var pr []string
122	err := json.Unmarshal(pj, &pr)
123	if err != nil {
124		return nil, err
125	}
126	var public []*big.Int
127	for _, s := range pr {
128		sb, err := stringToBigInt(s)
129		if err != nil {
130			return nil, err
131		}
132		public = append(public, sb)
133	}
134	return public, nil
135}
136
137// ParseVkRaw takes a json []byte and outputs the *Vk struct
138func ParseVkRaw(vj []byte) (*Vk, error) {
139	var vr VkRaw
140	err := json.Unmarshal(vj, &vr)
141	if err != nil {
142		return nil, err
143	}
144	v, err := vkRawToVk(vr)
145	return v, err
146}
147
148// ParseProofRaw takes a json []byte and outputs the *Proof struct
149func ParseProofRaw(pj []byte) (*Proof, error) {
150	var pr ProofRaw
151	err := json.Unmarshal(pj, &pr)
152	if err != nil {
153		return nil, err
154	}
155	p, err := proofRawToProof(pr)
156	return p, err
157}
158
159func vkRawToVk(vr VkRaw) (*Vk, error) {
160	var v Vk
161	var err error
162	v.Alpha, err = hexToG1(vr.Alpha)
163	if err != nil {
164		return nil, err
165	}
166
167	v.Beta, err = hexToG2(vr.Beta)
168	if err != nil {
169		return nil, err
170	}
171
172	v.Gamma, err = hexToG2(vr.Gamma)
173	if err != nil {
174		return nil, err
175	}
176
177	v.Delta, err = hexToG2(vr.Delta)
178	if err != nil {
179		return nil, err
180	}
181
182	for i := 0; i < len(vr.GammaABC); i++ {
183		p, err := hexToG1(vr.GammaABC[i])
184		if err != nil {
185			return nil, err
186		}
187		v.GammaABC = append(v.GammaABC, p)
188	}
189
190	return &v, nil
191}
192
193func proofRawToProof(pr ProofRaw) (*Proof, error) {
194	var p Proof
195	var err error
196	p.A, err = hexToG1(pr.A)
197	if err != nil {
198		return nil, err
199	}
200
201	p.B, err = hexToG2(pr.B)
202	if err != nil {
203		return nil, err
204	}
205
206	p.C, err = hexToG1(pr.C)
207	if err != nil {
208		return nil, err
209	}
210
211	return &p, nil
212}
213
214// Verify performs the Groth16 zkSnark verification
215func Verify(vk *Vk, proof *Proof, inputs []*big.Int) bool {
216	if len(inputs)+1 != len(vk.GammaABC) {
217		fmt.Println("len(inputs)+1 != len(vk.GammaABC)")
218		return false
219	}
220	vkX := new(bn256.G1).ScalarBaseMult(big.NewInt(0))
221	for i := 0; i < len(inputs); i++ {
222		// check input inside field
223		if inputs[i].Cmp(q) != -1 {
224			return false
225		}
226		vkX = new(bn256.G1).Add(vkX, new(bn256.G1).ScalarMult(vk.GammaABC[i+1], inputs[i]))
227	}
228	vkX = new(bn256.G1).Add(vkX, vk.GammaABC[0])
229
230	g1 := []*bn256.G1{proof.A, vk.Alpha.Neg(vk.Alpha), vkX.Neg(vkX), proof.C.Neg(proof.C)}
231	g2 := []*bn256.G2{proof.B, vk.Beta, vk.Gamma, vk.Delta}
232	return bn256.PairingCheck(g1, g2)
233}