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