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

          Line data    Source code
       1             : #include "fd_cert.h"
       2             : 
       3             : #include "fd_vote_serde.h" /* fd_vote_signing_ser */
       4             : 
       5             : static int
       6             : is_signer( fd_cert_t const * self,
       7           0 :            ulong             rank ) {
       8           0 :   switch( self->kind ) {
       9           0 :   case FD_CERT_KIND_FINAL:          return fd_bls_set_test( self->final.agg.set,               rank );
      10           0 :   case FD_CERT_KIND_FAST_FINAL:     return fd_bls_set_test( self->fast_final.agg.set,          rank );
      11           0 :   case FD_CERT_KIND_NOTAR:          return fd_bls_set_test( self->notar.agg.set,               rank );
      12           0 :   case FD_CERT_KIND_NOTAR_FALLBACK: return fd_bls_set_test( self->notar_fallback.agg_notar.set, rank ) || fd_bls_set_test( self->notar_fallback.agg_notar_fallback.set, rank );
      13           0 :   case FD_CERT_KIND_SKIP:           return fd_bls_set_test( self->skip.agg_skip.set,            rank ) || fd_bls_set_test( self->skip.agg_skip_fallback.set,            rank );
      14           0 :   default:                          FD_LOG_CRIT(( "unreachable" ));
      15           0 :   }
      16           0 : }
      17             : 
      18             : /* each validator is counted once even if in both partitions */
      19             : 
      20             : static int
      21             : check_threshold( fd_cert_t const *       self,
      22           0 :                  fd_epoch_info_t const * epoch_info ) {
      23           0 :   fd_validator_info_t const * validators = fd_epoch_info_validators( epoch_info );
      24           0 :   ulong                       stake      = 0UL;
      25           0 :   for( ulong i=0UL; i<epoch_info->validator_cnt; i++ ) if( FD_LIKELY( is_signer( self, validators[i].id ) ) ) stake += validators[i].stake;
      26           0 :   return fd_int_if( self->kind==FD_CERT_KIND_FAST_FINAL,
      27           0 :                     fd_epoch_info_is_strong_quorum( epoch_info, stake ),
      28           0 :                     fd_epoch_info_is_quorum       ( epoch_info, stake ) );
      29           0 : }
      30             : 
      31             : /* TODO sum all the pubkeys on advance_epoch and subtract instead? */
      32             : 
      33             : static int
      34             : pub_sum( fd_bls_pub_t *          pub,
      35             :          fd_bls_set_t const *    set,
      36           0 :          fd_epoch_info_t const * epoch_info ) {
      37           0 :   memset( pub, 0, sizeof(fd_bls_pub_t) ); /* zero is the point at infinity */
      38           0 :   if( FD_UNLIKELY( fd_bls_set_cnt( set ) &&
      39           0 :                    fd_bls_set_last( set )>=epoch_info->validator_cnt ) ) return -1;
      40           0 :   fd_bls_pub_sum( pub, epoch_info->pubkeys, set );
      41           0 :   return 0;
      42           0 : }
      43             : 
      44             : static int
      45             : check_sig_one( fd_bls_agg_t const *    agg,
      46             :                uint                    kind,
      47             :                ulong                   slot,
      48             :                fd_block_hash_t const * block_hash,
      49             :                fd_epoch_info_t const * epoch_info,
      50           0 :                ushort                  shred_version ) {
      51           0 :   fd_bls_pub_t pub[1];
      52           0 :   if( FD_UNLIKELY( pub_sum( pub, agg->set, epoch_info ) ) ) return 0;
      53           0 :   uchar buf[ FD_VOTE_SIGNING_SER_MAX ];
      54           0 :   ulong sz = fd_vote_signing_ser( kind, slot, block_hash, shred_version, buf );
      55           0 :   if( FD_UNLIKELY( !fd_bls_sig_validate( &agg->sig ) ) ) return 0; /* deferred g2 subgroup check */
      56           0 :   return fd_bls_agg_verify( buf, sz, pub, &agg->sig );
      57           0 : }
      58             : 
      59             : static int
      60             : check_sig_pair( fd_bls_agg_t const *    agg,
      61             :                 uint                    kind,
      62             :                 fd_bls_agg_t const *    agg_fb,
      63             :                 uint                    kind_fb,
      64             :                 ulong                   slot,
      65             :                 fd_block_hash_t const * block_hash,
      66             :                 fd_epoch_info_t const * epoch_info,
      67           0 :                 ushort                  shred_version ) {
      68           0 :   fd_bls_pub_t pub[1], pub_fb[1];
      69           0 :   if( FD_UNLIKELY( pub_sum( pub, agg->set, epoch_info ) || pub_sum( pub_fb, agg_fb->set, epoch_info ) ) ) return 0;
      70           0 :   fd_bls_sig_t sig[1];
      71           0 :   fd_bls_sig_add( sig, &agg->sig, &agg_fb->sig );
      72           0 :   if( FD_UNLIKELY( !fd_bls_sig_validate( sig ) ) ) return 0; /* deferred g2 subgroup check */
      73           0 :   uchar buf   [ FD_VOTE_SIGNING_SER_MAX ]; ulong sz    = fd_vote_signing_ser( kind,    slot, block_hash, shred_version, buf    );
      74           0 :   uchar buf_fb[ FD_VOTE_SIGNING_SER_MAX ]; ulong sz_fb = fd_vote_signing_ser( kind_fb, slot, block_hash, shred_version, buf_fb );
      75           0 :   if( FD_LIKELY  ( fd_bls_set_is_null( agg_fb->set ) ) ) return fd_bls_agg_verify( buf,    sz,    pub,    sig ); /* one partition is the common case */
      76           0 :   if( FD_UNLIKELY( fd_bls_set_is_null( agg->set    ) ) ) return fd_bls_agg_verify( buf_fb, sz_fb, pub_fb, sig );
      77           0 :   return fd_bls_agg_verify_pair( buf, sz, pub, buf_fb, sz_fb, pub_fb, sig );
      78           0 : }
      79             : 
      80             : static int
      81             : check_sig( fd_cert_t const *       self,
      82           0 :            fd_epoch_info_t const * epoch_info ) {
      83           0 :   switch( self->kind ) {
      84           0 :   case FD_CERT_KIND_FINAL:      return check_sig_one( &self->final.agg,      FD_VOTE_KIND_FINAL, self->final.slot,      NULL,                         epoch_info, self->final.shred_version      );
      85           0 :   case FD_CERT_KIND_FAST_FINAL: return check_sig_one( &self->fast_final.agg, FD_VOTE_KIND_NOTAR, self->fast_final.slot, &self->fast_final.block_hash, epoch_info, self->fast_final.shred_version );
      86           0 :   case FD_CERT_KIND_NOTAR:      return check_sig_one( &self->notar.agg,      FD_VOTE_KIND_NOTAR, self->notar.slot,      &self->notar.block_hash,      epoch_info, self->notar.shred_version      );
      87           0 :   case FD_CERT_KIND_NOTAR_FALLBACK: {
      88           0 :     fd_cert_notar_fallback_t const * nf = &self->notar_fallback;
      89           0 :     return check_sig_pair( &nf->agg_notar, FD_VOTE_KIND_NOTAR, &nf->agg_notar_fallback, FD_VOTE_KIND_NOTAR_FALLBACK, nf->slot, &nf->block_hash, epoch_info, nf->shred_version );
      90           0 :   }
      91           0 :   case FD_CERT_KIND_SKIP: {
      92           0 :     fd_cert_skip_t const * skip = &self->skip;
      93           0 :     return check_sig_pair( &skip->agg_skip, FD_VOTE_KIND_SKIP, &skip->agg_skip_fallback, FD_VOTE_KIND_SKIP_FALLBACK, skip->slot, NULL, epoch_info, skip->shred_version );
      94           0 :   }
      95           0 :   default:
      96           0 :     FD_LOG_CRIT(( "unreachable" ));
      97           0 :   }
      98           0 : }
      99             : 
     100             : int
     101             : fd_cert_verify( fd_cert_t const *       self,
     102           0 :                 fd_epoch_info_t const * epoch_info ) {
     103           0 :   if( FD_UNLIKELY( !check_threshold( self, epoch_info ) ) ) return FD_CERT_VERIFY_ERR_THRESHOLD;
     104           0 :   if( FD_UNLIKELY( !check_sig      ( self, epoch_info ) ) ) return FD_CERT_VERIFY_ERR_SIG;
     105           0 :   return FD_CERT_VERIFY_SUCCESS;
     106           0 : }

Generated by: LCOV version 1.14