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  }