LCOV - code coverage report
Current view: top level - ballet/bn254 - fd_poseidon.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 123 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 8 0.0 %

          Line data    Source code
       1             : #include "./fd_poseidon.h"
       2             : #include "fd_poseidon_params.c"
       3             : 
       4             : /* Poseidon internals */
       5             : 
       6             : static inline void
       7             : fd_poseidon_apply_ark( fd_bn254_scalar_t         state[],
       8             :                        ulong const               width,
       9             :                        fd_poseidon_par_t const * params,
      10           0 :                        ulong                     round ) {
      11           0 :   for( ulong i=0; i<width; i++ ) {
      12           0 :     fd_bn254_scalar_add( &state[i], &state[i], &params->ark[ round * width + i ] );
      13           0 :   }
      14           0 : }
      15             : 
      16             : static inline void
      17             : fd_poseidon_apply_sbox_full( fd_bn254_scalar_t state[],
      18           0 :                              ulong const       width ) {
      19             :   /* Compute s[i]^5 */
      20           0 :   for( ulong i=0; i<width; i++ ) {
      21           0 :     fd_bn254_scalar_t t[1];
      22           0 :     fd_bn254_scalar_sqr( t, &state[i] );            /* t = s^2 */
      23           0 :     fd_bn254_scalar_sqr( t, t );                    /* t = s^4 */
      24           0 :     fd_bn254_scalar_mul( &state[i], &state[i], t ); /* s = s^5 */
      25           0 :   }
      26           0 : }
      27             : 
      28             : static inline void
      29           0 : fd_poseidon_apply_sbox_partial( fd_bn254_scalar_t state[] ) {
      30             :   /* Compute s[0]^5 */
      31           0 :   fd_poseidon_apply_sbox_full( state, 1 );
      32           0 : }
      33             : 
      34             : static inline void
      35             : fd_poseidon_apply_mds( fd_bn254_scalar_t   state[],
      36             :                        ulong const       width,
      37           0 :                        fd_poseidon_par_t const * params ) {
      38           0 :   fd_bn254_scalar_t x[FD_POSEIDON_MAX_WIDTH+1] = { 0 };
      39             :   /* Vector-matrix multiplication (state vector times mds matrix) */
      40           0 :   for( ulong i=0; i<width; i++ ) {
      41           0 :     for( ulong j=0; j<width; j++ ) {
      42           0 :       fd_bn254_scalar_t t[1];
      43           0 :       fd_bn254_scalar_mul( t, &state[j], &params->mds[ i * width + j ] );
      44           0 :       fd_bn254_scalar_add( &x[i], &x[i], t );
      45           0 :     }
      46           0 :   }
      47           0 :   for( ulong i=0; i<width; i++ ) {
      48           0 :     state[i] = x[i];
      49           0 :   }
      50           0 : }
      51             : 
      52             : static inline void
      53             : fd_poseidon_get_params( fd_poseidon_par_t * params,
      54           0 :                         ulong const         width ) {
      55           0 : #define FD_POSEIDON_GET_PARAMS(w) case (w):                \
      56           0 :   params->ark = (fd_bn254_scalar_t *)fd_poseidon_ark_## w; \
      57           0 :   params->mds = (fd_bn254_scalar_t *)fd_poseidon_mds_## w; \
      58           0 :   break
      59             : 
      60           0 :   switch( width ) {
      61           0 :   FD_POSEIDON_GET_PARAMS(2);
      62           0 :   FD_POSEIDON_GET_PARAMS(3);
      63           0 :   FD_POSEIDON_GET_PARAMS(4);
      64           0 :   FD_POSEIDON_GET_PARAMS(5);
      65           0 :   FD_POSEIDON_GET_PARAMS(6);
      66           0 :   FD_POSEIDON_GET_PARAMS(7);
      67           0 :   FD_POSEIDON_GET_PARAMS(8);
      68           0 :   FD_POSEIDON_GET_PARAMS(9);
      69           0 :   FD_POSEIDON_GET_PARAMS(10);
      70           0 :   FD_POSEIDON_GET_PARAMS(11);
      71           0 :   FD_POSEIDON_GET_PARAMS(12);
      72           0 :   FD_POSEIDON_GET_PARAMS(13);
      73           0 :   }
      74           0 : #undef FD_POSEIDON_GET_PARAMS
      75           0 : }
      76             : 
      77             : /* Poseidon interface */
      78             : 
      79             : fd_poseidon_t *
      80             : fd_poseidon_init( fd_poseidon_t * pos,
      81           0 :                   int const       big_endian ) {
      82           0 :   if( FD_UNLIKELY( pos==NULL ) ) {
      83           0 :     return NULL;
      84           0 :   }
      85           0 :   pos->big_endian = big_endian;
      86           0 :   pos->cnt = 0UL;
      87           0 :   fd_memset( pos->state, 0, sizeof(pos->state) );
      88           0 :   return pos;
      89           0 : }
      90             : 
      91             : fd_poseidon_t *
      92             : fd_poseidon_append( fd_poseidon_t * pos,
      93             :                     uchar const *   data,
      94           0 :                     ulong           sz ) {
      95           0 :   if( FD_UNLIKELY( pos==NULL ) ) {
      96           0 :     return NULL;
      97           0 :   }
      98           0 :   if( FD_UNLIKELY( pos->cnt >= FD_POSEIDON_MAX_WIDTH ) ) {
      99           0 :     return NULL;
     100           0 :   }
     101             :   /* Empty input and non-field are errors. Short element is extended with 0s. */
     102           0 :   if( FD_UNLIKELY( sz==0 || sz>32UL ) ) {
     103           0 :     return NULL;
     104           0 :   }
     105             : 
     106             :   /* Handle endianness */
     107           0 :   fd_bn254_scalar_t cur[1] = { 0 };
     108           0 :   fd_memcpy( cur->buf + (32-sz)*(pos->big_endian?1:0), data, sz );
     109           0 :   if( pos->big_endian ) {
     110           0 :     fd_uint256_bswap( cur, cur );
     111           0 :   }
     112             : 
     113           0 :   if( FD_UNLIKELY( !fd_bn254_scalar_validate( cur ) ) ) {
     114           0 :     return NULL;
     115           0 :   }
     116           0 :   pos->cnt++;
     117           0 :   fd_bn254_scalar_to_mont( &pos->state[ pos->cnt ], cur );
     118             : 
     119           0 :   return pos;
     120           0 : }
     121             : 
     122             : uchar *
     123             : fd_poseidon_fini( fd_poseidon_t * pos,
     124           0 :                   uchar           hash[ FD_POSEIDON_HASH_SZ ] ) {
     125           0 :   if( FD_UNLIKELY( pos==NULL ) ) {
     126           0 :     return NULL;
     127           0 :   }
     128           0 :   if( FD_UNLIKELY( !pos->cnt ) ) {
     129           0 :     return NULL;
     130           0 :   }
     131           0 :   const ulong width = pos->cnt+1;
     132           0 :   fd_poseidon_par_t params[1] = { 0 };
     133           0 :   fd_poseidon_get_params( params, width );
     134           0 :   if( FD_UNLIKELY( !params->ark || !params->mds ) ) {
     135           0 :     return NULL;
     136           0 :   }
     137             : 
     138           0 :   const ulong PARTIAL_ROUNDS[] = { 56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68 };
     139           0 :   const ulong partial_rounds = PARTIAL_ROUNDS[ pos->cnt-1 ];
     140           0 :   const ulong full_rounds = 8;
     141           0 :   const ulong half_rounds = full_rounds / 2;
     142           0 :   const ulong all_rounds = full_rounds + partial_rounds;
     143             : 
     144           0 :   ulong round=0;
     145           0 :   for (; round<half_rounds; round++ ) {
     146           0 :     fd_poseidon_apply_ark         ( pos->state, width, params, round );
     147           0 :     fd_poseidon_apply_sbox_full   ( pos->state, width );
     148           0 :     fd_poseidon_apply_mds         ( pos->state, width, params );
     149           0 :   }
     150             : 
     151           0 :   for (; round<half_rounds+partial_rounds; round++ ) {
     152           0 :     fd_poseidon_apply_ark         ( pos->state, width, params, round );
     153           0 :     fd_poseidon_apply_sbox_partial( pos->state );
     154           0 :     fd_poseidon_apply_mds         ( pos->state, width, params );
     155           0 :   }
     156             : 
     157           0 :   for (; round<all_rounds; round++ ) {
     158           0 :     fd_poseidon_apply_ark         ( pos->state, width, params, round );
     159           0 :     fd_poseidon_apply_sbox_full   ( pos->state, width );
     160           0 :     fd_poseidon_apply_mds         ( pos->state, width, params );
     161           0 :   }
     162             : 
     163             :   /* Directly convert scalar into return hash buffer - hash MUST be FD_UINT256_ALIGNED */
     164           0 :   fd_bn254_scalar_t scalar_hash[1];
     165           0 :   fd_bn254_scalar_from_mont( scalar_hash, &pos->state[0] );
     166           0 :   if( pos->big_endian ) {
     167           0 :     fd_uint256_bswap( scalar_hash, scalar_hash );
     168           0 :   }
     169           0 :   fd_memcpy( hash, scalar_hash, 32 );
     170           0 :   return hash;
     171           0 : }

Generated by: LCOV version 1.14