LCOV - code coverage report
Current view: top level - choreo/votor - fd_cert_serde.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 128 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include "fd_cert_serde.h"
       2             : 
       3           0 : #define FAIL( cond, err ) do { if( FD_UNLIKELY( cond ) ) return FD_CERT_DE_ERR_##err; } while( 0 )
       4             : 
       5             : ulong
       6             : fd_cert_ser( fd_cert_t const * self,
       7           0 :              uchar             buf[ static FD_CERT_SER_MAX ] ) {
       8           0 :   fd_bls_agg_t const * agg;
       9           0 :   fd_bls_agg_t const * agg2 = NULL;
      10           0 :   uchar const *        hash = NULL;
      11           0 :   ulong                slot;
      12           0 :   switch( self->kind ) {
      13           0 :   case FD_CERT_KIND_FINAL:
      14           0 :     slot = self->final.slot;
      15           0 :     agg  = &self->final.agg;
      16           0 :     break;
      17           0 :   case FD_CERT_KIND_FAST_FINAL:
      18           0 :     slot = self->fast_final.slot;
      19           0 :     agg  = &self->fast_final.agg;
      20           0 :     hash = self->fast_final.block_hash.uc;
      21           0 :     break;
      22           0 :   case FD_CERT_KIND_NOTAR:
      23           0 :     slot = self->notar.slot;
      24           0 :     agg  = &self->notar.agg;
      25           0 :     hash = self->notar.block_hash.uc;
      26           0 :     break;
      27           0 :   case FD_CERT_KIND_NOTAR_FALLBACK:
      28           0 :     slot = self->notar_fallback.slot;
      29           0 :     agg  = &self->notar_fallback.agg_notar;
      30           0 :     agg2 = &self->notar_fallback.agg_notar_fallback;
      31           0 :     hash = self->notar_fallback.block_hash.uc;
      32           0 :     break;
      33           0 :   case FD_CERT_KIND_SKIP:
      34           0 :     slot = self->skip.slot;
      35           0 :     agg  = &self->skip.agg_skip;
      36           0 :     agg2 = &self->skip.agg_skip_fallback;
      37           0 :     break;
      38           0 :   default:
      39           0 :     FD_LOG_ERR(( "unimplemented" ));
      40           0 :   }
      41             : 
      42           0 :   if( FD_UNLIKELY( agg2 && !fd_bls_set_cnt( agg2->set ) ) ) agg2 = NULL; /* check empty */
      43             : 
      44           0 :   fd_bls_sig_t sig = agg->sig;
      45           0 :   if( FD_UNLIKELY( agg2 ) ) fd_bls_sig_add( &sig, &sig, &agg2->sig );
      46             : 
      47           0 :   fd_cert_serde_t cert = {
      48           0 :     .version       = (uchar)1,
      49           0 :     .tag           = (uchar)( self->kind+FD_CERT_SERDE_TAG_FINAL ),
      50           0 :     .slot          = slot,
      51           0 :     .block_id      = hash,
      52           0 :     .bitmap_sz     = agg2 ? fd_bls_agg_pair_ser_sz( agg, agg2 ) : fd_bls_agg_ser_sz( agg ),
      53           0 :     .shred_version = fd_cert_shred_version( self ),
      54           0 :   };
      55             : 
      56           0 :   ulong off = 0UL;
      57           0 :   buf[ off ] = cert.version;                                                                    off += sizeof(uchar);
      58           0 :   buf[ off ] = cert.tag;                                                                        off += sizeof(uchar);
      59           0 :   FD_STORE( ulong, buf+off, cert.slot );                                                        off += sizeof(ulong);
      60           0 :   if( FD_LIKELY( cert.block_id ) ) { memcpy( buf+off, cert.block_id, sizeof(fd_block_hash_t) ); off += sizeof(fd_block_hash_t); }
      61           0 :   fd_bls_sig_ser( &sig, buf+off );                                                              off += FD_BLS_SIG_SZ;
      62           0 :   FD_STORE( ulong, buf+off, cert.bitmap_sz );                                                   off += sizeof(ulong);
      63           0 :                                                                                                 off += agg2 ? fd_bls_agg_pair_ser( agg, agg2, buf+off ) : fd_bls_agg_ser( agg, buf+off );
      64           0 :   FD_STORE( ushort, buf+off, cert.shred_version );                                              off += sizeof(ushort);
      65             : 
      66           0 :   return off;
      67           0 : }
      68             : 
      69             : int
      70             : fd_cert_de( fd_cert_t *   self,
      71             :             ulong *       bit_cnt,
      72             :             uchar const * buf,
      73           0 :             ulong         buf_sz ) {
      74           0 :   FAIL( buf_sz<2 /* version + tag */, SZ );
      75             : 
      76           0 :   fd_cert_serde_t cert; ulong off = 0UL;
      77           0 :   cert.version       = buf[ off ];                off += sizeof(uchar);
      78           0 :   cert.tag           = buf[ off ];                off += sizeof(uchar);
      79           0 :   FAIL( cert.version!=1, INVAL );
      80             : 
      81           0 :   fd_memset( self, 0, sizeof(fd_cert_t) );
      82           0 :   self->kind = (uint)cert.tag - FD_CERT_SERDE_TAG_FINAL;
      83             : 
      84           0 :   int   has_block_id = self->kind==FD_CERT_KIND_FAST_FINAL || self->kind==FD_CERT_KIND_NOTAR || self->kind==FD_CERT_KIND_NOTAR_FALLBACK;
      85           0 :   ulong hdr_sz       = FD_CERT_SER_HDR_SZ( has_block_id );
      86           0 :   FAIL( buf_sz<hdr_sz, SZ );
      87             : 
      88           0 :   cert.slot          = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
      89           0 :   cert.block_id      = NULL;
      90           0 :   if( FD_LIKELY( has_block_id ) ) {
      91           0 :     cert.block_id    = buf+off;                   off += sizeof(fd_block_hash_t);
      92           0 :   }
      93           0 :   cert.signature     = buf+off;                   off += FD_BLS_SIG_SZ;
      94             : 
      95           0 :   fd_bls_sig_t sig[1];
      96           0 :   FAIL( fd_bls_sig_de_unchecked( sig, cert.signature ), INVAL ); /* deserialize now, defer the g2 subgroup check to verify */
      97           0 :   cert.bitmap_sz     = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
      98           0 :   cert.bitmap        = buf+off;
      99           0 :   FD_TEST( off==hdr_sz );
     100             : 
     101           0 :   ulong rem = buf_sz - hdr_sz;
     102           0 :   FAIL( cert.bitmap_sz>rem || rem-cert.bitmap_sz<sizeof(ushort), SZ ); /* too few, trailing bytes are ignored */
     103             : 
     104           0 :   cert.shred_version = FD_LOAD( ushort, cert.bitmap+cert.bitmap_sz );
     105             : 
     106           0 :   int err;
     107           0 :   switch( self->kind ) {
     108           0 :   case FD_CERT_KIND_FINAL:
     109           0 :     self->final.slot = cert.slot;
     110           0 :     self->final.shred_version = cert.shred_version;
     111           0 :     if( FD_UNLIKELY( err = fd_bls_agg_de( &self->final.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     112           0 :     self->final.agg.sig = *sig;
     113           0 :     break;
     114           0 :   case FD_CERT_KIND_FAST_FINAL:
     115           0 :     self->fast_final.slot = cert.slot;
     116           0 :     self->fast_final.shred_version = cert.shred_version;
     117           0 :     memcpy( &self->fast_final.block_hash, cert.block_id, sizeof(fd_block_hash_t) );
     118           0 :     if( FD_UNLIKELY( err = fd_bls_agg_de( &self->fast_final.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     119           0 :     self->fast_final.agg.sig = *sig;
     120           0 :     break;
     121           0 :   case FD_CERT_KIND_NOTAR:
     122           0 :     self->notar.slot = cert.slot;
     123           0 :     self->notar.shred_version = cert.shred_version;
     124           0 :     memcpy( &self->notar.block_hash, cert.block_id, sizeof(fd_block_hash_t) );
     125           0 :     if( FD_UNLIKELY( err = fd_bls_agg_de( &self->notar.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     126           0 :     self->notar.agg.sig = *sig;
     127           0 :     break;
     128           0 :   case FD_CERT_KIND_NOTAR_FALLBACK: {
     129           0 :     fd_bls_agg_t * agg  = &self->notar_fallback.agg_notar;
     130           0 :     fd_bls_agg_t * agg2 = &self->notar_fallback.agg_notar_fallback;
     131           0 :     self->notar_fallback.slot = cert.slot;
     132           0 :     self->notar_fallback.shred_version = cert.shred_version;
     133           0 :     memcpy( &self->notar_fallback.block_hash, cert.block_id, sizeof(fd_block_hash_t) );
     134           0 :     if( FD_UNLIKELY( err = fd_bls_agg_pair_de( agg, agg2, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     135           0 :     agg->sig = *sig;
     136           0 :     break;
     137           0 :   }
     138           0 :   case FD_CERT_KIND_SKIP: {
     139           0 :     fd_bls_agg_t * agg  = &self->skip.agg_skip;
     140           0 :     fd_bls_agg_t * agg2 = &self->skip.agg_skip_fallback;
     141           0 :     self->skip.slot = cert.slot;
     142           0 :     self->skip.shred_version = cert.shred_version;
     143           0 :     if( FD_UNLIKELY( err = fd_bls_agg_pair_de( agg, agg2, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     144           0 :     agg->sig = *sig;
     145           0 :     break;
     146           0 :   }
     147           0 :   default:
     148           0 :     return FD_CERT_DE_ERR_INVAL;
     149           0 :   }
     150             : 
     151           0 :   return FD_CERT_DE_SUCCESS;
     152           0 : }

Generated by: LCOV version 1.14