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

          Line data    Source code
       1             : #ifndef HEADER_fd_src_choreo_votor_test_fd_cert_builder_h
       2             : #define HEADER_fd_src_choreo_votor_test_fd_cert_builder_h
       3             : 
       4             : /* Certificates are built incrementally in fd_votor_pool.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 fd_cert
       7             :    API. */
       8             : 
       9             : #include "fd_cert.h"
      10             : #include "fd_epoch_info.h"
      11             : #include "fd_vote.h"
      12             : 
      13             : static inline void
      14             : bls_key_from_sec( uchar                out[ FD_BLS_PUB_COMPRESSED_SZ ],
      15           0 :                   fd_bls_sec_t const * sec ) {
      16           0 :   fd_bls_pub_t pub[1];
      17           0 :   fd_bls_sec_to_pub( sec, pub );
      18           0 :   fd_bls_pub_compress( pub, out );
      19           0 : }
      20             : 
      21             : /* epoch_info_build fills epoch_info from an already ranked validator
      22             :    list.  Production ranks in the votor tile (handle_epoch). */
      23             : 
      24             : static inline void
      25             : epoch_info_build( fd_epoch_info_t *           epoch_info,
      26             :                   fd_validator_info_t const * validators,
      27           0 :                   ulong                       validator_cnt ) {
      28           0 :   epoch_info->total_stake = 0UL;
      29           0 :   for( ulong i=0UL; i<validator_cnt; i++ ) {
      30           0 :     FD_TEST( validators[i].id==i );
      31           0 :     epoch_info->validators[i] = validators[i];
      32           0 :     FD_TEST( !fd_bls_pub_de( &epoch_info->pubkeys[i], validators[i].bls_key, FD_BLS_PUB_COMPRESSED_SZ ) );
      33           0 :     epoch_info->total_stake  += validators[i].stake;
      34           0 :   }
      35           0 :   epoch_info->validator_cnt = validator_cnt;
      36           0 : }
      37             : 
      38             : static uchar const test_bls_public_key[ FD_BLS_PUB_COMPRESSED_SZ ] = {0};
      39             : 
      40             : /* A valid affine G2 point outside the prime-order subgroup. */
      41             : static inline void
      42           0 : test_bls_torsion( fd_bls_sig_t * out ) {
      43           0 :   static uchar const bytes[ FD_BLS_SIG_SZ ] = {
      44           0 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      45           0 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      46           0 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      47           0 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      48           0 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      49           0 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
      50           0 :     0x17, 0x2e, 0x93, 0xdb, 0x76, 0x4a, 0x84, 0x00, 0xa7, 0xd5, 0x07, 0x1b, 0x6b, 0x6f, 0x5d, 0xe0,
      51           0 :     0xda, 0x2f, 0x0f, 0x4a, 0x06, 0x31, 0x19, 0xab, 0xca, 0x01, 0x40, 0x06, 0xb7, 0xc4, 0x0a, 0x2c,
      52           0 :     0xfe, 0x29, 0x1a, 0x19, 0x24, 0xe6, 0x5d, 0xb0, 0xd6, 0xd0, 0xfc, 0xfb, 0xf3, 0xbf, 0x3d, 0x5c,
      53           0 :     0x18, 0xc6, 0xb8, 0x64, 0xae, 0x17, 0xdc, 0x9d, 0xa6, 0x42, 0x03, 0xff, 0xef, 0xb9, 0x66, 0x30,
      54           0 :     0x64, 0x25, 0xa7, 0xbc, 0x6a, 0xeb, 0x7c, 0x75, 0x24, 0x74, 0x38, 0x37, 0x27, 0x16, 0x28, 0x4a,
      55           0 :     0x41, 0x73, 0x83, 0x04, 0x20, 0xcd, 0x47, 0x6b, 0xa1, 0xa3, 0x65, 0xb9, 0x5b, 0xfc, 0xec, 0x38
      56           0 :   };
      57           0 :   FD_TEST( !fd_bls_sig_de_unchecked( out, bytes ) );
      58           0 :   FD_TEST( !fd_bls_sig_validate( out ) );
      59           0 : }
      60             : 
      61             : /* sec_sign_fn is the fd_bls_sign_fn of a test that holds the secret
      62             :    key in memory; ctx points to the fd_bls_sec_t. */
      63             : 
      64             : static inline void
      65             : sec_sign_fn( void *         ctx,
      66             :              fd_bls_sig_t * sig,
      67             :              uchar const *  public_key,
      68             :              uchar const *  msg,
      69           0 :              ulong          msg_sz ) {
      70           0 :   (void)public_key;
      71           0 :   fd_bls_sec_sign( (fd_bls_sec_t const *)ctx, msg, msg_sz, sig );
      72           0 : }
      73             : 
      74             : static inline void
      75             : agg_add( fd_bls_agg_t *       agg,
      76             :          ulong                rank,
      77           0 :          fd_bls_sig_t const * sig ) {
      78           0 :   fd_bls_set_insert( agg->set, rank );
      79           0 :   fd_bls_sig_add( &agg->sig, &agg->sig, sig );
      80           0 : }
      81             : 
      82             : static inline int
      83           0 : agg_is_identity( fd_bls_agg_t const * agg ) {
      84           0 :   return !!fd_bls_sig_is_inf( &agg->sig );
      85           0 : }
      86             : 
      87             : static inline fd_cert_t
      88             : cert_build_final( fd_vote_final_t const * votes, ulong vote_cnt, fd_epoch_info_t const * epoch_info );
      89             : static inline fd_cert_t
      90             : cert_build_fast_final( fd_vote_notar_t const * votes, ulong vote_cnt, fd_epoch_info_t const * epoch_info );
      91             : static inline fd_cert_t
      92             : cert_build_notar( fd_vote_notar_t const * votes, ulong vote_cnt, fd_epoch_info_t const * epoch_info );
      93             : static inline fd_cert_t
      94             : cert_build_notar_fallback( fd_vote_notar_t const * votes, ulong vote_cnt, fd_vote_notar_fallback_t const * fallback_votes, ulong fallback_vote_cnt, fd_epoch_info_t const * epoch_info );
      95             : static inline fd_cert_t
      96             : cert_build_skip( fd_vote_skip_t const * votes, ulong vote_cnt, fd_vote_skip_fallback_t const * fallback_votes, ulong fallback_vote_cnt, fd_epoch_info_t const * epoch_info );
      97             : 
      98             : static inline fd_cert_t
      99             : cert_build_final( fd_vote_final_t const * votes,
     100             :                   ulong                   vote_cnt,
     101           0 :                   fd_epoch_info_t const * epoch_info ) {
     102           0 :   fd_validator_info_t const * validators = fd_epoch_info_validators( epoch_info );
     103           0 :   FD_TEST( vote_cnt>0UL );
     104           0 :   ulong slot  = votes[0].slot;
     105           0 :   ulong stake = 0UL;
     106           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     107           0 :     FD_TEST( votes[i].slot==slot );
     108           0 :     stake += validators[ votes[i].rank ].stake;
     109           0 :   }
     110           0 :   fd_cert_final_t cert;
     111           0 :   cert.slot = slot; cert.stake = stake; cert.shred_version = votes[0].shred_version;
     112           0 :   memset( &cert.agg, 0, sizeof(fd_bls_agg_t) );
     113           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg, votes[i].rank, &votes[i].sig );
     114           0 :   return (fd_cert_t){ .kind = FD_CERT_KIND_FINAL, .final = cert };
     115           0 : }
     116             : 
     117             : static inline fd_cert_t
     118             : cert_build_fast_final( fd_vote_notar_t const * votes,
     119             :                        ulong                   vote_cnt,
     120           0 :                        fd_epoch_info_t const * epoch_info ) {
     121           0 :   fd_cert_notar_t      notar = cert_build_notar( votes, vote_cnt, epoch_info ).notar;
     122           0 :   fd_cert_fast_final_t cert;
     123           0 :   cert.slot = notar.slot; cert.stake = notar.stake; cert.agg = notar.agg; cert.shred_version = notar.shred_version;
     124           0 :   memcpy( &cert.block_hash, &notar.block_hash, sizeof(fd_block_hash_t) );
     125           0 :   return (fd_cert_t){ .kind = FD_CERT_KIND_FAST_FINAL, .fast_final = cert };
     126           0 : }
     127             : 
     128             : static inline fd_cert_t
     129             : cert_build_notar( fd_vote_notar_t const * votes,
     130             :                   ulong                   vote_cnt,
     131           0 :                   fd_epoch_info_t const * epoch_info ) {
     132           0 :   fd_validator_info_t const * validators = fd_epoch_info_validators( epoch_info );
     133           0 :   FD_TEST( vote_cnt>0UL );
     134           0 :   ulong           slot  = votes[0].slot;
     135           0 :   ulong           stake = 0UL;
     136           0 :   fd_block_hash_t block_hash;
     137           0 :   memcpy( &block_hash, &votes[0].block_hash, sizeof(fd_block_hash_t) );
     138           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     139           0 :     FD_TEST( votes[i].slot==slot );
     140           0 :     FD_TEST( !memcmp( &votes[i].block_hash, &block_hash, sizeof(fd_block_hash_t) ) );
     141           0 :     stake += validators[ votes[i].rank ].stake;
     142           0 :   }
     143           0 :   fd_cert_notar_t cert;
     144           0 :   cert.slot = slot; cert.stake = stake; cert.shred_version = votes[0].shred_version;
     145           0 :   memcpy( &cert.block_hash, &block_hash, sizeof(fd_block_hash_t) );
     146           0 :   memset( &cert.agg, 0, sizeof(fd_bls_agg_t) );
     147           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg, votes[i].rank, &votes[i].sig );
     148           0 :   return (fd_cert_t){ .kind = FD_CERT_KIND_NOTAR, .notar = cert };
     149           0 : }
     150             : 
     151             : static inline fd_cert_t
     152             : cert_build_notar_fallback( fd_vote_notar_t const *          votes,
     153             :                            ulong                            vote_cnt,
     154             :                            fd_vote_notar_fallback_t const * fallback_votes,
     155             :                            ulong                            fallback_vote_cnt,
     156           0 :                            fd_epoch_info_t const *          epoch_info ) {
     157           0 :   fd_validator_info_t const * validators = fd_epoch_info_validators( epoch_info );
     158           0 :   FD_TEST( vote_cnt>0UL || fallback_vote_cnt>0UL );
     159           0 :   ulong           slot;
     160           0 :   fd_block_hash_t block_hash;
     161           0 :   if( vote_cnt>0UL ) { slot = votes[0].slot;                   memcpy( &block_hash, &votes[0].block_hash,                   sizeof(fd_block_hash_t) ); }
     162           0 :   else               { slot = fallback_votes[0].slot; memcpy( &block_hash, &fallback_votes[0].block_hash, sizeof(fd_block_hash_t) ); }
     163             : 
     164           0 :   ulong stake = 0UL;
     165           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     166           0 :     FD_TEST( votes[i].slot==slot );
     167           0 :     FD_TEST( !memcmp( &votes[i].block_hash, &block_hash, sizeof(fd_block_hash_t) ) );
     168           0 :     stake += validators[ votes[i].rank ].stake;
     169           0 :   }
     170           0 :   ulong stake_fallback = 0UL;
     171           0 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) {
     172           0 :     FD_TEST( fallback_votes[i].slot==slot );
     173           0 :     FD_TEST( !memcmp( &fallback_votes[i].block_hash, &block_hash, sizeof(fd_block_hash_t) ) );
     174           0 :     stake_fallback += validators[ fallback_votes[i].rank ].stake;
     175           0 :   }
     176             : 
     177           0 :   fd_cert_notar_fallback_t cert;
     178           0 :   cert.slot = slot; cert.shred_version = vote_cnt>0UL ? votes[0].shred_version : fallback_votes[0].shred_version;
     179           0 :   memcpy( &cert.block_hash, &block_hash, sizeof(fd_block_hash_t) );
     180           0 :   memset( &cert.agg_notar, 0, sizeof(fd_bls_agg_t) );
     181           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg_notar, votes[i].rank, &votes[i].sig );
     182           0 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_notar ) ) ) {
     183           0 :     memset( &cert.agg_notar, 0, sizeof(fd_bls_agg_t) );
     184           0 :     stake = 0UL;
     185           0 :   }
     186           0 :   memset( &cert.agg_notar_fallback, 0, sizeof(fd_bls_agg_t) );
     187           0 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) agg_add( &cert.agg_notar_fallback, fallback_votes[i].rank, &fallback_votes[i].sig );
     188           0 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_notar_fallback ) ) ) {
     189           0 :     memset( &cert.agg_notar_fallback, 0, sizeof(fd_bls_agg_t) );
     190           0 :     stake_fallback = 0UL;
     191           0 :   }
     192           0 :   cert.stake = stake + stake_fallback;
     193           0 :   return (fd_cert_t){ .kind = FD_CERT_KIND_NOTAR_FALLBACK, .notar_fallback = cert };
     194           0 : }
     195             : 
     196             : static inline fd_cert_t
     197             : cert_build_skip( fd_vote_skip_t const *          votes,
     198             :                  ulong                           vote_cnt,
     199             :                  fd_vote_skip_fallback_t const * fallback_votes,
     200             :                  ulong                           fallback_vote_cnt,
     201           0 :                  fd_epoch_info_t const *         epoch_info ) {
     202           0 :   fd_validator_info_t const * validators = fd_epoch_info_validators( epoch_info );
     203           0 :   FD_TEST( vote_cnt>0UL || fallback_vote_cnt>0UL );
     204           0 :   ulong slot = vote_cnt>0UL ? votes[0].slot : fallback_votes[0].slot;
     205             : 
     206           0 :   ulong stake = 0UL;
     207           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) {
     208           0 :     FD_TEST( votes[i].slot==slot );
     209           0 :     stake += validators[ votes[i].rank ].stake;
     210           0 :   }
     211           0 :   ulong stake_fallback = 0UL;
     212           0 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) {
     213           0 :     FD_TEST( fallback_votes[i].slot==slot );
     214           0 :     stake_fallback += validators[ fallback_votes[i].rank ].stake;
     215           0 :   }
     216             : 
     217           0 :   fd_cert_skip_t cert;
     218           0 :   cert.slot = slot; cert.shred_version = vote_cnt>0UL ? votes[0].shred_version : fallback_votes[0].shred_version;
     219           0 :   memset( &cert.agg_skip, 0, sizeof(fd_bls_agg_t) );
     220           0 :   for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg_skip, votes[i].rank, &votes[i].sig );
     221           0 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_skip ) ) ) {
     222           0 :     memset( &cert.agg_skip, 0, sizeof(fd_bls_agg_t) );
     223           0 :     stake = 0UL;
     224           0 :   }
     225           0 :   memset( &cert.agg_skip_fallback, 0, sizeof(fd_bls_agg_t) );
     226           0 :   for( ulong i=0UL; i<fallback_vote_cnt; i++ ) agg_add( &cert.agg_skip_fallback, fallback_votes[i].rank, &fallback_votes[i].sig );
     227           0 :   if( FD_UNLIKELY( agg_is_identity( &cert.agg_skip_fallback ) ) ) {
     228           0 :     memset( &cert.agg_skip_fallback, 0, sizeof(fd_bls_agg_t) );
     229           0 :     stake_fallback = 0UL;
     230           0 :   }
     231           0 :   cert.stake = stake + stake_fallback;
     232           0 :   return (fd_cert_t){ .kind = FD_CERT_KIND_SKIP, .skip = cert };
     233           0 : }
     234             : 
     235             : #endif

Generated by: LCOV version 1.14