LCOV - code coverage report
Current view: top level - choreo/votor - ag_cert_serde.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 130 134 97.0 %
Date: 2026-09-17 04:28:31 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "ag_cert_serde.h"
       2             : 
       3             : #include "../../ballet/bls/fd_bls12_381.h" /* fd_bls12_381_g2_add_syscall */
       4             : 
       5         672 : #define FAIL( cond, err ) do { if( FD_UNLIKELY( cond ) ) return AG_CERT_DE_ERR_##err; } while( 0 )
       6             : 
       7             : ulong
       8             : ag_cert_ser( ag_cert_t const * self,
       9          75 :              uchar             buf[ static AG_CERT_SER_MAX ] ) {
      10          75 :   fd_bls_agg_t const * agg;
      11          75 :   fd_bls_agg_t const * agg2 = NULL;
      12          75 :   uchar const *        hash = NULL;
      13          75 :   ulong                slot;
      14          75 :   switch( self->kind ) {
      15          12 :   case AG_CERT_KIND_FINAL:
      16          12 :     slot = self->final.slot;
      17          12 :     agg  = &self->final.agg;
      18          12 :     break;
      19          12 :   case AG_CERT_KIND_FAST_FINAL:
      20          12 :     slot = self->fast_final.slot;
      21          12 :     agg  = &self->fast_final.agg;
      22          12 :     hash = self->fast_final.block_hash;
      23          12 :     break;
      24           9 :   case AG_CERT_KIND_NOTAR:
      25           9 :     slot = self->notar.slot;
      26           9 :     agg  = &self->notar.agg;
      27           9 :     hash = self->notar.block_hash;
      28           9 :     break;
      29          24 :   case AG_CERT_KIND_NOTAR_FALLBACK:
      30          24 :     slot = self->notar_fallback.slot;
      31          24 :     agg  = &self->notar_fallback.agg_notar;
      32          24 :     agg2 = &self->notar_fallback.agg_notar_fallback;
      33          24 :     hash = self->notar_fallback.block_hash;
      34          24 :     break;
      35          18 :   case AG_CERT_KIND_SKIP:
      36          18 :     slot = self->skip.slot;
      37          18 :     agg  = &self->skip.agg_skip;
      38          18 :     agg2 = &self->skip.agg_skip_fallback;
      39          18 :     break;
      40           0 :   default:
      41           0 :     FD_LOG_ERR(( "unimplemented" ));
      42          75 :   }
      43             : 
      44          75 :   if( FD_UNLIKELY( agg2 && !fd_bls_set_cnt( agg2->set ) ) ) agg2 = NULL; /* check empty */
      45             : 
      46          75 :   fd_bls_sig_t sig = agg->sig;
      47          75 :   if( FD_UNLIKELY( agg2 ) ) blst_p2_add_or_double( &sig, &sig, &agg2->sig );
      48             : 
      49          75 :   ag_cert_serde_t cert = {
      50          75 :     .version       = (uchar)1,
      51          75 :     .tag           = (uchar)( self->kind+AG_CERT_SERDE_TAG_FINAL ),
      52          75 :     .slot          = slot,
      53          75 :     .block_id      = hash,
      54          75 :     .bitmap_sz     = agg2 ? ag_bls_agg_pair_ser_sz( agg, agg2 ) : ag_bls_agg_ser_sz( agg ),
      55          75 :     .shred_version = ag_cert_shred_version( self ),
      56          75 :   };
      57             : 
      58          75 :   ulong off = 0UL;
      59          75 :   buf[ off ] = cert.version;                                                                    off += sizeof(uchar);
      60          75 :   buf[ off ] = cert.tag;                                                                        off += sizeof(uchar);
      61          75 :   FD_STORE( ulong, buf+off, cert.slot );                                                        off += sizeof(ulong);
      62          75 :   if( FD_LIKELY( cert.block_id ) ) { memcpy( buf+off, cert.block_id, sizeof(ag_block_hash_t) ); off += sizeof(ag_block_hash_t); }
      63          75 :   blst_p2_affine sig_aff[1];
      64          75 :   blst_p2_to_affine( sig_aff, &sig );
      65          75 :   blst_p2_affine_serialize( buf+off, sig_aff );                                                 off += FD_BLS_SIG_SZ;
      66          75 :   FD_STORE( ulong, buf+off, cert.bitmap_sz );                                                   off += sizeof(ulong);
      67          75 :                                                                                                 off += agg2 ? ag_bls_agg_pair_ser( agg, agg2, buf+off ) : ag_bls_agg_ser( agg, buf+off );
      68          75 :   FD_STORE( ushort, buf+off, cert.shred_version );                                              off += sizeof(ushort);
      69             : 
      70          75 :   return off;
      71          75 : }
      72             : 
      73             : int
      74             : ag_cert_de( ag_cert_t *   self,
      75             :             uchar const * buf,
      76          96 :             ulong         buf_sz ) {
      77          96 :   FAIL( buf_sz<2 /* version + tag */, SZ );
      78             : 
      79          96 :   ag_cert_serde_t cert; ulong off = 0UL;
      80          96 :   cert.version       = buf[ off ];                off += sizeof(uchar);
      81          96 :   cert.tag           = buf[ off ];                off += sizeof(uchar);
      82          96 :   FAIL( cert.version!=1, INVAL );
      83             : 
      84          96 :   fd_memset( self, 0, sizeof(ag_cert_t) );
      85          96 :   self->kind = (uint)cert.tag - AG_CERT_SERDE_TAG_FINAL;
      86             : 
      87          96 :   int   has_block_id = self->kind==AG_CERT_KIND_FAST_FINAL || self->kind==AG_CERT_KIND_NOTAR || self->kind==AG_CERT_KIND_NOTAR_FALLBACK;
      88          96 :   ulong hdr_sz       = AG_CERT_SER_HDR_SZ( has_block_id );
      89          96 :   FAIL( buf_sz<hdr_sz, SZ );
      90             : 
      91          96 :   cert.slot          = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
      92          96 :   cert.block_id      = NULL;
      93          96 :   if( FD_LIKELY( has_block_id ) ) {
      94          54 :     cert.block_id    = buf+off;                   off += sizeof(ag_block_hash_t);
      95          54 :   }
      96          96 :   cert.signature     = buf+off;                   off += FD_BLS_SIG_SZ;
      97             : 
      98          96 :   fd_bls_sig_t   sig[1];
      99          96 :   blst_p2_affine sig_aff[1];
     100          96 :   FAIL( cert.signature[0]&0xA0U,                                      INVAL );
     101          96 :   FAIL( blst_p2_deserialize( sig_aff, cert.signature )!=BLST_SUCCESS, INVAL );
     102          96 :   FAIL( !blst_p2_affine_in_g2( sig_aff ),                             INVAL );
     103          96 :   blst_p2_from_affine( sig, sig_aff );
     104          96 :   cert.bitmap_sz     = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
     105          96 :   cert.bitmap        = buf+off;
     106          96 :   FD_TEST( off==hdr_sz );
     107             : 
     108          96 :   ulong rem = buf_sz - hdr_sz;
     109          96 :   FAIL( cert.bitmap_sz>rem || rem-cert.bitmap_sz!=sizeof(ushort), SZ ); /* too few, or trailing bytes */
     110             : 
     111          42 :   cert.shred_version = FD_LOAD( ushort, cert.bitmap+cert.bitmap_sz );
     112             : 
     113          42 :   int err;
     114          42 :   switch( self->kind ) {
     115           6 :   case AG_CERT_KIND_FINAL:
     116           6 :     self->final.slot = cert.slot;
     117           6 :     self->final.shred_version = cert.shred_version;
     118           6 :     if( FD_UNLIKELY( err = ag_bls_agg_de( &self->final.agg, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     119           6 :     self->final.agg.sig = *sig;
     120           6 :     break;
     121           6 :   case AG_CERT_KIND_FAST_FINAL:
     122           6 :     self->fast_final.slot = cert.slot;
     123           6 :     self->fast_final.shred_version = cert.shred_version;
     124           6 :     memcpy( self->fast_final.block_hash, cert.block_id, sizeof(ag_block_hash_t) );
     125           6 :     if( FD_UNLIKELY( err = ag_bls_agg_de( &self->fast_final.agg, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     126           6 :     self->fast_final.agg.sig = *sig;
     127           6 :     break;
     128           6 :   case AG_CERT_KIND_NOTAR:
     129           6 :     self->notar.slot = cert.slot;
     130           6 :     self->notar.shred_version = cert.shred_version;
     131           6 :     memcpy( self->notar.block_hash, cert.block_id, sizeof(ag_block_hash_t) );
     132           6 :     if( FD_UNLIKELY( err = ag_bls_agg_de( &self->notar.agg, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     133           6 :     self->notar.agg.sig = *sig;
     134           6 :     break;
     135          12 :   case AG_CERT_KIND_NOTAR_FALLBACK: {
     136          12 :     fd_bls_agg_t * agg  = &self->notar_fallback.agg_notar;
     137          12 :     fd_bls_agg_t * agg2 = &self->notar_fallback.agg_notar_fallback;
     138          12 :     self->notar_fallback.slot = cert.slot;
     139          12 :     self->notar_fallback.shred_version = cert.shred_version;
     140          12 :     memcpy( self->notar_fallback.block_hash, cert.block_id, sizeof(ag_block_hash_t) );
     141          12 :     if( FD_UNLIKELY( err = ag_bls_agg_pair_de( agg, agg2, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     142          12 :     agg->sig = *sig;
     143          12 :     break;
     144          12 :   }
     145          12 :   case AG_CERT_KIND_SKIP: {
     146          12 :     fd_bls_agg_t * agg  = &self->skip.agg_skip;
     147          12 :     fd_bls_agg_t * agg2 = &self->skip.agg_skip_fallback;
     148          12 :     self->skip.slot = cert.slot;
     149          12 :     self->skip.shred_version = cert.shred_version;
     150          12 :     if( FD_UNLIKELY( err = ag_bls_agg_pair_de( agg, agg2, cert.bitmap, cert.bitmap_sz ) ) ) return err;
     151          12 :     agg->sig = *sig;
     152          12 :     break;
     153          12 :   }
     154           0 :   default:
     155           0 :     return AG_CERT_DE_ERR_INVAL;
     156          42 :   }
     157             : 
     158          42 :   return AG_CERT_DE_SUCCESS;
     159          42 : }

Generated by: LCOV version 1.14