LCOV - code coverage report
Current view: top level - ballet/bn254 - fd_bn254_field.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 114 114 100.0 %
Date: 2024-11-13 11:58:15 Functions: 16 16 100.0 %

          Line data    Source code
       1             : #include "./fd_bn254.h"
       2             : #include "../fiat-crypto/bn254_64.c"
       3             : 
       4             : /* Fp = base field */
       5             : 
       6        6018 : #define FLAG_INF  ((uchar)(1 << 6))
       7        5796 : #define FLAG_NEG  ((uchar)(1 << 7))
       8        5328 : #define FLAG_MASK 0x3F
       9             : 
      10             : /* const 0. */
      11             : const fd_bn254_fp_t fd_bn254_const_zero[1] = {{{
      12             :   0x0UL, 0x0UL, 0x0UL, 0x0UL,
      13             : }}};
      14             : 
      15             : /* const p, used to validate a field element. NOT Montgomery.
      16             :    0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 */
      17             : const fd_bn254_fp_t fd_bn254_const_p[1] = {{{
      18             :   0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029,
      19             : }}};
      20             : 
      21             : /* const 1/p for CIOS mul */
      22             : static const ulong fd_bn254_const_p_inv = 0x87D20782E4866389UL;
      23             : 
      24             : /* const 1. Montgomery.
      25             :    0x0e0a77c19a07df2f666ea36f7879462c0a78eb28f5c70b3dd35d438dc58f0d9d */
      26             : const fd_bn254_fp_t fd_bn254_const_one_mont[1] = {{{
      27             :   0xd35d438dc58f0d9d, 0x0a78eb28f5c70b3d, 0x666ea36f7879462c, 0x0e0a77c19a07df2f
      28             : }}};
      29             : 
      30             : /* const x, used by fd_bn254_g2_frombytes_check(). scalar (NOT Montgomery)
      31             :    0x44e992b44a6909f1 (64-bit) */
      32             : const fd_bn254_scalar_t fd_bn254_const_x[1] = {{{
      33             :   0x44e992b44a6909f1, 0x0, 0x0, 0x0,
      34             : }}};
      35             : 
      36             : /* const b=3, in curve equation y^2 = x^3 + b. Montgomery.
      37             :    0x2a1f6744ce179d8e334bea4e696bd2841f6ac17ae15521b97a17caa950ad28d7 */
      38             : const fd_bn254_fp_t fd_bn254_const_b_mont[1] = {{{
      39             :   0x7a17caa950ad28d7, 0x1f6ac17ae15521b9, 0x334bea4e696bd284, 0x2a1f6744ce179d8e
      40             :   // 0x3UL, 0x0UL, 0x0UL, 0x0UL,
      41             : }}};
      42             : 
      43             : /* const p-1, to check if sqrt exists. Montgomery.
      44             :    0x2259d6b14729c0fa51e1a247090812318d087f6872aabf4f68c3488912edefaa */
      45             : const fd_bn254_fp_t fd_bn254_const_p_minus_one_mont[1] = {{{
      46             :   0x68c3488912edefaa, 0x8d087f6872aabf4f, 0x51e1a24709081231, 0x2259d6b14729c0fa,
      47             : }}};
      48             : 
      49             : /* const (p-1)/2, used to check if an element is positive or negative,
      50             :    and to calculate sqrt() in Fp2. NOT Montgomery.
      51             :    0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3 */
      52             : const fd_bn254_fp_t fd_bn254_const_p_minus_one_half[1] = {{{
      53             :   0x9e10460b6c3e7ea3, 0xcbc0b548b438e546, 0xdc2822db40c0ac2e, 0x183227397098d014,
      54             : }}};
      55             : 
      56             : /* const (p-3)/4, used to calculate sqrt() in Fp and Fp2. bigint (NOT Montgomery)
      57             :    0x0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f51 */
      58             : const fd_uint256_t fd_bn254_const_sqrt_exp[1] = {{{
      59             :   0x4f082305b61f3f51, 0x65e05aa45a1c72a3, 0x6e14116da0605617, 0x0c19139cb84c680a,
      60             : }}};
      61             : 
      62             : static inline int
      63         789 : fd_bn254_fp_is_neg_nm( fd_bn254_fp_t * x ) {
      64         789 :   return fd_uint256_cmp( x, fd_bn254_const_p_minus_one_half ) > 0;
      65         789 : }
      66             : 
      67             : static inline fd_bn254_fp_t *
      68             : fd_bn254_fp_frombytes_be_nm( fd_bn254_fp_t * r,
      69             :                              uchar const     buf[32],
      70             :                              int *           is_inf,
      71       18117 :                              int *           is_neg ) {
      72             :   /* Flags (optional) */
      73       18117 :   if( is_inf != NULL /* && is_neg != NULL */ ) {
      74        5718 :     *is_inf = !!(buf[0] & FLAG_INF);
      75        5718 :     *is_neg = !!(buf[0] & FLAG_NEG);
      76             :     /* If both flags are set (bit 6, 7), return error.
      77             :        https://github.com/arkworks-rs/algebra/blob/v0.4.2/ec/src/models/short_weierstrass/serialization_flags.rs#L75 */
      78        5718 :     if( FD_UNLIKELY( *is_inf && *is_neg ) ) {
      79         981 :       return NULL;
      80         981 :     }
      81        5718 :   }
      82             : 
      83       17136 :   fd_memcpy( r, buf, 32 );
      84       17136 :   fd_uint256_bswap( r, r );
      85       17136 :   if( is_inf != NULL ) {
      86        4737 :     r->buf[31] &= FLAG_MASK;
      87        4737 :   }
      88             : 
      89             :   /* Field element */
      90       17136 :   if( FD_UNLIKELY( fd_uint256_cmp( r, fd_bn254_const_p ) >= 0 ) ) {
      91        5382 :     return NULL;
      92        5382 :   }
      93       11754 :   return r;
      94       17136 : }
      95             : 
      96             : static inline uchar *
      97             : fd_bn254_fp_tobytes_be_nm( uchar           buf[32],
      98        2217 :                            fd_bn254_fp_t * a ) {
      99        2217 :   fd_uint256_bswap( a, a );
     100        2217 :   fd_memcpy( buf, a, 32 );
     101        2217 :   return buf;
     102        2217 : }
     103             : 
     104             : static inline int
     105             : fd_bn254_fp_eq( fd_bn254_fp_t const * r,
     106      103584 :                 fd_bn254_fp_t const * a ) {
     107      103584 :   return fd_uint256_eq( r, a );
     108      103584 : }
     109             : 
     110             : static inline fd_bn254_fp_t *
     111             : fd_bn254_fp_from_mont( fd_bn254_fp_t * r,
     112        2217 :                        fd_bn254_fp_t const * a ) {
     113        2217 :   fiat_bn254_from_montgomery( r->limbs, a->limbs );
     114        2217 :   return r;
     115        2217 : }
     116             : 
     117             : static inline fd_bn254_fp_t *
     118             : fd_bn254_fp_to_mont( fd_bn254_fp_t * r,
     119        6831 :                      fd_bn254_fp_t const * a ) {
     120        6831 :   fiat_bn254_to_montgomery( r->limbs, a->limbs );
     121        6831 :   return r;
     122        6831 : }
     123             : 
     124             : static inline fd_bn254_fp_t *
     125             : fd_bn254_fp_neg_nm( fd_bn254_fp_t * r,
     126         219 :                     fd_bn254_fp_t const * a ) {
     127         219 :   if( FD_UNLIKELY( fd_bn254_fp_is_zero( a ) ) ) {
     128           6 :     return fd_bn254_fp_set_zero( r );
     129           6 :   }
     130             :   /* compute p-a */
     131        1065 :   for( ulong i=0, cy=0; i<4; i++ ) {
     132         852 :     ulong p = fd_bn254_const_p->limbs[i];
     133         852 :     ulong b = a->limbs[i];
     134         852 :     b += cy;
     135         852 :     cy = (b < cy);
     136         852 :     cy += (p < b);
     137         852 :     r->limbs[i] = p - b;
     138         852 :   }
     139         213 :   return r;
     140         219 : }
     141             : 
     142             : static inline fd_bn254_fp_t *
     143             : fd_bn254_fp_set( fd_bn254_fp_t * r,
     144     1940574 :                  fd_bn254_fp_t const * a ) {
     145     1940574 :   r->limbs[0] = a->limbs[0];
     146     1940574 :   r->limbs[1] = a->limbs[1];
     147     1940574 :   r->limbs[2] = a->limbs[2];
     148     1940574 :   r->limbs[3] = a->limbs[3];
     149     1940574 :   return r;
     150     1940574 : }
     151             : 
     152             : static inline fd_bn254_fp_t *
     153             : fd_bn254_fp_add( fd_bn254_fp_t * r,
     154             :                  fd_bn254_fp_t const * a,
     155    16783779 :                  fd_bn254_fp_t const * b ) {
     156    16783779 :   fiat_bn254_add( r->limbs, a->limbs, b->limbs );
     157    16783779 :   return r;
     158    16783779 : }
     159             : 
     160             : static inline fd_bn254_fp_t *
     161             : fd_bn254_fp_sub( fd_bn254_fp_t * r,
     162             :                  fd_bn254_fp_t const * a,
     163    10781037 :                  fd_bn254_fp_t const * b ) {
     164    10781037 :   fiat_bn254_sub( r->limbs, a->limbs, b->limbs );
     165    10781037 :   return r;
     166    10781037 : }
     167             : 
     168             : static inline fd_bn254_fp_t *
     169             : fd_bn254_fp_neg( fd_bn254_fp_t * r,
     170       67458 :                  fd_bn254_fp_t const * a ) {
     171       67458 :   fiat_bn254_opp( r->limbs, a->limbs );
     172       67458 :   return r;
     173       67458 : }
     174             : 
     175             : static inline fd_bn254_fp_t *
     176             : fd_bn254_fp_halve( fd_bn254_fp_t * r,
     177       64512 :                    fd_bn254_fp_t const * a ) {
     178       64512 :   int is_odd = r->limbs[0] & 0x1;
     179       64512 :   fd_uint256_add( r, a, is_odd ? fd_bn254_const_p : fd_bn254_const_zero );
     180       64512 :   r->limbs[0] = (r->limbs[0] >> 1) | (r->limbs[1] << 63);
     181       64512 :   r->limbs[1] = (r->limbs[1] >> 1) | (r->limbs[2] << 63);
     182       64512 :   r->limbs[2] = (r->limbs[2] >> 1) | (r->limbs[3] << 63);
     183       64512 :   r->limbs[3] = (r->limbs[3] >> 1);
     184       64512 :   return r;
     185       64512 : }
     186             : 
     187             : FD_UINT256_FP_MUL_IMPL(fd_bn254_fp, fd_bn254_const_p, fd_bn254_const_p_inv)
     188             : 
     189             : static inline fd_bn254_fp_t *
     190             : fd_bn254_fp_sqr( fd_bn254_fp_t * r,
     191     1763430 :                  fd_bn254_fp_t const * a ) {
     192     1763430 :   return fd_bn254_fp_mul( r, a, a );
     193     1763430 : }
     194             : 
     195             : fd_bn254_fp_t *
     196             : fd_bn254_fp_pow( fd_bn254_fp_t * restrict r,
     197             :                  fd_bn254_fp_t const *    a,
     198        1167 :                  fd_uint256_t const *     b ) {
     199        1167 :   fd_bn254_fp_set_one( r );
     200             : 
     201        1167 :   int i = 255;
     202        4155 :   while( !fd_uint256_bit( b, i) ) i--;
     203      296931 :   for( ; i>=0; i--) {
     204      295764 :     fd_bn254_fp_sqr( r, r );
     205      295764 :     if( fd_uint256_bit( b, i ) ) {
     206      128043 :       fd_bn254_fp_mul( r, r, a );
     207      128043 :     }
     208      295764 :   }
     209        1167 :   return r;
     210        1167 : }
     211             : 
     212             : static inline fd_bn254_fp_t *
     213             : fd_bn254_fp_inv( fd_bn254_fp_t * r,
     214         840 :                   fd_bn254_fp_t const * a ) {
     215         840 :   fd_uint256_t p_minus_2[1];
     216         840 :   fd_bn254_fp_set( p_minus_2, fd_bn254_const_p );
     217         840 :   p_minus_2->limbs[0] = p_minus_2->limbs[0] - 2UL;
     218         840 :   return fd_bn254_fp_pow( r, a, p_minus_2 );
     219         840 : }
     220             : 
     221             : static inline fd_bn254_fp_t *
     222             : fd_bn254_fp_sqrt( fd_bn254_fp_t * r,
     223         327 :                   fd_bn254_fp_t const * a ) {
     224             :   /* Alg. 2, https://eprint.iacr.org/2012/685 */
     225             : 
     226         327 :   fd_bn254_fp_t a0[1], a1[1];
     227             : 
     228         327 :   fd_bn254_fp_pow( a1, a, fd_bn254_const_sqrt_exp );
     229             : 
     230         327 :   fd_bn254_fp_sqr( a0, a1 );
     231         327 :   fd_bn254_fp_mul( a0, a0, a );
     232         327 :   if( FD_UNLIKELY( fd_bn254_fp_eq( a0, fd_bn254_const_p_minus_one_mont ) ) ) {
     233           6 :     return NULL;
     234           6 :   }
     235             : 
     236         321 :   fd_bn254_fp_mul( r, a1, a );
     237         321 :   return r;
     238         327 : }

Generated by: LCOV version 1.14