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 }