github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl (about) 1 import ( 2 {{ template "import_curve" . }} 3 {{ template "import_pedersen" . }} 4 "github.com/consensys/gnark/internal/utils" 5 "github.com/consensys/gnark-crypto/utils/unsafe" 6 "io" 7 ) 8 9 // WriteTo writes binary encoding of the Proof elements to writer 10 // points are stored in compressed form Ar | Krs | Bs 11 // use WriteRawTo(...) to encode the proof without point compression 12 func (proof *Proof) WriteTo(w io.Writer) (n int64, err error) { 13 return proof.writeTo(w, false) 14 } 15 16 // WriteRawTo writes binary encoding of the Proof elements to writer 17 // points are stored in uncompressed form Ar | Krs | Bs 18 // use WriteTo(...) to encode the proof with point compression 19 func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) { 20 return proof.writeTo(w, true) 21 } 22 23 func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) { 24 var enc *curve.Encoder 25 if raw { 26 enc = curve.NewEncoder(w, curve.RawEncoding()) 27 } else { 28 enc = curve.NewEncoder(w) 29 } 30 31 if err := enc.Encode(&proof.Ar); err != nil { 32 return enc.BytesWritten(), err 33 } 34 if err := enc.Encode(&proof.Bs); err != nil { 35 return enc.BytesWritten(), err 36 } 37 if err := enc.Encode(&proof.Krs); err != nil { 38 return enc.BytesWritten(), err 39 } 40 if err := enc.Encode(proof.Commitments); err != nil { 41 return enc.BytesWritten(), err 42 } 43 if err := enc.Encode(&proof.CommitmentPok); err != nil { 44 return enc.BytesWritten(), err 45 } 46 47 return enc.BytesWritten(), nil 48 } 49 50 51 // ReadFrom attempts to decode a Proof from reader 52 // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) 53 func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) { 54 55 dec := curve.NewDecoder(r) 56 57 if err := dec.Decode(&proof.Ar); err != nil { 58 return dec.BytesRead(), err 59 } 60 if err := dec.Decode(&proof.Bs); err != nil { 61 return dec.BytesRead(), err 62 } 63 if err := dec.Decode(&proof.Krs); err != nil { 64 return dec.BytesRead(), err 65 } 66 if err := dec.Decode(&proof.Commitments); err != nil { 67 return dec.BytesRead(), err 68 } 69 if err := dec.Decode(&proof.CommitmentPok); err != nil { 70 return dec.BytesRead(), err 71 } 72 73 return dec.BytesRead(), nil 74 } 75 76 // WriteTo writes binary encoding of the key elements to writer 77 // points are compressed 78 // use WriteRawTo(...) to encode the key without point compression 79 func (vk *VerifyingKey) WriteTo(w io.Writer) (n int64, err error) { 80 return vk.writeTo(w, false) 81 } 82 83 // WriteRawTo writes binary encoding of the key elements to writer 84 // points are not compressed 85 // use WriteTo(...) to encode the key with point compression 86 func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) { 87 return vk.writeTo(w, true) 88 } 89 90 // writeTo serialization format: 91 // follows bellman format: 92 // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 93 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 94 func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) { 95 var enc *curve.Encoder 96 if raw { 97 enc = curve.NewEncoder(w, curve.RawEncoding()) 98 } else { 99 enc = curve.NewEncoder(w) 100 } 101 if vk.PublicAndCommitmentCommitted == nil { 102 vk.PublicAndCommitmentCommitted = [][]int{} // only matters in tests 103 } 104 toEncode := []interface{}{ 105 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2 106 &vk.G1.Alpha, 107 &vk.G1.Beta, 108 &vk.G2.Beta, 109 &vk.G2.Gamma, 110 &vk.G1.Delta, 111 &vk.G2.Delta, 112 // uint32(len(Kvk)),[Kvk]1 113 vk.G1.K, 114 utils.IntSliceSliceToUint64SliceSlice(vk.PublicAndCommitmentCommitted), 115 uint32(len(vk.CommitmentKeys)), 116 } 117 for _, v := range toEncode { 118 if err := enc.Encode(v); err != nil { 119 return enc.BytesWritten(), err 120 } 121 } 122 var n int64 123 for i := range vk.CommitmentKeys { 124 var ( 125 m int64 126 err error 127 ) 128 if raw { 129 m, err = vk.CommitmentKeys[i].WriteRawTo(w) 130 } else { 131 m, err = vk.CommitmentKeys[i].WriteTo(w) 132 } 133 n += m 134 if err != nil { 135 return n + enc.BytesWritten(), err 136 } 137 } 138 return n + enc.BytesWritten(), nil 139 } 140 141 // ReadFrom attempts to decode a VerifyingKey from reader 142 // VerifyingKey must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) 143 // serialization format: 144 // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 145 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 146 func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { 147 return vk.readFrom(r, false) 148 } 149 150 // UnsafeReadFrom has the same behavior as ReadFrom, except that it will not check that decode points 151 // are on the curve and in the correct subgroup. 152 func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { 153 return vk.readFrom(r, true) 154 } 155 156 func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { 157 var dec *curve.Decoder 158 if raw { 159 dec = curve.NewDecoder(r, curve.NoSubgroupChecks()) 160 } else { 161 dec = curve.NewDecoder(r) 162 } 163 164 var publicCommitted [][]uint64 165 var nbCommitments uint32 166 167 toDecode := []interface{}{ 168 // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2 169 &vk.G1.Alpha, 170 &vk.G1.Beta, 171 &vk.G2.Beta, 172 &vk.G2.Gamma, 173 &vk.G1.Delta, 174 &vk.G2.Delta, 175 // uint32(len(Kvk)),[Kvk]1 176 &vk.G1.K, 177 &publicCommitted, 178 &nbCommitments, 179 } 180 181 for _, v := range toDecode { 182 if err := dec.Decode(v); err != nil { 183 return dec.BytesRead(), err 184 } 185 } 186 187 vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) 188 189 vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) 190 var n int64 191 for i := range vk.CommitmentKeys { 192 var ( 193 m int64 194 err error 195 ) 196 if raw { 197 m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) 198 } else { 199 m, err = vk.CommitmentKeys[i].ReadFrom(r) 200 } 201 n += m 202 if err != nil { 203 return n + dec.BytesRead(), err 204 } 205 } 206 207 // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 208 if err := vk.Precompute(); err != nil { 209 return n + dec.BytesRead(), err 210 } 211 212 return n + dec.BytesRead(), nil 213 } 214 215 216 217 // WriteTo writes binary encoding of the key elements to writer 218 // points are compressed 219 // use WriteRawTo(...) to encode the key without point compression 220 func (pk *ProvingKey) WriteTo(w io.Writer) (n int64, err error) { 221 return pk.writeTo(w, false) 222 } 223 224 225 // WriteRawTo writes binary encoding of the key elements to writer 226 // points are not compressed 227 // use WriteTo(...) to encode the key with point compression 228 func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) { 229 return pk.writeTo(w, true) 230 } 231 232 func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) { 233 n, err := pk.Domain.WriteTo(w) 234 if err != nil { 235 return n, err 236 } 237 238 var enc *curve.Encoder 239 if raw { 240 enc = curve.NewEncoder(w, curve.RawEncoding()) 241 } else { 242 enc = curve.NewEncoder(w) 243 } 244 nbWires := uint64(len(pk.InfinityA)) 245 246 toEncode := []interface{}{ 247 &pk.G1.Alpha, 248 &pk.G1.Beta, 249 &pk.G1.Delta, 250 pk.G1.A, 251 pk.G1.B, 252 pk.G1.Z, 253 pk.G1.K, 254 &pk.G2.Beta, 255 &pk.G2.Delta, 256 pk.G2.B, 257 nbWires, 258 pk.NbInfinityA, 259 pk.NbInfinityB, 260 pk.InfinityA, 261 pk.InfinityB, 262 uint32(len(pk.CommitmentKeys)), 263 } 264 265 for _, v := range toEncode { 266 if err := enc.Encode(v); err != nil { 267 return n + enc.BytesWritten(), err 268 } 269 } 270 271 for i := range pk.CommitmentKeys { 272 var ( 273 n2 int64 274 err error 275 ) 276 if raw { 277 n2, err = pk.CommitmentKeys[i].WriteRawTo(w) 278 } else { 279 n2, err = pk.CommitmentKeys[i].WriteTo(w) 280 } 281 282 n += n2 283 if err != nil { 284 return n + enc.BytesWritten(), err 285 } 286 } 287 288 return n + enc.BytesWritten(), nil 289 290 } 291 292 // ReadFrom attempts to decode a ProvingKey from reader 293 // ProvingKey must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) 294 // note that we don't check that the points are on the curve or in the correct subgroup at this point 295 func (pk *ProvingKey) ReadFrom(r io.Reader) (int64, error) { 296 return pk.readFrom(r) 297 } 298 299 300 // UnsafeReadFrom behaves like ReadFrom excepts it doesn't check if the decoded points are on the curve 301 // or in the correct subgroup 302 func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { 303 return pk.readFrom(r, curve.NoSubgroupChecks()) 304 } 305 306 func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { 307 n, err := pk.Domain.ReadFrom(r) 308 if err != nil { 309 return n, err 310 } 311 312 dec := curve.NewDecoder(r, decOptions...) 313 314 var nbWires uint64 315 var nbCommitments uint32 316 317 toDecode := []interface{}{ 318 &pk.G1.Alpha, 319 &pk.G1.Beta, 320 &pk.G1.Delta, 321 &pk.G1.A, 322 &pk.G1.B, 323 &pk.G1.Z, 324 &pk.G1.K, 325 &pk.G2.Beta, 326 &pk.G2.Delta, 327 &pk.G2.B, 328 &nbWires, 329 &pk.NbInfinityA, 330 &pk.NbInfinityB, 331 } 332 333 for _, v := range toDecode { 334 if err := dec.Decode(v); err != nil { 335 return n + dec.BytesRead(), err 336 } 337 } 338 pk.InfinityA = make([]bool, nbWires) 339 pk.InfinityB = make([]bool, nbWires) 340 341 if err := dec.Decode(&pk.InfinityA); err != nil { 342 return n + dec.BytesRead(), err 343 } 344 if err := dec.Decode(&pk.InfinityB); err != nil { 345 return n + dec.BytesRead(), err 346 } 347 if err := dec.Decode(&nbCommitments); err != nil { 348 return n + dec.BytesRead(), err 349 } 350 351 pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) 352 for i := range pk.CommitmentKeys { 353 n2, err := pk.CommitmentKeys[i].ReadFrom(r) 354 n += n2 355 if err != nil { 356 return n, err 357 } 358 } 359 360 return n + dec.BytesRead(), nil 361 } 362 363 364 // WriteDump behaves like WriteRawTo, excepts, the slices of points are "dumped" using gnark-crypto/utils/unsafe 365 // Output is compatible with ReadDump, with the caveat that, not only the points are not checked for 366 // correctness, but the raw bytes are platform dependent (endianness, etc.) 367 func (pk *ProvingKey) WriteDump(w io.Writer) error { 368 // it behaves like WriteRawTo, excepts, the slices of points are "dumped" using gnark-crypto/utils/unsafe 369 370 // start by writing an unsafe marker to fail early. 371 if err := unsafe.WriteMarker(w); err != nil { 372 return err 373 } 374 375 if _, err := pk.Domain.WriteTo(w); err != nil { 376 return err 377 } 378 379 enc := curve.NewEncoder(w, curve.RawEncoding()) 380 nbWires := uint64(len(pk.InfinityA)) 381 382 toEncode := []interface{}{ 383 &pk.G1.Alpha, 384 &pk.G1.Beta, 385 &pk.G1.Delta, 386 // pk.G1.A, 387 // pk.G1.B, 388 // pk.G1.Z, 389 // pk.G1.K, 390 &pk.G2.Beta, 391 &pk.G2.Delta, 392 // pk.G2.B, 393 nbWires, 394 pk.NbInfinityA, 395 pk.NbInfinityB, 396 pk.InfinityA, 397 pk.InfinityB, 398 uint32(len(pk.CommitmentKeys)), 399 } 400 401 for _, v := range toEncode { 402 if err := enc.Encode(v); err != nil { 403 return err 404 } 405 } 406 407 // dump slices of points 408 if err := unsafe.WriteSlice(w, pk.G1.A); err != nil { 409 return err 410 } 411 if err := unsafe.WriteSlice(w, pk.G1.B); err != nil { 412 return err 413 } 414 if err := unsafe.WriteSlice(w, pk.G1.Z); err != nil { 415 return err 416 } 417 if err := unsafe.WriteSlice(w, pk.G1.K); err != nil { 418 return err 419 } 420 if err := unsafe.WriteSlice(w, pk.G2.B); err != nil { 421 return err 422 } 423 424 for i := range pk.CommitmentKeys { 425 if err := unsafe.WriteSlice(w, pk.CommitmentKeys[i].Basis); err != nil { 426 return err 427 } 428 if err := unsafe.WriteSlice(w, pk.CommitmentKeys[i].BasisExpSigma); err != nil { 429 return err 430 } 431 } 432 433 return nil 434 } 435 436 // ReadDump reads a ProvingKey from a dump written by WriteDump. 437 // This is platform dependent and very unsafe (no checks, no endianness translation, etc.) 438 func (pk *ProvingKey) ReadDump(r io.Reader) error { 439 // read the marker to fail early in case of malformed input 440 if err := unsafe.ReadMarker(r); err != nil { 441 return err 442 } 443 444 if _, err := pk.Domain.ReadFrom(r); err != nil { 445 return err 446 } 447 448 dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) 449 450 var nbWires uint64 451 var nbCommitments uint32 452 453 toDecode := []interface{}{ 454 &pk.G1.Alpha, 455 &pk.G1.Beta, 456 &pk.G1.Delta, 457 // &pk.G1.A, 458 // &pk.G1.B, 459 // &pk.G1.Z, 460 // &pk.G1.K, 461 &pk.G2.Beta, 462 &pk.G2.Delta, 463 // &pk.G2.B, 464 &nbWires, 465 &pk.NbInfinityA, 466 &pk.NbInfinityB, 467 } 468 469 for _, v := range toDecode { 470 if err := dec.Decode(v); err != nil { 471 return err 472 } 473 } 474 pk.InfinityA = make([]bool, nbWires) 475 pk.InfinityB = make([]bool, nbWires) 476 477 if err := dec.Decode(&pk.InfinityA); err != nil { 478 return err 479 } 480 if err := dec.Decode(&pk.InfinityB); err != nil { 481 return err 482 } 483 if err := dec.Decode(&nbCommitments); err != nil { 484 return err 485 } 486 487 // read slices of points 488 var err error 489 pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) 490 if err != nil { 491 return err 492 } 493 pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) 494 if err != nil { 495 return err 496 } 497 pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) 498 if err != nil { 499 return err 500 } 501 pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) 502 if err != nil { 503 return err 504 } 505 pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) 506 if err != nil { 507 return err 508 } 509 510 pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) 511 for i := range pk.CommitmentKeys { 512 pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) 513 if err != nil { 514 return err 515 } 516 pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) 517 if err != nil { 518 return err 519 } 520 } 521 522 return nil 523 524 }