github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/lagrange.go.tmpl (about) 1 import ( 2 "math/big" 3 "math/bits" 4 "runtime" 5 6 "github.com/consensys/gnark-crypto/ecc" 7 8 {{- template "import_fr" . }} 9 {{- template "import_curve" . }} 10 {{- template "import_fft" . }} 11 "github.com/consensys/gnark/internal/utils" 12 ) 13 14 15 // TODO use gnark-crypto for this op 16 func lagrangeCoeffsG1(powers []curve.G1Affine, size int) []curve.G1Affine { 17 coeffs := make([]curve.G1Affine, size) 18 copy(coeffs, powers[:size]) 19 domain := fft.NewDomain(uint64(size)) 20 numCPU := uint64(runtime.NumCPU()) 21 maxSplits := bits.TrailingZeros64(ecc.NextPowerOfTwo(numCPU)) 22 23 twiddlesInv, _ := domain.TwiddlesInv() 24 difFFTG1(coeffs, twiddlesInv, 0, maxSplits, nil) 25 bitReverse(coeffs) 26 27 var invBigint big.Int 28 domain.CardinalityInv.BigInt(&invBigint) 29 30 utils.Parallelize(size, func(start, end int) { 31 for i := start; i < end; i++ { 32 coeffs[i].ScalarMultiplication(&coeffs[i], &invBigint) 33 } 34 }) 35 return coeffs 36 } 37 38 // TODO use gnark-crypto for this op 39 func lagrangeCoeffsG2(powers []curve.G2Affine, size int) []curve.G2Affine { 40 coeffs := make([]curve.G2Affine, size) 41 copy(coeffs, powers[:size]) 42 domain := fft.NewDomain(uint64(size)) 43 numCPU := uint64(runtime.NumCPU()) 44 maxSplits := bits.TrailingZeros64(ecc.NextPowerOfTwo(numCPU)) 45 46 twiddlesInv, _ := domain.TwiddlesInv() 47 difFFTG2(coeffs, twiddlesInv, 0, maxSplits, nil) 48 bitReverse(coeffs) 49 50 var invBigint big.Int 51 domain.CardinalityInv.BigInt(&invBigint) 52 53 utils.Parallelize(size, func(start, end int) { 54 for i := start; i < end; i++ { 55 coeffs[i].ScalarMultiplication(&coeffs[i], &invBigint) 56 } 57 }) 58 return coeffs 59 } 60 61 func butterflyG1(a *curve.G1Affine, b *curve.G1Affine) { 62 t := *a 63 a.Add(a, b) 64 b.Sub(&t, b) 65 } 66 67 func butterflyG2(a *curve.G2Affine, b *curve.G2Affine) { 68 t := *a 69 a.Add(a, b) 70 b.Sub(&t, b) 71 } 72 73 // kerDIF8 is a kernel that process a FFT of size 8 74 func kerDIF8G1(a []curve.G1Affine, twiddles [][]fr.Element, stage int) { 75 butterflyG1(&a[0], &a[4]) 76 butterflyG1(&a[1], &a[5]) 77 butterflyG1(&a[2], &a[6]) 78 butterflyG1(&a[3], &a[7]) 79 80 var twiddle big.Int 81 twiddles[stage+0][1].BigInt(&twiddle) 82 a[5].ScalarMultiplication(&a[5], &twiddle) 83 twiddles[stage+0][2].BigInt(&twiddle) 84 a[6].ScalarMultiplication(&a[6], &twiddle) 85 twiddles[stage+0][3].BigInt(&twiddle) 86 a[7].ScalarMultiplication(&a[7], &twiddle) 87 butterflyG1(&a[0], &a[2]) 88 butterflyG1(&a[1], &a[3]) 89 butterflyG1(&a[4], &a[6]) 90 butterflyG1(&a[5], &a[7]) 91 twiddles[stage+1][1].BigInt(&twiddle) 92 a[3].ScalarMultiplication(&a[3], &twiddle) 93 twiddles[stage+1][1].BigInt(&twiddle) 94 a[7].ScalarMultiplication(&a[7], &twiddle) 95 butterflyG1(&a[0], &a[1]) 96 butterflyG1(&a[2], &a[3]) 97 butterflyG1(&a[4], &a[5]) 98 butterflyG1(&a[6], &a[7]) 99 } 100 101 // kerDIF8 is a kernel that process a FFT of size 8 102 func kerDIF8G2(a []curve.G2Affine, twiddles [][]fr.Element, stage int) { 103 butterflyG2(&a[0], &a[4]) 104 butterflyG2(&a[1], &a[5]) 105 butterflyG2(&a[2], &a[6]) 106 butterflyG2(&a[3], &a[7]) 107 108 var twiddle big.Int 109 twiddles[stage+0][1].BigInt(&twiddle) 110 a[5].ScalarMultiplication(&a[5], &twiddle) 111 twiddles[stage+0][2].BigInt(&twiddle) 112 a[6].ScalarMultiplication(&a[6], &twiddle) 113 twiddles[stage+0][3].BigInt(&twiddle) 114 a[7].ScalarMultiplication(&a[7], &twiddle) 115 butterflyG2(&a[0], &a[2]) 116 butterflyG2(&a[1], &a[3]) 117 butterflyG2(&a[4], &a[6]) 118 butterflyG2(&a[5], &a[7]) 119 twiddles[stage+1][1].BigInt(&twiddle) 120 a[3].ScalarMultiplication(&a[3], &twiddle) 121 twiddles[stage+1][1].BigInt(&twiddle) 122 a[7].ScalarMultiplication(&a[7], &twiddle) 123 butterflyG2(&a[0], &a[1]) 124 butterflyG2(&a[2], &a[3]) 125 butterflyG2(&a[4], &a[5]) 126 butterflyG2(&a[6], &a[7]) 127 } 128 129 func difFFTG1(a []curve.G1Affine, twiddles [][]fr.Element, stage, maxSplits int, chDone chan struct{}) { 130 if chDone != nil { 131 defer close(chDone) 132 } 133 134 n := len(a) 135 if n == 1 { 136 return 137 } else if n == 8 { 138 kerDIF8G1(a, twiddles, stage) 139 return 140 } 141 m := n >> 1 142 143 butterflyG1(&a[0], &a[m]) 144 145 var twiddle big.Int 146 for i := 1; i < m; i++ { 147 butterflyG1(&a[i], &a[i+m]) 148 twiddles[stage][i].BigInt(&twiddle) 149 a[i+m].ScalarMultiplication(&a[i+m], &twiddle) 150 } 151 152 if m == 1 { 153 return 154 } 155 156 nextStage := stage + 1 157 if stage < maxSplits { 158 chDone := make(chan struct{}, 1) 159 go difFFTG1(a[m:n], twiddles, nextStage, maxSplits, chDone) 160 difFFTG1(a[0:m], twiddles, nextStage, maxSplits, nil) 161 <-chDone 162 } else { 163 difFFTG1(a[0:m], twiddles, nextStage, maxSplits, nil) 164 difFFTG1(a[m:n], twiddles, nextStage, maxSplits, nil) 165 } 166 } 167 func difFFTG2(a []curve.G2Affine, twiddles [][]fr.Element, stage, maxSplits int, chDone chan struct{}) { 168 if chDone != nil { 169 defer close(chDone) 170 } 171 172 n := len(a) 173 if n == 1 { 174 return 175 } else if n == 8 { 176 kerDIF8G2(a, twiddles, stage) 177 return 178 } 179 m := n >> 1 180 181 butterflyG2(&a[0], &a[m]) 182 183 var twiddle big.Int 184 for i := 1; i < m; i++ { 185 butterflyG2(&a[i], &a[i+m]) 186 twiddles[stage][i].BigInt(&twiddle) 187 a[i+m].ScalarMultiplication(&a[i+m], &twiddle) 188 } 189 190 if m == 1 { 191 return 192 } 193 194 nextStage := stage + 1 195 if stage < maxSplits { 196 chDone := make(chan struct{}, 1) 197 go difFFTG2(a[m:n], twiddles, nextStage, maxSplits, chDone) 198 difFFTG2(a[0:m], twiddles, nextStage, maxSplits, nil) 199 <-chDone 200 } else { 201 difFFTG2(a[0:m], twiddles, nextStage, maxSplits, nil) 202 difFFTG2(a[m:n], twiddles, nextStage, maxSplits, nil) 203 } 204 }