github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/utils.go.tmpl (about)

     1  import (
     2  	"bytes"
     3  	"math/big"
     4  	"math/bits"
     5  	"runtime"
     6  
     7  	"github.com/consensys/gnark-crypto/ecc"
     8  
     9  	{{- template "import_fr" . }}
    10  	{{- template "import_curve" . }}
    11  	"github.com/consensys/gnark/internal/utils"
    12  )
    13  
    14  type PublicKey struct {
    15  	SG  curve.G1Affine
    16  	SXG curve.G1Affine
    17  	XR  curve.G2Affine
    18  }
    19  
    20  func newPublicKey(x fr.Element, challenge []byte, dst byte) PublicKey {
    21  	var pk PublicKey
    22  	_, _, g1, _ := curve.Generators()
    23  
    24  	var s fr.Element
    25  	var sBi big.Int
    26  	s.SetRandom()
    27  	s.BigInt(&sBi)
    28  	pk.SG.ScalarMultiplication(&g1, &sBi)
    29  
    30  	// compute x*sG1
    31  	var xBi big.Int
    32  	x.BigInt(&xBi)
    33  	pk.SXG.ScalarMultiplication(&pk.SG, &xBi)
    34  
    35  	// generate R based on sG1, sxG1, challenge, and domain separation tag (tau, alpha or beta)
    36  	R := genR(pk.SG, pk.SXG, challenge, dst)
    37  
    38  	// compute x*spG2
    39  	pk.XR.ScalarMultiplication(&R, &xBi)
    40  	return pk
    41  }
    42  
    43  func bitReverse[T any](a []T) {
    44  	n := uint64(len(a))
    45  	nn := uint64(64 - bits.TrailingZeros64(n))
    46  
    47  	for i := uint64(0); i < n; i++ {
    48  		irev := bits.Reverse64(i) >> nn
    49  		if irev > i {
    50  			a[i], a[irev] = a[irev], a[i]
    51  		}
    52  	}
    53  }
    54  
    55  // Returns [1, a, a², ..., aⁿ⁻¹ ] in Montgomery form
    56  func powers(a fr.Element, n int) []fr.Element {
    57  	result := make([]fr.Element, n)
    58  	result[0] = fr.NewElement(1)
    59  	for i := 1; i < n; i++ {
    60  		result[i].Mul(&result[i-1], &a)
    61  	}
    62  	return result
    63  }
    64  
    65  // Returns [aᵢAᵢ, ...] in G1
    66  func scaleG1InPlace(A []curve.G1Affine, a []fr.Element) {
    67  	utils.Parallelize(len(A), func(start, end int) {
    68  		var tmp big.Int
    69  		for i := start; i < end; i++ {
    70  			a[i].BigInt(&tmp)
    71  			A[i].ScalarMultiplication(&A[i], &tmp)
    72  		}
    73  	})
    74  }
    75  
    76  // Returns [aᵢAᵢ, ...] in G2
    77  func scaleG2InPlace(A []curve.G2Affine, a []fr.Element) {
    78  	utils.Parallelize(len(A), func(start, end int) {
    79  		var tmp big.Int
    80  		for i := start; i < end; i++ {
    81  			a[i].BigInt(&tmp)
    82  			A[i].ScalarMultiplication(&A[i], &tmp)
    83  		}
    84  	})
    85  }
    86  
    87  // Check e(a₁, a₂) = e(b₁, b₂)
    88  func sameRatio(a1, b1 curve.G1Affine, a2, b2 curve.G2Affine) bool {
    89  	if !a1.IsInSubGroup() || !b1.IsInSubGroup() || !a2.IsInSubGroup() || !b2.IsInSubGroup() {
    90  		panic("invalid point not in subgroup")
    91  	}
    92  	var na2 curve.G2Affine
    93  	na2.Neg(&a2)
    94  	res, err := curve.PairingCheck(
    95  		[]curve.G1Affine{a1, b1},
    96  		[]curve.G2Affine{na2, b2})
    97  	if err != nil {
    98  		panic(err)
    99  	}
   100  	return res
   101  }
   102  
   103  // returns a = ∑ rᵢAᵢ, b = ∑ rᵢBᵢ
   104  func merge(A, B []curve.G1Affine) (a, b curve.G1Affine) {
   105  	nc := runtime.NumCPU()
   106  	r := make([]fr.Element, len(A))
   107  	for i := 0; i < len(A); i++ {
   108  		r[i].SetRandom()
   109  	}
   110  	a.MultiExp(A, r, ecc.MultiExpConfig{NbTasks: nc / 2})
   111  	b.MultiExp(B, r, ecc.MultiExpConfig{NbTasks: nc / 2})
   112  	return
   113  }
   114  
   115  // L1 = ∑ rᵢAᵢ, L2 = ∑ rᵢAᵢ₊₁ in G1
   116  func linearCombinationG1(A []curve.G1Affine) (L1, L2 curve.G1Affine) {
   117  	nc := runtime.NumCPU()
   118  	n := len(A)
   119  	r := make([]fr.Element, n-1)
   120  	for i := 0; i < n-1; i++ {
   121  		r[i].SetRandom()
   122  	}
   123  	L1.MultiExp(A[:n-1], r, ecc.MultiExpConfig{NbTasks: nc / 2})
   124  	L2.MultiExp(A[1:], r, ecc.MultiExpConfig{NbTasks: nc / 2})
   125  	return
   126  }
   127  
   128  // L1 = ∑ rᵢAᵢ, L2 = ∑ rᵢAᵢ₊₁ in G2
   129  func linearCombinationG2(A []curve.G2Affine) (L1, L2 curve.G2Affine) {
   130  	nc := runtime.NumCPU()
   131  	n := len(A)
   132  	r := make([]fr.Element, n-1)
   133  	for i := 0; i < n-1; i++ {
   134  		r[i].SetRandom()
   135  	}
   136  	L1.MultiExp(A[:n-1], r, ecc.MultiExpConfig{NbTasks: nc / 2})
   137  	L2.MultiExp(A[1:], r, ecc.MultiExpConfig{NbTasks: nc / 2})
   138  	return
   139  }
   140  
   141  // Generate R in G₂ as Hash(gˢ, gˢˣ, challenge, dst)
   142  func genR(sG1, sxG1 curve.G1Affine, challenge []byte, dst byte) curve.G2Affine {
   143  	var buf bytes.Buffer
   144  	buf.Grow(len(challenge) + curve.SizeOfG1AffineUncompressed*2)
   145  	buf.Write(sG1.Marshal())
   146  	buf.Write(sxG1.Marshal())
   147  	buf.Write(challenge)
   148  	spG2, err := curve.HashToG2(buf.Bytes(), []byte{dst})
   149  	if err != nil {
   150  		panic(err)
   151  	}
   152  	return spG2
   153  }