github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/groth16.setup.go.tmpl (about) 1 import ( 2 "errors" 3 {{- template "import_fr" . }} 4 {{- template "import_curve" . }} 5 {{- template "import_backend_cs" . }} 6 {{- template "import_fft" . }} 7 {{- template "import_pedersen" .}} 8 "github.com/consensys/gnark/backend/groth16/internal" 9 "github.com/consensys/gnark-crypto/ecc" 10 "github.com/consensys/gnark/constraint" 11 "math/big" 12 "math/bits" 13 ) 14 15 // ProvingKey is used by a Groth16 prover to encode a proof of a statement 16 // Notation follows Figure 4. in DIZK paper https://eprint.iacr.org/2018/691.pdf 17 type ProvingKey struct { 18 // domain 19 Domain fft.Domain 20 21 // [α]₁, [β]₁, [δ]₁ 22 // [A(t)]₁, [B(t)]₁, [Kpk(t)]₁, [Z(t)]₁ 23 G1 struct { 24 Alpha, Beta, Delta curve.G1Affine 25 A, B, Z []curve.G1Affine 26 K []curve.G1Affine // the indexes correspond to the private wires 27 } 28 29 // [β]₂, [δ]₂, [B(t)]₂ 30 G2 struct { 31 Beta, Delta curve.G2Affine 32 B []curve.G2Affine 33 } 34 35 // if InfinityA[i] == true, the point G1.A[i] == infinity 36 InfinityA, InfinityB []bool 37 NbInfinityA, NbInfinityB uint64 38 39 CommitmentKeys []pedersen.ProvingKey 40 } 41 42 // VerifyingKey is used by a Groth16 verifier to verify the validity of a proof and a statement 43 // Notation follows Figure 4. in DIZK paper https://eprint.iacr.org/2018/691.pdf 44 type VerifyingKey struct { 45 // [α]₁, [Kvk]₁ 46 G1 struct { 47 Alpha curve.G1Affine 48 Beta, Delta curve.G1Affine // unused, here for compatibility purposes 49 K []curve.G1Affine // The indexes correspond to the public wires 50 } 51 52 // [β]₂, [δ]₂, [γ]₂, 53 // -[δ]₂, -[γ]₂: see proof.Verify() for more details 54 G2 struct { 55 Beta, Delta, Gamma curve.G2Affine 56 deltaNeg, gammaNeg curve.G2Affine // not serialized 57 } 58 59 // e(α, β) 60 e curve.GT // not serialized 61 62 CommitmentKeys []pedersen.VerifyingKey 63 PublicAndCommitmentCommitted [][]int // indexes of public/commitment committed variables 64 } 65 66 // Setup constructs the SRS 67 func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { 68 /* 69 Setup 70 ----- 71 To build the verifying keys: 72 - compile the r1cs system -> the number of gates is len(GateOrdering)+len(PureStructuralConstraints)+len(InpureStructuralConstraints) 73 - loop through the ordered computational constraints (=gate in r1cs system structure), eValuate A(X), B(X), C(X) with simple formula (the gate number is the current iterator) 74 - loop through the inpure structural constraints, eValuate A(X), B(X), C(X) with simple formula, the gate number is len(gateOrdering)+ current iterator 75 - loop through the pure structural constraints, eValuate A(X), B(X), C(X) with simple formula, the gate number is len(gateOrdering)+len(InpureStructuralConstraints)+current iterator 76 */ 77 78 // get R1CS nb constraints, wires and public/private inputs 79 nbWires := r1cs.NbInternalVariables + r1cs.GetNbPublicVariables() + r1cs.GetNbSecretVariables() 80 81 commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) 82 commitmentWires := commitmentInfo.CommitmentIndexes() 83 privateCommitted := commitmentInfo.GetPrivateCommitted() 84 nbPrivateCommittedWires := internal.NbElements(privateCommitted) 85 86 // a commitment is itself defined by a hint so the prover considers it private 87 // but the verifier will need to inject the value itself so on the groth16 88 // level it must be considered public 89 nbPublicWires := r1cs.GetNbPublicVariables() + len(commitmentInfo) 90 nbPrivateWires := r1cs.GetNbSecretVariables() + r1cs.NbInternalVariables - nbPrivateCommittedWires - len(commitmentInfo) 91 92 // Setting group for fft 93 domain := fft.NewDomain(uint64(r1cs.GetNbConstraints())) 94 95 // samples toxic waste 96 toxicWaste, err := sampleToxicWaste() 97 if err != nil { 98 return err 99 } 100 101 // Setup coeffs to compute pk.G1.A, pk.G1.B, pk.G1.K 102 A, B, C := setupABC(r1cs, domain, toxicWaste) 103 104 // To fill in the Proving and Verifying keys, we need to perform a lot of ecc scalar multiplication (with generator) 105 // and convert the resulting points to affine 106 // this is done using the curve.BatchScalarMultiplicationGX API, which takes as input the base point 107 // (in our case the generator) and the list of scalars, and outputs a list of points (len(points) == len(scalars)) 108 // to use this batch call, we need to order our scalars in the same slice 109 // we have 1 batch call for G1 and 1 batch call for G1 110 // scalars are fr.Element in non montgomery form 111 _, _, g1, g2 := curve.Generators() 112 113 // --------------------------------------------------------------------------------------------- 114 // G1 scalars 115 116 // the G1 scalars are ordered (arbitrary) as follows: 117 // 118 // [[α], [β], [δ], [A(i)], [B(i)], [pk.K(i)], [Z(i)], [vk.K(i)]] 119 // len(A) == len(B) == nbWires 120 // len(pk.K) == nbPrivateWires 121 // len(vk.K) == nbPublicWires 122 // len(Z) == domain.Cardinality 123 124 // compute scalars for pkK, vkK and ckK 125 pkK := make([]fr.Element, nbPrivateWires) 126 vkK := make([]fr.Element, nbPublicWires) 127 ckK := make([][]fr.Element, len(commitmentInfo)) 128 for i := range commitmentInfo { 129 ckK[i] = make([]fr.Element, len(privateCommitted[i])) 130 } 131 132 var t0, t1 fr.Element 133 134 computeK := func(i int, coeff *fr.Element) { // TODO: Inline again 135 t1.Mul(&A[i], &toxicWaste.beta) 136 t0.Mul(&B[i], &toxicWaste.alpha) 137 t1.Add(&t1, &t0). 138 Add(&t1, &C[i]). 139 Mul(&t1, coeff) 140 } 141 vI := 0 // number of public wires seen so far 142 cI := make([]int, len(commitmentInfo)) // number of private committed wires seen so far for each commitment 143 nbPrivateCommittedSeen := 0 // = ∑ᵢ cI[i] 144 nbCommitmentsSeen := 0 145 146 for i := range A { 147 commitment := -1 // index of the commitment that commits to this variable as a private or commitment value 148 var isCommitment, isPublic bool 149 if isPublic = i < r1cs.GetNbPublicVariables(); !isPublic { 150 if nbCommitmentsSeen < len(commitmentWires) && commitmentWires[nbCommitmentsSeen] == i { 151 isCommitment = true 152 nbCommitmentsSeen++ 153 } 154 155 for j := range commitmentInfo { // does commitment j commit to i? 156 if cI[j] < len(privateCommitted[j]) && privateCommitted[j][cI[j]] == i { 157 commitment = j 158 break // frontend guarantees that no private variable is committed to more than once 159 } 160 } 161 } 162 163 if isPublic || commitment != -1 || isCommitment { 164 computeK(i, &toxicWaste.gammaInv) 165 166 if isPublic || isCommitment { 167 vkK[vI] = t1 168 vI++ 169 } else { // committed and private 170 ckK[commitment][cI[commitment]] = t1 171 cI[commitment]++ 172 nbPrivateCommittedSeen++ 173 } 174 } else { 175 computeK(i, &toxicWaste.deltaInv) 176 pkK[i-vI-nbPrivateCommittedSeen] = t1 // vI = nbPublicSeen + nbCommitmentsSeen 177 } 178 } 179 180 // Z part of the proving key (scalars) 181 Z := make([]fr.Element, domain.Cardinality) 182 one := fr.One() 183 var zdt fr.Element 184 185 zdt.Exp(toxicWaste.t, new(big.Int).SetUint64(domain.Cardinality)). 186 Sub(&zdt, &one). 187 Mul(&zdt, &toxicWaste.deltaInv) // sets Zdt to Zdt/delta 188 189 for i := 0; i < int(domain.Cardinality); i++ { 190 Z[i] = zdt 191 zdt.Mul(&zdt, &toxicWaste.t) 192 } 193 194 // mark points at infinity and filter them 195 pk.InfinityA = make([]bool, len(A)) 196 pk.InfinityB = make([]bool, len(B)) 197 198 n := 0 199 for i, e := range A { 200 if e.IsZero() { 201 pk.InfinityA[i] = true 202 continue 203 } 204 A[n] = A[i] 205 n++ 206 } 207 A = A[:n] 208 pk.NbInfinityA = uint64(nbWires - n) 209 n = 0 210 for i, e := range B { 211 if e.IsZero() { 212 pk.InfinityB[i] = true 213 continue 214 } 215 B[n] = B[i] 216 n++ 217 } 218 B = B[:n] 219 pk.NbInfinityB = uint64(nbWires - n) 220 221 // compute our batch scalar multiplication with g1 elements 222 g1Scalars := make([]fr.Element, 0, (nbWires*3)+int(domain.Cardinality)+3) 223 g1Scalars = append(g1Scalars, toxicWaste.alpha, toxicWaste.beta, toxicWaste.delta) 224 g1Scalars = append(g1Scalars, A...) 225 g1Scalars = append(g1Scalars, B...) 226 g1Scalars = append(g1Scalars, Z...) 227 g1Scalars = append(g1Scalars, vkK...) 228 g1Scalars = append(g1Scalars, pkK...) 229 for i := range ckK { 230 g1Scalars = append(g1Scalars, ckK[i]...) 231 } 232 233 g1PointsAff := curve.BatchScalarMultiplicationG1(&g1, g1Scalars) 234 235 // sets pk: [α]₁, [β]₁, [δ]₁ 236 pk.G1.Alpha = g1PointsAff[0] 237 pk.G1.Beta = g1PointsAff[1] 238 pk.G1.Delta = g1PointsAff[2] 239 240 offset := 3 241 pk.G1.A = g1PointsAff[offset : offset+len(A)] 242 offset += len(A) 243 244 pk.G1.B = g1PointsAff[offset : offset+len(B)] 245 offset += len(B) 246 247 bitReverse(g1PointsAff[offset : offset+int(domain.Cardinality)]) 248 sizeZ := int(domain.Cardinality)-1 // deg(H)=deg(A*B-C/X^n-1)=(n-1)+(n-1)-n=n-2 249 pk.G1.Z = g1PointsAff[offset : offset+sizeZ] 250 251 offset += int(domain.Cardinality) 252 253 vk.G1.K = g1PointsAff[offset : offset+nbPublicWires] 254 offset += nbPublicWires 255 256 pk.G1.K = g1PointsAff[offset : offset+nbPrivateWires] 257 offset += nbPrivateWires 258 259 // --------------------------------------------------------------------------------------------- 260 // Commitment setup 261 262 commitmentBases := make([][]curve.G1Affine, len(commitmentInfo)) 263 for i := range commitmentBases { 264 size := len(ckK[i]) 265 commitmentBases[i] = g1PointsAff[offset : offset+size] 266 offset += size 267 } 268 if offset != len(g1PointsAff) { 269 return errors.New("didn't consume all G1 points") // TODO @Tabaie Remove this 270 } 271 272 cG2, err := curve.RandomOnG2() 273 if err != nil { 274 return err 275 } 276 pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) 277 vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) 278 for i := range commitmentBases { 279 comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) 280 if err != nil { 281 return err 282 } 283 pk.CommitmentKeys[i] = comPKey[0] 284 vk.CommitmentKeys[i] = comVKey 285 } 286 287 vk.PublicAndCommitmentCommitted = commitmentInfo.GetPublicAndCommitmentCommitted(commitmentWires, r1cs.GetNbPublicVariables()) 288 289 // --------------------------------------------------------------------------------------------- 290 // G2 scalars 291 292 // the G2 scalars are ordered as follow: 293 // 294 // [[B(i)], [β], [δ], [γ]] 295 // len(B) == nbWires 296 297 // compute our batch scalar multiplication with g2 elements 298 g2Scalars := append(B, toxicWaste.beta, toxicWaste.delta, toxicWaste.gamma) 299 300 g2PointsAff := curve.BatchScalarMultiplicationG2(&g2, g2Scalars) 301 302 pk.G2.B = g2PointsAff[:len(B)] 303 304 // sets pk: [β]₂, [δ]₂ 305 pk.G2.Beta = g2PointsAff[len(B)+0] 306 pk.G2.Delta = g2PointsAff[len(B)+1] 307 308 // sets vk: [δ]₂, [γ]₂ 309 vk.G2.Delta = g2PointsAff[len(B)+1] 310 vk.G2.Gamma = g2PointsAff[len(B)+2] 311 312 // --------------------------------------------------------------------------------------------- 313 // Pairing: vk.e 314 vk.G1.Alpha = pk.G1.Alpha 315 vk.G2.Beta = pk.G2.Beta 316 317 // unused, here for compatibility purposes 318 vk.G1.Beta = pk.G1.Beta 319 vk.G1.Delta = pk.G1.Delta 320 321 if err := vk.Precompute(); err != nil { 322 return err 323 } 324 325 // set domain 326 pk.Domain = *domain 327 328 return nil 329 } 330 331 // Precompute sets e, -[δ]₂, -[γ]₂ 332 // This is meant to be called internally during setup or deserialization. 333 func (vk *VerifyingKey) Precompute() error { 334 var err error 335 vk.e, err = curve.Pair([]curve.G1Affine{vk.G1.Alpha}, []curve.G2Affine{vk.G2.Beta}) 336 if err != nil { 337 return err 338 } 339 vk.G2.deltaNeg.Neg(&vk.G2.Delta) 340 vk.G2.gammaNeg.Neg(&vk.G2.Gamma) 341 return nil 342 } 343 344 func setupABC(r1cs *cs.R1CS, domain *fft.Domain, toxicWaste toxicWaste) (A []fr.Element, B []fr.Element, C []fr.Element) { 345 346 nbWires := r1cs.NbInternalVariables + r1cs.GetNbPublicVariables() + r1cs.GetNbSecretVariables() 347 348 A = make([]fr.Element, nbWires) 349 B = make([]fr.Element, nbWires) 350 C = make([]fr.Element, nbWires) 351 352 one := fr.One() 353 354 // first we compute [t-w^i] and its inverse 355 var w fr.Element 356 w.Set(&domain.Generator) 357 wi := fr.One() 358 t := make([]fr.Element, r1cs.GetNbConstraints()+1) 359 for i := 0; i < len(t); i++ { 360 t[i].Sub(&toxicWaste.t, &wi) 361 wi.Mul(&wi, &w) // TODO this is already pre computed in fft.Domain 362 } 363 tInv := fr.BatchInvert(t) 364 365 // evaluation of the i-th lagrange polynomial at t 366 var L fr.Element 367 368 // L = 1/n*(t^n-1)/(t-1), Li+1 = w*Li*(t-w^i)/(t-w^(i+1)) 369 370 // Setting L0 371 L.Exp(toxicWaste.t, new(big.Int).SetUint64(uint64(domain.Cardinality))). 372 Sub(&L, &one) 373 L.Mul(&L, &tInv[0]). 374 Mul(&L, &domain.CardinalityInv) 375 376 accumulate := func(res *fr.Element, t constraint.Term, value *fr.Element) { 377 cID := t.CoeffID() 378 switch cID { 379 case constraint.CoeffIdZero: 380 return 381 case constraint.CoeffIdOne: 382 res.Add(res, value) 383 case constraint.CoeffIdMinusOne: 384 res.Sub(res, value) 385 case constraint.CoeffIdTwo: 386 var buffer fr.Element 387 buffer.Double(value) 388 res.Add(res, &buffer) 389 default: 390 var buffer fr.Element 391 buffer.Mul(&r1cs.Coefficients[cID], value) 392 res.Add(res, &buffer) 393 } 394 } 395 396 // each constraint is in the form 397 // L * R == O 398 // L, R and O being linear expressions 399 // for each term appearing in the linear expression, 400 // we compute term.Coefficient * L, and cumulate it in 401 // A, B or C at the index of the variable 402 403 j := 0 404 it := r1cs.GetR1CIterator() 405 for c := it.Next(); c!=nil; c = it.Next() { 406 for _, t := range c.L { 407 accumulate(&A[t.WireID()], t, &L) 408 } 409 for _, t := range c.R { 410 accumulate(&B[t.WireID()], t, &L) 411 } 412 for _, t := range c.O { 413 accumulate(&C[t.WireID()], t, &L) 414 } 415 416 // Li+1 = w*Li*(t-w^i)/(t-w^(i+1)) 417 L.Mul(&L, &w) 418 L.Mul(&L, &t[j]) 419 L.Mul(&L, &tInv[j+1]) 420 421 j++ 422 } 423 424 return 425 426 } 427 428 // toxicWaste toxic waste 429 type toxicWaste struct { 430 431 // Montgomery form of params 432 t, alpha, beta, gamma, delta fr.Element 433 gammaInv, deltaInv fr.Element 434 } 435 436 func sampleToxicWaste() (toxicWaste, error) { 437 438 res := toxicWaste{} 439 440 for res.t.IsZero() { 441 if _, err := res.t.SetRandom(); err != nil { 442 return res, err 443 } 444 } 445 for res.alpha.IsZero() { 446 if _, err := res.alpha.SetRandom(); err != nil { 447 return res, err 448 } 449 } 450 for res.beta.IsZero() { 451 if _, err := res.beta.SetRandom(); err != nil { 452 return res, err 453 } 454 } 455 for res.gamma.IsZero() { 456 if _, err := res.gamma.SetRandom(); err != nil { 457 return res, err 458 } 459 } 460 for res.delta.IsZero() { 461 if _, err := res.delta.SetRandom(); err != nil { 462 return res, err 463 } 464 } 465 466 res.gammaInv.Inverse(&res.gamma) 467 res.deltaInv.Inverse(&res.delta) 468 469 return res, nil 470 } 471 472 // DummySetup fills a random ProvingKey 473 // used for test or benchmarking purposes 474 func DummySetup(r1cs *cs.R1CS, pk *ProvingKey) error { 475 // get R1CS nb constraints, wires and public/private inputs 476 nbWires := r1cs.NbInternalVariables + r1cs.GetNbPublicVariables() + r1cs.GetNbSecretVariables() 477 nbConstraints := r1cs.GetNbConstraints() 478 commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) 479 privateCommitted := commitmentInfo.GetPrivateCommitted() 480 nbPrivateWires := r1cs.GetNbSecretVariables() + r1cs.NbInternalVariables - internal.NbElements(privateCommitted) - len(commitmentInfo) 481 482 // Setting group for fft 483 domain := fft.NewDomain(uint64(nbConstraints)) 484 485 // count number of infinity points we would have had we a normal setup 486 // in pk.G1.A, pk.G1.B, and pk.G2.B 487 nbZeroesA, nbZeroesB := dummyInfinityCount(r1cs) 488 489 // initialize proving key 490 pk.G1.A = make([]curve.G1Affine, nbWires-nbZeroesA) 491 pk.G1.B = make([]curve.G1Affine, nbWires-nbZeroesB) 492 pk.G1.K = make([]curve.G1Affine, nbPrivateWires) 493 pk.G1.Z = make([]curve.G1Affine, domain.Cardinality-1) 494 pk.G2.B = make([]curve.G2Affine, nbWires-nbZeroesB) 495 496 // set infinity markers 497 pk.InfinityA = make([]bool, nbWires) 498 pk.InfinityB = make([]bool, nbWires) 499 pk.NbInfinityA = uint64(nbZeroesA) 500 pk.NbInfinityB = uint64(nbZeroesB) 501 for i := 0; i < nbZeroesA; i++ { 502 pk.InfinityA[i] = true 503 } 504 for i := 0; i < nbZeroesB; i++ { 505 pk.InfinityB[i] = true 506 } 507 508 // samples toxic waste 509 toxicWaste, err := sampleToxicWaste() 510 if err != nil { 511 return err 512 } 513 514 var r1Jac curve.G1Jac 515 var r1Aff curve.G1Affine 516 var b big.Int 517 g1, g2, _, _ := curve.Generators() 518 r1Jac.ScalarMultiplication(&g1, toxicWaste.alpha.BigInt(&b)) 519 r1Aff.FromJacobian(&r1Jac) 520 var r2Jac curve.G2Jac 521 var r2Aff curve.G2Affine 522 r2Jac.ScalarMultiplication(&g2, &b) 523 r2Aff.FromJacobian(&r2Jac) 524 for i := 0; i < len(pk.G1.A); i++ { 525 pk.G1.A[i] = r1Aff 526 } 527 for i := 0; i < len(pk.G1.B); i++ { 528 pk.G1.B[i] = r1Aff 529 } 530 for i := 0; i < len(pk.G2.B); i++ { 531 pk.G2.B[i] = r2Aff 532 } 533 for i := 0; i < len(pk.G1.Z); i++ { 534 pk.G1.Z[i] = r1Aff 535 } 536 for i := 0; i < len(pk.G1.K); i++ { 537 pk.G1.K[i] = r1Aff 538 } 539 pk.G1.Alpha = r1Aff 540 pk.G1.Beta = r1Aff 541 pk.G1.Delta = r1Aff 542 pk.G2.Beta = r2Aff 543 pk.G2.Delta = r2Aff 544 545 pk.Domain = *domain 546 547 // --------------------------------------------------------------------------------------------- 548 // Commitment setup 549 commitmentBases := make([][]curve.G1Affine, len(commitmentInfo)) 550 for i := range commitmentBases { 551 size := len(privateCommitted[i]) 552 commitmentBases[i] = make([]curve.G1Affine, size) 553 for j := range commitmentBases[i] { 554 commitmentBases[i][j] = r1Aff 555 } 556 } 557 558 pk.CommitmentKeys,_, err = pedersen.Setup(commitmentBases) 559 if err != nil { 560 return err 561 } 562 563 return nil 564 } 565 566 // dummyInfinityCount helps us simulate the number of infinity points we have with the given R1CS 567 // in A and B as it directly impacts prover performance 568 func dummyInfinityCount(r1cs *cs.R1CS) (nbZeroesA, nbZeroesB int) { 569 570 nbWires := r1cs.NbInternalVariables + r1cs.GetNbPublicVariables() + r1cs.GetNbSecretVariables() 571 572 A := make([]bool, nbWires) 573 B := make([]bool, nbWires) 574 575 it := r1cs.GetR1CIterator() 576 for c := it.Next(); c!=nil; c = it.Next() { 577 for _, t := range c.L { 578 A[t.WireID()] = true 579 } 580 for _, t := range c.R { 581 B[t.WireID()] = true 582 } 583 } 584 585 586 for i := 0; i < nbWires; i++ { 587 if !A[i] { 588 nbZeroesA++ 589 } 590 if !B[i] { 591 nbZeroesB++ 592 } 593 } 594 return 595 596 } 597 598 // IsDifferent returns true if provided vk is different than self 599 // this is used by groth16.Assert to ensure random sampling 600 func (vk *VerifyingKey) IsDifferent(_other interface{}) bool { 601 vk2 := _other.(*VerifyingKey) 602 for i := 0; i < len(vk.G1.K); i++ { 603 if !vk.G1.K[i].IsInfinity() { 604 if vk.G1.K[i].Equal(&vk2.G1.K[i]) { 605 return false 606 } 607 } 608 } 609 610 return true 611 } 612 613 // IsDifferent returns true if provided pk is different than self 614 // this is used by groth16.Assert to ensure random sampling 615 func (pk *ProvingKey) IsDifferent(_other interface{}) bool { 616 pk2 := _other.(*ProvingKey) 617 618 if pk.G1.Alpha.Equal(&pk2.G1.Alpha) || 619 pk.G1.Beta.Equal(&pk2.G1.Beta) || 620 pk.G1.Delta.Equal(&pk2.G1.Delta) { 621 return false 622 } 623 624 for i := 0; i < len(pk.G1.K); i++ { 625 if !pk.G1.K[i].IsInfinity() { 626 if pk.G1.K[i].Equal(&pk2.G1.K[i]) { 627 return false 628 } 629 } 630 } 631 632 return true 633 } 634 635 // CurveID returns the curveID 636 func (pk *ProvingKey) CurveID() ecc.ID { 637 return curve.ID 638 } 639 640 // CurveID returns the curveID 641 func (vk *VerifyingKey) CurveID() ecc.ID { 642 return curve.ID 643 } 644 645 // NbPublicWitness returns the number of elements in the expected public witness 646 func (vk *VerifyingKey) NbPublicWitness() int { 647 return (len(vk.G1.K) - 1) 648 } 649 650 // NbG1 returns the number of G1 elements in the VerifyingKey 651 func (vk *VerifyingKey) NbG1() int { 652 return 3 + len(vk.G1.K) 653 } 654 655 // NbG2 returns the number of G2 elements in the VerifyingKey 656 func (vk *VerifyingKey) NbG2() int { 657 return 3 658 } 659 660 // NbG1 returns the number of G1 elements in the ProvingKey 661 func (pk *ProvingKey) NbG1() int { 662 return 3 + len(pk.G1.A) + len(pk.G1.B) + len(pk.G1.Z) + len(pk.G1.K) 663 } 664 665 // NbG2 returns the number of G2 elements in the ProvingKey 666 func (pk *ProvingKey) NbG2() int { 667 return 2 + len(pk.G2.B) 668 } 669 670 // bitReverse permutation as in fft.BitReverse , but with []curve.G1Affine 671 func bitReverse(a []curve.G1Affine) { 672 n := uint(len(a)) 673 nn := uint(bits.UintSize - bits.TrailingZeros(n)) 674 675 for i := uint(0); i < n; i++ { 676 irev := bits.Reverse(i) >> nn 677 if irev > i { 678 a[i], a[irev] = a[irev], a[i] 679 } 680 } 681 }