LCOV - code coverage report
Current view: top level - ballet/bn254 - fd_bn254_g2.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 192 228 84.2 %
Date: 2026-01-09 05:14:11 Functions: 12 13 92.3 %

          Line data    Source code
       1             : #include "./fd_bn254.h"
       2             : 
       3             : /* G2 */
       4             : 
       5             : /* COV: unlike g1, g2 operations are not exposed to users.
       6             :    So many edge cases and checks for zero are never triggered, e.g. by syscall tests. */
       7             : 
       8             : static inline int
       9      101337 : fd_bn254_g2_is_zero( fd_bn254_g2_t const * p ) {
      10      101337 :   return fd_bn254_fp2_is_zero( &p->Z );
      11      101337 : }
      12             : 
      13             : static inline int
      14             : fd_bn254_g2_eq( fd_bn254_g2_t const * p,
      15         735 :                 fd_bn254_g2_t const * q ) {
      16         735 :   if( fd_bn254_g2_is_zero( p ) ) {
      17           0 :     return fd_bn254_g2_is_zero( q );
      18           0 :   }
      19         735 :   if( fd_bn254_g2_is_zero( q ) ) {
      20           0 :     return 0;
      21           0 :   }
      22             : 
      23         735 :   fd_bn254_fp2_t pz2[1], qz2[1];
      24         735 :   fd_bn254_fp2_t l[1], r[1];
      25             : 
      26         735 :   fd_bn254_fp2_sqr( pz2, &p->Z );
      27         735 :   fd_bn254_fp2_sqr( qz2, &q->Z );
      28             : 
      29         735 :   fd_bn254_fp2_mul( l, &p->X, qz2 );
      30         735 :   fd_bn254_fp2_mul( r, &q->X, pz2 );
      31         735 :   if( !fd_bn254_fp2_eq( l, r ) ) {
      32           0 :     return 0;
      33           0 :   }
      34             : 
      35         735 :   fd_bn254_fp2_mul( l, &p->Y, qz2 );
      36         735 :   fd_bn254_fp2_mul( l, l, &q->Z );
      37         735 :   fd_bn254_fp2_mul( r, &q->Y, pz2 );
      38         735 :   fd_bn254_fp2_mul( r, r, &p->Z );
      39         735 :   return fd_bn254_fp2_eq( l, r );
      40         735 : }
      41             : 
      42             : static inline fd_bn254_g2_t *
      43             : fd_bn254_g2_set( fd_bn254_g2_t *       r,
      44        1470 :                  fd_bn254_g2_t const * p ) {
      45        1470 :   fd_bn254_fp2_set( &r->X, &p->X );
      46        1470 :   fd_bn254_fp2_set( &r->Y, &p->Y );
      47        1470 :   fd_bn254_fp2_set( &r->Z, &p->Z );
      48        1470 :   return r;
      49        1470 : }
      50             : 
      51             : static inline fd_bn254_g2_t *
      52             : fd_bn254_g2_neg( fd_bn254_g2_t *       r,
      53         735 :                  fd_bn254_g2_t const * p ) {
      54         735 :   fd_bn254_fp2_set( &r->X, &p->X );
      55         735 :   fd_bn254_fp2_neg( &r->Y, &p->Y );
      56         735 :   fd_bn254_fp2_set( &r->Z, &p->Z );
      57         735 :   return r;
      58         735 : }
      59             : 
      60             : static inline fd_bn254_g2_t *
      61           0 : fd_bn254_g2_set_zero( fd_bn254_g2_t * r ) {
      62             :   // fd_bn254_fp2_set_zero( &r->X );
      63             :   // fd_bn254_fp2_set_zero( &r->Y );
      64           0 :   fd_bn254_fp2_set_zero( &r->Z );
      65           0 :   return r;
      66           0 : }
      67             : 
      68             : static inline fd_bn254_g2_t *
      69             : fd_bn254_g2_frob( fd_bn254_g2_t *       r,
      70        2205 :                   fd_bn254_g2_t const * p ) {
      71        2205 :   fd_bn254_fp2_conj( &r->X, &p->X );
      72        2205 :   fd_bn254_fp2_mul ( &r->X, &r->X, &fd_bn254_const_frob_gamma1_mont[1] );
      73        2205 :   fd_bn254_fp2_conj( &r->Y, &p->Y );
      74        2205 :   fd_bn254_fp2_mul ( &r->Y, &r->Y, &fd_bn254_const_frob_gamma1_mont[2] );
      75        2205 :   fd_bn254_fp2_conj( &r->Z, &p->Z );
      76        2205 :   return r;
      77        2205 : }
      78             : 
      79             : static inline fd_bn254_g2_t *
      80             : fd_bn254_g2_frob2( fd_bn254_g2_t *       r,
      81        1470 :                    fd_bn254_g2_t const * p ) {
      82             :   /* X */
      83        1470 :   fd_bn254_fp_mul( &r->X.el[0], &p->X.el[0], &fd_bn254_const_frob_gamma2_mont[1] );
      84        1470 :   fd_bn254_fp_mul( &r->X.el[1], &p->X.el[1], &fd_bn254_const_frob_gamma2_mont[1] );
      85             :   /* Y */
      86        1470 :   fd_bn254_fp_mul( &r->Y.el[0], &p->Y.el[0], &fd_bn254_const_frob_gamma2_mont[2] );
      87        1470 :   fd_bn254_fp_mul( &r->Y.el[1], &p->Y.el[1], &fd_bn254_const_frob_gamma2_mont[2] );
      88             :   /* Z=1 */
      89        1470 :   fd_bn254_fp2_set( &r->Z, &p->Z );
      90        1470 :   return r;
      91        1470 : }
      92             : 
      93             : /* fd_bn254_g2_dbl computes r = 2p.
      94             :    https://hyperelliptic.org/efd/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l */
      95             : fd_bn254_g2_t *
      96             : fd_bn254_g2_dbl( fd_bn254_g2_t *       r,
      97       46305 :                  fd_bn254_g2_t const * p ) {
      98             :   /* p==0, return 0 */
      99       46305 :   if( FD_UNLIKELY( fd_bn254_g2_is_zero( p ) ) ) {
     100           0 :     return fd_bn254_g2_set_zero( r );
     101           0 :   }
     102             : 
     103       46305 :   fd_bn254_fp2_t a[1], b[1], c[1];
     104       46305 :   fd_bn254_fp2_t d[1], e[1], f[1];
     105             : 
     106             :   /* A = X1^2 */
     107       46305 :   fd_bn254_fp2_sqr( a, &p->X );
     108             :   /* B = Y1^2 */
     109       46305 :   fd_bn254_fp2_sqr( b, &p->Y );
     110             :   /* C = B^2 */
     111       46305 :   fd_bn254_fp2_sqr( c, b );
     112             :   /* D = 2*((X1+B)^2-A-C)
     113             :      (X1+B)^2 = X1^2 + 2*X1*B + B^2
     114             :      D = 2*(X1^2 + 2*X1*B + B^2 - A    - C)
     115             :      D = 2*(X1^2 + 2*X1*B + B^2 - X1^2 - B^2)
     116             :             ^               ^     ^      ^
     117             :             |---------------|-----|      |
     118             :                             |------------|
     119             :      These terms cancel each other out, and we're left with:
     120             :      D = 2*(2*X1*B) */
     121       46305 :   fd_bn254_fp2_mul( d, &p->X, b );
     122       46305 :   fd_bn254_fp2_add( d, d, d );
     123       46305 :   fd_bn254_fp2_add( d, d, d );
     124             :   /* E = 3*A */
     125       46305 :   fd_bn254_fp2_add( e, a, a );
     126       46305 :   fd_bn254_fp2_add( e, a, e );
     127             :   /* F = E^2 */
     128       46305 :   fd_bn254_fp2_sqr( f, e );
     129             :   /* X3 = F-2*D */
     130       46305 :   fd_bn254_fp2_add( &r->X, d, d );
     131       46305 :   fd_bn254_fp2_sub( &r->X, f, &r->X );
     132             :   /* Z3 = (Y1+Z1)^2-YY-ZZ
     133             :      note: compute Z3 before Y3 because it depends on p->Y,
     134             :      that might be overwritten if r==p. */
     135             :   /* Z3 = 2*Y1*Z1 */
     136       46305 :   fd_bn254_fp2_mul( &r->Z, &p->Y, &p->Z );
     137       46305 :   fd_bn254_fp2_add( &r->Z, &r->Z, &r->Z );
     138             :   /* Y3 = E*(D-X3)-8*C */
     139       46305 :   fd_bn254_fp2_sub( &r->Y, d, &r->X );
     140       46305 :   fd_bn254_fp2_mul( &r->Y, e, &r->Y );
     141       46305 :   fd_bn254_fp2_add( c, c, c ); /* 2*c */
     142       46305 :   fd_bn254_fp2_add( c, c, c ); /* 4*y */
     143       46305 :   fd_bn254_fp2_add( c, c, c ); /* 8*y */
     144       46305 :   fd_bn254_fp2_sub( &r->Y, &r->Y, c );
     145       46305 :   return r;
     146       46305 : }
     147             : 
     148             : /* fd_bn254_g2_add_mixed computes r = p + q, when q->Z==1.
     149             :    http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl */
     150             : fd_bn254_g2_t *
     151             : fd_bn254_g2_add_mixed( fd_bn254_g2_t *       r,
     152             :                        fd_bn254_g2_t const * p,
     153       20580 :                        fd_bn254_g2_t const * q ) {
     154             :   /* p==0, return q */
     155       20580 :   if( FD_UNLIKELY( fd_bn254_g2_is_zero( p ) ) ) {
     156           0 :     return fd_bn254_g2_set( r, q );
     157           0 :   }
     158       20580 :   fd_bn254_fp2_t zz[1], u2[1], s2[1];
     159       20580 :   fd_bn254_fp2_t h[1], hh[1];
     160       20580 :   fd_bn254_fp2_t i[1], j[1];
     161       20580 :   fd_bn254_fp2_t rr[1], v[1];
     162             :   /* Z1Z1 = Z1^2 */
     163       20580 :   fd_bn254_fp2_sqr( zz, &p->Z );
     164             :   /* U2 = X2*Z1Z1 */
     165       20580 :   fd_bn254_fp2_mul( u2, &q->X, zz );
     166             :   /* S2 = Y2*Z1*Z1Z1 */
     167       20580 :   fd_bn254_fp2_mul( s2, &q->Y, &p->Z );
     168       20580 :   fd_bn254_fp2_mul( s2, s2, zz );
     169             : 
     170             :   /* if p==q, call fd_bn254_g2_dbl */
     171       20580 :   if( FD_UNLIKELY( fd_bn254_fp2_eq( u2, &p->X ) && fd_bn254_fp2_eq( s2, &p->Y ) ) ) {
     172           0 :     return fd_bn254_g2_dbl( r, p );
     173           0 :   }
     174             : 
     175             :   /* H = U2-X1 */
     176       20580 :   fd_bn254_fp2_sub( h, u2, &p->X );
     177             :   /* HH = H^2 */
     178       20580 :   fd_bn254_fp2_sqr( hh, h );
     179             :   /* I = 4*HH */
     180       20580 :   fd_bn254_fp2_add( i, hh, hh );
     181       20580 :   fd_bn254_fp2_add( i, i, i );
     182             :   /* J = H*I */
     183       20580 :   fd_bn254_fp2_mul( j, h, i );
     184             :   /* r = 2*(S2-Y1) */
     185       20580 :   fd_bn254_fp2_sub( rr, s2, &p->Y );
     186       20580 :   fd_bn254_fp2_add( rr, rr, rr );
     187             :   /* V = X1*I */
     188       20580 :   fd_bn254_fp2_mul( v, &p->X, i );
     189             :   /* X3 = r^2-J-2*V */
     190       20580 :   fd_bn254_fp2_sqr( &r->X, rr );
     191       20580 :   fd_bn254_fp2_sub( &r->X, &r->X, j );
     192       20580 :   fd_bn254_fp2_sub( &r->X, &r->X, v );
     193       20580 :   fd_bn254_fp2_sub( &r->X, &r->X, v );
     194             :   /* Y3 = r*(V-X3)-2*Y1*J
     195             :      note: i no longer used */
     196       20580 :   fd_bn254_fp2_mul( i, &p->Y, j ); /* i =   Y1*J */
     197       20580 :   fd_bn254_fp2_add( i, i, i );     /* i = 2*Y1*J */
     198       20580 :   fd_bn254_fp2_sub( &r->Y, v, &r->X );
     199       20580 :   fd_bn254_fp2_mul( &r->Y, &r->Y, rr );
     200       20580 :   fd_bn254_fp2_sub( &r->Y, &r->Y, i );
     201             :   /* Z3 = (Z1+H)^2-Z1Z1-HH */
     202       20580 :   fd_bn254_fp2_add( &r->Z, &p->Z, h );
     203       20580 :   fd_bn254_fp2_sqr( &r->Z, &r->Z );
     204       20580 :   fd_bn254_fp2_sub( &r->Z, &r->Z, zz );
     205       20580 :   fd_bn254_fp2_sub( &r->Z, &r->Z, hh );
     206       20580 :   return r;
     207       20580 : }
     208             : 
     209             : /* fd_bn254_g2_add computes r = p + q.
     210             :    http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl */
     211             : fd_bn254_g2_t *
     212             : fd_bn254_g2_add( fd_bn254_g2_t *       r,
     213             :                  fd_bn254_g2_t const * p,
     214        1470 :                  fd_bn254_g2_t const * q ) {
     215             :   /* p==0, return q */
     216        1470 :   if( FD_UNLIKELY( fd_bn254_g2_is_zero( p ) ) ) {
     217           0 :     return fd_bn254_g2_set( r, q );
     218           0 :   }
     219        1470 :   fd_bn254_fp2_t zz1[1], zz2[1];
     220        1470 :   fd_bn254_fp2_t u1[1], s1[1];
     221        1470 :   fd_bn254_fp2_t u2[1], s2[1];
     222        1470 :   fd_bn254_fp2_t h[1];
     223        1470 :   fd_bn254_fp2_t i[1], j[1];
     224        1470 :   fd_bn254_fp2_t rr[1], v[1];
     225             :   /* Z1Z1 = Z1^2 */
     226        1470 :   fd_bn254_fp2_sqr( zz1, &p->Z );
     227             :   /* Z2Z2 = Z2^2 */
     228        1470 :   fd_bn254_fp2_sqr( zz2, &q->Z );
     229             :   /* U1 = X1*Z2Z2 */
     230        1470 :   fd_bn254_fp2_mul( u1, &p->X, zz2 );
     231             :   /* U2 = X2*Z1Z1 */
     232        1470 :   fd_bn254_fp2_mul( u2, &q->X, zz1 );
     233             :   /* S1 = Y1*Z2*Z2Z2 */
     234        1470 :   fd_bn254_fp2_mul( s1, &p->Y, &q->Z );
     235        1470 :   fd_bn254_fp2_mul( s1, s1, zz2 );
     236             :   /* S2 = Y2*Z1*Z1Z1 */
     237        1470 :   fd_bn254_fp2_mul( s2, &q->Y, &p->Z );
     238        1470 :   fd_bn254_fp2_mul( s2, s2, zz1 );
     239             : 
     240             :   /* if p==q, call fd_bn254_g2_dbl */
     241             :   // if( FD_UNLIKELY( fd_bn254_fp2_eq( u2, &p->X ) && fd_bn254_fp2_eq( s2, &p->Y ) ) ) {
     242             :   //   return fd_bn254_g2_dbl( r, p );
     243             :   // }
     244             : 
     245             :   /* H = U2-U1 */
     246        1470 :   fd_bn254_fp2_sub( h, u2, u1 );
     247             :   /* HH = (2*H)^2 */
     248        1470 :   fd_bn254_fp2_add( i, h, h );
     249        1470 :   fd_bn254_fp2_sqr( i, i );
     250             :   /* J = H*I */
     251        1470 :   fd_bn254_fp2_mul( j, h, i );
     252             :   /* r = 2*(S2-S1) */
     253        1470 :   fd_bn254_fp2_sub( rr, s2, s1 );
     254        1470 :   fd_bn254_fp2_add( rr, rr, rr );
     255             :   /* V = U1*I */
     256        1470 :   fd_bn254_fp2_mul( v, u1, i );
     257             :   /* X3 = r^2-J-2*V */
     258        1470 :   fd_bn254_fp2_sqr( &r->X, rr );
     259        1470 :   fd_bn254_fp2_sub( &r->X, &r->X, j );
     260        1470 :   fd_bn254_fp2_sub( &r->X, &r->X, v );
     261        1470 :   fd_bn254_fp2_sub( &r->X, &r->X, v );
     262             :   /* Y3 = r*(V-X3)-2*S1*J
     263             :      note: i no longer used */
     264        1470 :   fd_bn254_fp2_mul( i, s1, j ); /* i =   S1*J */
     265        1470 :   fd_bn254_fp2_add( i, i, i );  /* i = 2*S1*J */
     266        1470 :   fd_bn254_fp2_sub( &r->Y, v, &r->X );
     267        1470 :   fd_bn254_fp2_mul( &r->Y, &r->Y, rr );
     268        1470 :   fd_bn254_fp2_sub( &r->Y, &r->Y, i );
     269             :   /* Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H */
     270        1470 :   fd_bn254_fp2_add( &r->Z, &p->Z, &q->Z );
     271        1470 :   fd_bn254_fp2_sqr( &r->Z, &r->Z );
     272        1470 :   fd_bn254_fp2_sub( &r->Z, &r->Z, zz1 );
     273        1470 :   fd_bn254_fp2_sub( &r->Z, &r->Z, zz2 );
     274        1470 :   fd_bn254_fp2_mul( &r->Z, &r->Z, h );
     275        1470 :   return r;
     276        1470 : }
     277             : 
     278             : /* fd_bn254_g2_scalar_mul computes r = s * p.
     279             :    This assumes that p is affine, i.e. p->Z==1. */
     280             : fd_bn254_g2_t *
     281             : fd_bn254_g2_scalar_mul( fd_bn254_g2_t *           r,
     282             :                         fd_bn254_g2_t const *     p,
     283         735 :                         fd_bn254_scalar_t const * s ) {
     284             :   /* TODO: wNAF, GLV */
     285         735 :   int i = 255;
     286      142590 :   for( ; i>=0 && !fd_uint256_bit( s, i ); i-- ) ; /* do nothing, just i-- */
     287         735 :   if( FD_UNLIKELY( i<0 ) ) {
     288             :     /* COV: this only happens when the scalar is zero.
     289             :        Unlike g1, g2_scalar_mul is not exposed to users but only used internally,
     290             :        so scalar is never zero. */
     291           0 :     return fd_bn254_g2_set_zero( r );
     292           0 :   }
     293         735 :   fd_bn254_g2_set( r, p );
     294       46305 :   for( i--; i>=0; i-- ) {
     295       45570 :     fd_bn254_g2_dbl( r, r );
     296       45570 :     if( fd_uint256_bit( s, i ) ) {
     297       19845 :       fd_bn254_g2_add_mixed( r, r, p );
     298       19845 :     }
     299       45570 :   }
     300         735 :   return r;
     301         735 : }
     302             : 
     303             : /* fd_bn254_g2_frombytes_internal extracts (x, y) and performs basic checks.
     304             :    This is used by fd_bn254_g2_compress() and fd_bn254_g2_frombytes_check_subgroup(). */
     305             : static inline fd_bn254_g2_t *
     306             : fd_bn254_g2_frombytes_internal( fd_bn254_g2_t * p,
     307       30777 :                                 uchar const     in[128] ) {
     308             :   /* Special case: all zeros => point at infinity */
     309       30777 :   const uchar zero[128] = { 0 };
     310       30777 :   if( FD_UNLIKELY( fd_memeq( in, zero, 128 ) ) ) {
     311           0 :     return fd_bn254_g2_set_zero( p );
     312           0 :   }
     313             : 
     314             :   /* Check x < p */
     315       30777 :   if( FD_UNLIKELY( !fd_bn254_fp2_frombytes_be_nm( &p->X, &in[0], NULL, NULL ) ) ) {
     316           0 :     return NULL;
     317           0 :   }
     318             : 
     319             :   /* Check flags and y < p */
     320       30777 :   int is_inf, is_neg;
     321       30777 :   if( FD_UNLIKELY( !fd_bn254_fp2_frombytes_be_nm( &p->Y, &in[64], &is_inf, &is_neg ) ) ) {
     322           0 :     return NULL;
     323           0 :   }
     324             : 
     325       30777 :   if( FD_UNLIKELY( is_inf ) ) {
     326           0 :     return fd_bn254_g2_set_zero( p );
     327           0 :   }
     328             : 
     329       30777 :   fd_bn254_fp2_set_one( &p->Z );
     330       30777 :   return p;
     331       30777 : }
     332             : 
     333             : /* fd_bn254_g2_frombytes_check_subgroup performs frombytes AND checks subgroup membership. */
     334             : static inline fd_bn254_g2_t *
     335             : fd_bn254_g2_frombytes_check_subgroup( fd_bn254_g2_t * p,
     336         735 :                                       uchar const     in[128] ) {
     337         735 :   if( FD_UNLIKELY( !fd_bn254_g2_frombytes_internal( p, in ) ) ) {
     338           0 :     return NULL;
     339           0 :   }
     340         735 :   if( FD_UNLIKELY( fd_bn254_g2_is_zero( p ) ) ) {
     341           0 :     return p;
     342           0 :   }
     343             : 
     344         735 :   fd_bn254_fp2_to_mont( &p->X, &p->X );
     345         735 :   fd_bn254_fp2_to_mont( &p->Y, &p->Y );
     346         735 :   fd_bn254_fp2_set_one( &p->Z );
     347             : 
     348             :   /* Check that y^2 = x^3 + b */
     349         735 :   fd_bn254_fp2_t y2[1], x3b[1];
     350         735 :   fd_bn254_fp2_sqr( y2, &p->Y );
     351         735 :   fd_bn254_fp2_sqr( x3b, &p->X );
     352         735 :   fd_bn254_fp2_mul( x3b, x3b, &p->X );
     353         735 :   fd_bn254_fp2_add( x3b, x3b, fd_bn254_const_twist_b_mont );
     354         735 :   if( FD_UNLIKELY( !fd_bn254_fp2_eq( y2, x3b ) ) ) {
     355           0 :     return NULL;
     356           0 :   }
     357             : 
     358             :   /* G2 does NOT have prime order, so we have to check group membership. */
     359             : 
     360             :   /* We use the fast subgroup membership check, that requires a single 64-bit scalar mul.
     361             :      https://eprint.iacr.org/2022/348, Sec 3.1.
     362             :      [r]P == 0 <==> [x+1]P + ψ([x]P) + ψ²([x]P) = ψ³([2x]P)
     363             :      See also: https://github.com/Consensys/gnark-crypto/blob/v0.12.1/ecc/bn254/g2.go#L404
     364             : 
     365             :      For reference, the followings also work:
     366             : 
     367             :      1) very slow: 256-bit scalar mul
     368             : 
     369             :      fd_bn254_g2_t r[1];
     370             :      fd_bn254_g2_scalar_mul( r, p, fd_bn254_const_r );
     371             :      if( !fd_bn254_g2_is_zero( r ) ) return NULL;
     372             : 
     373             :      2) slow: 128-bit scalar mul
     374             : 
     375             :      fd_bn254_g2_t a[1], b[1];
     376             :      const fd_bn254_scalar_t six_x_sqr[1] = {{{ 0xf83e9682e87cfd46, 0x6f4d8248eeb859fb, 0x0, 0x0, }}};
     377             :      fd_bn254_g2_scalar_mul( a, p, six_x_sqr );
     378             :      fd_bn254_g2_frob( b, p );
     379             :      if( !fd_bn254_g2_eq( a, b ) ) return NULL; */
     380             : 
     381         735 :   fd_bn254_g2_t xp[1], l[1], psi[1], r[1];
     382         735 :   fd_bn254_g2_scalar_mul( xp, p, fd_bn254_const_x ); /* 64-bit */
     383         735 :   fd_bn254_g2_add_mixed( l, xp, p );
     384             : 
     385         735 :   fd_bn254_g2_frob( psi, xp );
     386         735 :   fd_bn254_g2_add( l, l, psi );
     387             : 
     388         735 :   fd_bn254_g2_frob2( psi, xp ); /* faster than frob( psi, psi ) */
     389         735 :   fd_bn254_g2_add( l, l, psi );
     390             : 
     391         735 :   fd_bn254_g2_frob( psi, psi );
     392         735 :   fd_bn254_g2_dbl( r, psi );
     393         735 :   if( FD_UNLIKELY( !fd_bn254_g2_eq( l, r ) ) ) {
     394           0 :     return NULL;
     395           0 :   }
     396             : 
     397         735 :   return p;
     398         735 : }

Generated by: LCOV version 1.14