LCOV - code coverage report
Current view: top level - choreo/votor - test_ag_cert_builder.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 126 129 97.7 %
Date: 2026-09-17 04:28:31 Functions: 26 45 57.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_choreo_votor_test_ag_cert_builder_h
       2             : #define HEADER_fd_src_choreo_votor_test_ag_cert_builder_h
       3             : 
       4             : /* Certificates are built incrementally in ag_slot_state.c as votes
       5             :    arrive.  These rebuild one from a complete vote list, which tests
       6             :    need to get a cert in isolation; they are not part of the ag_cert
       7             :    API. */
       8             : 
       9             : #include "ag_cert.h"
      10             : #include "ag_epoch_info.h"
      11             : #include "ag_vote.h"
      12             : 
      13             : /* epoch_info_build fills epoch_info from an already ranked validator
      14             :    list.  Production ranks in the votor tile (rank_voters). */
      15             : 
      16             : static inline void
      17             : epoch_info_build( ag_epoch_info_t *           epoch_info,
      18             :                   ag_validator_info_t const * validators,
      19         279 :                   ulong                       validator_cnt ) {
      20         279 :   epoch_info->total_stake = 0UL;
      21        4704 :   for( ulong i=0UL; i<validator_cnt; i++ ) {
      22        4425 :     FD_TEST( validators[i].id==i );
      23        4425 :     epoch_info->validators[i] = validators[i];
      24        4425 :     epoch_info->pubkeys[i]    = validators[i].bls_key;
      25        4425 :     epoch_info->total_stake  += validators[i].stake;
      26        4425 :   }
      27         279 :   epoch_info->validator_cnt = validator_cnt;
      28         279 : }
      29             : 
      30             : /* sec_sign_fn is the fd_bls_sign_fn of a test that holds the secret
      31             :    key in memory; ctx points to the fd_bls_sec_t. */
      32             : 
      33             : static inline void
      34             : sec_sign_fn( void *         ctx,
      35             :              fd_bls_sig_t * sig,
      36             :              uchar const *  msg,
      37        8670 :              ulong          msg_sz ) {
      38        8670 :   fd_bls_sec_sign( (fd_bls_sec_t const *)ctx, msg, msg_sz, sig );
      39        8670 : }
      40             : 
      41             : static inline void
      42             : agg_add( fd_bls_agg_t *       agg,
      43             :          ulong                rank,
      44        4020 :          fd_bls_sig_t const * sig ) {
      45        4020 :   fd_bls_set_insert( agg->set, rank );
      46        4020 :   blst_p2_add_or_double( &agg->sig, &agg->sig, sig );
      47        4020 : }
      48             : 
      49             : static inline int
      50         234 : agg_is_identity( fd_bls_agg_t const * agg ) {
      51         234 :   return !!blst_p2_is_inf( &agg->sig );
      52         234 : }
      53             : 
      54             : static inline ag_cert_t
      55             : cert_build_final( ag_vote_final_t const * votes, ulong vote_cnt, ag_epoch_info_t const * epoch_info );
      56             : static inline ag_cert_t
      57             : cert_build_fast_final( ag_vote_notar_t const * votes, ulong vote_cnt, ag_epoch_info_t const * epoch_info );
      58             : static inline ag_cert_t
      59             : cert_build_notar( ag_vote_notar_t const * votes, ulong vote_cnt, ag_epoch_info_t const * epoch_info );
      60             : static inline ag_cert_t
      61             : cert_build_notar_fallback( ag_vote_notar_t const * votes, ulong vote_cnt, ag_vote_notar_fallback_t const * fallback_votes, ulong fallback_vote_cnt, ag_epoch_info_t const * epoch_info );
      62             : static inline ag_cert_t
      63             : cert_build_skip( ag_vote_skip_t const * votes, ulong vote_cnt, ag_vote_skip_fallback_t const * fallback_votes, ulong fallback_vote_cnt, ag_epoch_info_t const * epoch_info );
      64             : 
      65             : static inline ag_cert_t
      66             : cert_build_final( ag_vote_final_t const * votes,
      67             :                   ulong                   vote_cnt,
      68          24 :                   ag_epoch_info_t const * epoch_info ) {
      69          24 :   ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
      70          24 :   FD_TEST( vote_cnt>0UL );
      71          24 :   ulong slot  = votes[0].slot;
      72          24 :   ulong stake = 0UL;
      73         462 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
      74         438 :     FD_TEST( votes[i].slot==slot );
      75         438 :     stake += validators[ votes[i].rank ].stake;
      76         438 :   }
      77          24 :   ag_cert_final_t cert;
      78          24 :   cert.slot = slot; cert.stake = stake; cert.shred_version = votes[0].shred_version;
      79          24 :   memset( &cert.agg, 0, sizeof(fd_bls_agg_t) );
      80         462 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg, votes[i].rank, &votes[i].sig );
      81          24 :   return (ag_cert_t){ .kind = AG_CERT_KIND_FINAL, .final = cert };
      82          24 : }
      83             : 
      84             : static inline ag_cert_t
      85             : cert_build_fast_final( ag_vote_notar_t const * votes,
      86             :                        ulong                   vote_cnt,
      87         102 :                        ag_epoch_info_t const * epoch_info ) {
      88         102 :   ag_cert_notar_t      notar = cert_build_notar( votes, vote_cnt, epoch_info ).notar;
      89         102 :   ag_cert_fast_final_t cert;
      90         102 :   cert.slot = notar.slot; cert.stake = notar.stake; cert.agg = notar.agg; cert.shred_version = notar.shred_version;
      91         102 :   memcpy( cert.block_hash, notar.block_hash, sizeof(ag_block_hash_t) );
      92         102 :   return (ag_cert_t){ .kind = AG_CERT_KIND_FAST_FINAL, .fast_final = cert };
      93         102 : }
      94             : 
      95             : static inline ag_cert_t
      96             : cert_build_notar( ag_vote_notar_t const * votes,
      97             :                   ulong                   vote_cnt,
      98         150 :                   ag_epoch_info_t const * epoch_info ) {
      99         150 :   ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
     100         150 :   FD_TEST( vote_cnt>0UL );
     101         150 :   ulong           slot  = votes[0].slot;
     102         150 :   ulong           stake = 0UL;
     103         150 :   ag_block_hash_t block_hash;
     104         150 :   memcpy( block_hash, votes[0].block_hash, sizeof(ag_block_hash_t) );
     105        2142 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     106        1992 :     FD_TEST( votes[i].slot==slot );
     107        1992 :     FD_TEST( !memcmp( votes[i].block_hash, block_hash, sizeof(ag_block_hash_t) ) );
     108        1992 :     stake += validators[ votes[i].rank ].stake;
     109        1992 :   }
     110         150 :   ag_cert_notar_t cert;
     111         150 :   cert.slot = slot; cert.stake = stake; cert.shred_version = votes[0].shred_version;
     112         150 :   memcpy( cert.block_hash, block_hash, sizeof(ag_block_hash_t) );
     113         150 :   memset( &cert.agg, 0, sizeof(fd_bls_agg_t) );
     114        2142 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg, votes[i].rank, &votes[i].sig );
     115         150 :   return (ag_cert_t){ .kind = AG_CERT_KIND_NOTAR, .notar = cert };
     116         150 : }
     117             : 
     118             : static inline ag_cert_t
     119             : cert_build_notar_fallback( ag_vote_notar_t const *          votes,
     120             :                            ulong                            vote_cnt,
     121             :                            ag_vote_notar_fallback_t const * fallback_votes,
     122             :                            ulong                            fallback_vote_cnt,
     123          42 :                            ag_epoch_info_t const *          epoch_info ) {
     124          42 :   ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
     125          42 :   FD_TEST( vote_cnt>0UL || fallback_vote_cnt>0UL );
     126          42 :   ulong           slot;
     127          42 :   ag_block_hash_t block_hash;
     128          42 :   if( vote_cnt>0UL ) { slot = votes[0].slot;                   memcpy( block_hash, votes[0].block_hash,                   sizeof(ag_block_hash_t) ); }
     129           6 :   else               { slot = fallback_votes[0].slot; memcpy( block_hash, fallback_votes[0].block_hash, sizeof(ag_block_hash_t) ); }
     130             : 
     131          42 :   ulong stake = 0UL;
     132         222 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     133         180 :     FD_TEST( votes[i].slot==slot );
     134         180 :     FD_TEST( !memcmp( votes[i].block_hash, block_hash, sizeof(ag_block_hash_t) ) );
     135         180 :     stake += validators[ votes[i].rank ].stake;
     136         180 :   }
     137          42 :   ulong stake_fallback = 0UL;
     138         468 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) {
     139         426 :     FD_TEST( fallback_votes[i].slot==slot );
     140         426 :     FD_TEST( !memcmp( fallback_votes[i].block_hash, block_hash, sizeof(ag_block_hash_t) ) );
     141         426 :     stake_fallback += validators[ fallback_votes[i].rank ].stake;
     142         426 :   }
     143             : 
     144          42 :   ag_cert_notar_fallback_t cert;
     145          42 :   cert.slot = slot; cert.shred_version = vote_cnt>0UL ? votes[0].shred_version : fallback_votes[0].shred_version;
     146          42 :   memcpy( cert.block_hash, block_hash, sizeof(ag_block_hash_t) );
     147          42 :   memset( &cert.agg_notar, 0, sizeof(fd_bls_agg_t) );
     148         222 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg_notar, votes[i].rank, &votes[i].sig );
     149          42 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_notar ) ) ) {
     150           6 :     memset( &cert.agg_notar, 0, sizeof(fd_bls_agg_t) );
     151           6 :     stake = 0UL;
     152           6 :   }
     153          42 :   memset( &cert.agg_notar_fallback, 0, sizeof(fd_bls_agg_t) );
     154         468 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) agg_add( &cert.agg_notar_fallback, fallback_votes[i].rank, &fallback_votes[i].sig );
     155          42 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_notar_fallback ) ) ) {
     156           9 :     memset( &cert.agg_notar_fallback, 0, sizeof(fd_bls_agg_t) );
     157           9 :     stake_fallback = 0UL;
     158           9 :   }
     159          42 :   cert.stake = stake + stake_fallback;
     160          42 :   return (ag_cert_t){ .kind = AG_CERT_KIND_NOTAR_FALLBACK, .notar_fallback = cert };
     161          42 : }
     162             : 
     163             : static inline ag_cert_t
     164             : cert_build_skip( ag_vote_skip_t const *          votes,
     165             :                  ulong                           vote_cnt,
     166             :                  ag_vote_skip_fallback_t const * fallback_votes,
     167             :                  ulong                           fallback_vote_cnt,
     168          75 :                  ag_epoch_info_t const *         epoch_info ) {
     169          75 :   ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
     170          75 :   FD_TEST( vote_cnt>0UL || fallback_vote_cnt>0UL );
     171          75 :   ulong slot = vote_cnt>0UL ? votes[0].slot : fallback_votes[0].slot;
     172             : 
     173          75 :   ulong stake = 0UL;
     174        1002 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     175         927 :     FD_TEST( votes[i].slot==slot );
     176         927 :     stake += validators[ votes[i].rank ].stake;
     177         927 :   }
     178          75 :   ulong stake_fallback = 0UL;
     179         132 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) {
     180          57 :     FD_TEST( fallback_votes[i].slot==slot );
     181          57 :     stake_fallback += validators[ fallback_votes[i].rank ].stake;
     182          57 :   }
     183             : 
     184          75 :   ag_cert_skip_t cert;
     185          75 :   cert.slot = slot; cert.shred_version = vote_cnt>0UL ? votes[0].shred_version : fallback_votes[0].shred_version;
     186          75 :   memset( &cert.agg_skip, 0, sizeof(fd_bls_agg_t) );
     187        1002 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg_skip, votes[i].rank, &votes[i].sig );
     188          75 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_skip ) ) ) {
     189           0 :     memset( &cert.agg_skip, 0, sizeof(fd_bls_agg_t) );
     190           0 :     stake = 0UL;
     191           0 :   }
     192          75 :   memset( &cert.agg_skip_fallback, 0, sizeof(fd_bls_agg_t) );
     193         132 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) agg_add( &cert.agg_skip_fallback, fallback_votes[i].rank, &fallback_votes[i].sig );
     194          75 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_skip_fallback ) ) ) {
     195          60 :     memset( &cert.agg_skip_fallback, 0, sizeof(fd_bls_agg_t) );
     196          60 :     stake_fallback = 0UL;
     197          60 :   }
     198          75 :   cert.stake = stake + stake_fallback;
     199          75 :   return (ag_cert_t){ .kind = AG_CERT_KIND_SKIP, .skip = cert };
     200          75 : }
     201             : 
     202             : #endif

Generated by: LCOV version 1.14