github.com/consensys/gnark-crypto@v0.14.0/internal/generator/ecc/template/svdw.go.tmpl (about)

     1  {{define "svdw"}}
     2  )
     3  {{$TowerDegree := .Field.Degree}}
     4  {{$CoordType := .Point.CoordType}}
     5  {{$CurveName := .Point.PointName}}
     6  {{$CurveTitle := toTitle $CurveName}}
     7  {{$AffineType := print $CurveTitle "Affine"}}
     8  {{$IsG1 := eq $CurveTitle "G1"}}
     9  {{$CurveIndex := "2"}}
    10  {{$B := "bTwistCurveCoeff"}}
    11  {{if $IsG1}}{{$CurveIndex = "1"}}{{$B = "bCurveCoeff"}}{{end}}
    12  
    13  
    14  // MapToCurve{{$CurveIndex}} implements the Shallue and van de Woestijne method, applicable to any elliptic curve in Weierstrass form
    15  // No cofactor clearing or isogeny
    16  // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#straightline-svdw
    17  func MapToCurve{{$CurveIndex}}(u *{{$CoordType}}) {{$AffineType}} {
    18      var tv1, tv2, tv3, tv4 {{$CoordType}}
    19      var x1, x2, x3, gx1, gx2, gx, x, y {{$CoordType}}
    20      var one {{$CoordType}}
    21      var gx1NotSquare, gx1SquareOrGx2Not int
    22  
    23      //constants
    24      //c1 = g(Z)
    25      //c2 = -Z / 2
    26      //c3 = sqrt(-g(Z) * (3 * Z² + 4 * A))     # sgn0(c3) MUST equal 0
    27      //c4 = -4 * g(Z) / (3 * Z² + 4 * A)
    28  
    29      Z  := {{$CoordType}}{{asElement (index $.PrecomputedParams 0)}}
    30      c1 := {{$CoordType}}{{asElement (index $.PrecomputedParams 1)}}
    31      c2 := {{$CoordType}}{{asElement (index $.PrecomputedParams 2)}}
    32      c3 := {{$CoordType}}{{asElement (index $.PrecomputedParams 3)}}
    33      c4 := {{$CoordType}}{{asElement (index $.PrecomputedParams 4)}}
    34  
    35      one.SetOne()
    36  
    37      tv1.Square(u)      //    1.  tv1 = u²
    38      tv1.Mul(&tv1, &c1)  //    2.  tv1 = tv1 * c1
    39      tv2.Add(&one, &tv1) //    3.  tv2 = 1 + tv1
    40      tv1.Sub(&one, &tv1) //    4.  tv1 = 1 - tv1
    41      tv3.Mul(&tv1, &tv2) //    5.  tv3 = tv1 * tv2
    42  
    43      tv3.Inverse(&tv3)   //    6.  tv3 = inv0(tv3)
    44      tv4.Mul(u, &tv1)   //    7.  tv4 = u * tv1
    45      tv4.Mul(&tv4, &tv3) //    8.  tv4 = tv4 * tv3
    46      tv4.Mul(&tv4, &c3)  //    9.  tv4 = tv4 * c3
    47      x1.Sub(&c2, &tv4)   //    10.  x1 = c2 - tv4
    48  
    49      gx1.Square(&x1) //    11. gx1 = x1²
    50      //12. gx1 = gx1 + A     All curves in gnark-crypto have A=0 (j-invariant=0). It is crucial to include this step if the curve has nonzero A coefficient.
    51      gx1.Mul(&gx1, &x1)                 //    13. gx1 = gx1 * x1
    52      gx1.Add(&gx1, &{{$B}})   //    14. gx1 = gx1 + B
    53      gx1NotSquare = gx1.Legendre() >> 1 //    15.  e1 = is_square(gx1)
    54      // gx1NotSquare = 0 if gx1 is a square, -1 otherwise
    55  
    56      x2.Add(&c2, &tv4) //    16.  x2 = c2 + tv4
    57      gx2.Square(&x2)   //    17. gx2 = x2²
    58      //    18. gx2 = gx2 + A     See line 12
    59      gx2.Mul(&gx2, &x2)               //    19. gx2 = gx2 * x2
    60      gx2.Add(&gx2, &{{$B}}) //    20. gx2 = gx2 + B
    61  
    62      {
    63          gx2NotSquare := gx2.Legendre() >> 1              // gx2Square = 0 if gx2 is a square, -1 otherwise
    64          gx1SquareOrGx2Not = gx2NotSquare | ^gx1NotSquare //    21.  e2 = is_square(gx2) AND NOT e1   # Avoid short-circuit logic ops
    65      }
    66  
    67      x3.Square(&tv2)   //    22.  x3 = tv2²
    68      x3.Mul(&x3, &tv3) //    23.  x3 = x3 * tv3
    69      x3.Square(&x3)    //    24.  x3 = x3²
    70      x3.Mul(&x3, &c4)  //    25.  x3 = x3 * c4
    71  
    72      x3.Add(&x3, &Z)                  //    26.  x3 = x3 + Z
    73      x.Select(gx1NotSquare, &x1, &x3) //    27.   x = CMOV(x3, x1, e1)   # x = x1 if gx1 is square, else x = x3
    74      // Select x1 iff gx1 is square iff gx1NotSquare = 0
    75      x.Select(gx1SquareOrGx2Not, &x2, &x) //    28.   x = CMOV(x, x2, e2)    # x = x2 if gx2 is square and gx1 is not
    76      // Select x2 iff gx2 is square and gx1 is not, iff gx1SquareOrGx2Not = 0
    77      gx.Square(&x) //    29.  gx = x²
    78      //    30.  gx = gx + A
    79  
    80      gx.Mul(&gx, &x)                //    31.  gx = gx * x
    81      gx.Add(&gx, &{{$B}}) //    32.  gx = gx + B
    82  
    83      y.Sqrt(&gx)                              //    33.   y = sqrt(gx)
    84      signsNotEqual := {{$CurveName}}Sgn0(u) ^ {{$CurveName}}Sgn0(&y) //    34.  e3 = sgn0(u) == sgn0(y)
    85  
    86      tv1.Neg(&y)
    87      y.Select(int(signsNotEqual), &y, &tv1) //    35.   y = CMOV(-y, y, e3)       # Select correct sign of y
    88      return {{$AffineType}}{x, y}
    89  }
    90  
    91  {{end}}