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  }