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  }