LCOV - code coverage report
Current view: top level - flamenco/genesis - fd_genesis_parse.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 150 0.0 %
Date: 2026-10-23 17:13:25 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #include "fd_genesis_parse.h"
       2             : #include "../runtime/fd_runtime_const.h"
       3             : #include "../../util/bits/fd_bits.h"
       4             : 
       5             : #include <stddef.h>
       6             : 
       7             : FD_STATIC_ASSERT( alignof(fd_genesis_t)<=FD_GENESIS_ALIGN,              fd_genesis_align     );
       8             : FD_STATIC_ASSERT( offsetof(fd_genesis_t, account)==sizeof(fd_genesis_t), fd_genesis_footprint );
       9             : 
      10             : ulong
      11           0 : fd_genesis_align( void ) {
      12           0 :   return FD_GENESIS_ALIGN;
      13           0 : }
      14             : 
      15             : ulong
      16           0 : fd_genesis_footprint( ulong account_max ) {
      17           0 :   return FD_GENESIS_FOOTPRINT( account_max );
      18           0 : }
      19             : 
      20             : fd_genesis_t *
      21             : fd_genesis_new( void * mem,
      22           0 :                 ulong  account_max ) {
      23           0 :   if( FD_UNLIKELY( !mem ) ) {
      24           0 :     FD_LOG_WARNING(( "NULL mem" ));
      25           0 :     return NULL;
      26           0 :   }
      27           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_GENESIS_ALIGN ) ) ) {
      28           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      29           0 :     return NULL;
      30           0 :   }
      31           0 :   fd_genesis_t * genesis = (fd_genesis_t *)mem;
      32           0 :   memset( genesis, 0, sizeof(fd_genesis_t) );
      33           0 :   genesis->account_max = account_max;
      34           0 :   return genesis;
      35           0 : }
      36             : 
      37             : fd_genesis_t *
      38             : fd_genesis_parse( fd_genesis_t * genesis,
      39             :                   uchar const *  bin,
      40           0 :                   ulong          bin_sz ) {
      41             :   /* Zero out top part of descriptor which is sufficient to fully
      42             :      initialize fd_genesis_t (assuming no struct reordering).  The
      43             :      account_max capacity set by fd_genesis_new lives after builtin and
      44             :      is preserved. */
      45           0 :   memset( genesis, 0, offsetof(fd_genesis_t, builtin) );
      46             : 
      47           0 :   uchar const * _payload    = bin;
      48           0 :   ulong const   _payload_sz = bin_sz;
      49           0 :   ulong         _i          = 0UL;
      50             : 
      51           0 : # define CHECK( cond )   { if( FD_UNLIKELY( !(cond) ) ) { return NULL; } }
      52           0 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
      53           0 : # define INC( n )        (_i += (ulong)(n))
      54           0 : # define CUR_OFFSET      ((ushort)_i)
      55           0 : # define CURSOR          (_payload+_i)
      56             : 
      57           0 :   CHECK_LEFT( 8UL ); genesis->creation_time = FD_LOAD( ulong, CURSOR ); INC( 8UL );
      58             : 
      59           0 :   CHECK_LEFT( 8UL ); genesis->account_cnt = FD_LOAD( ulong, CURSOR ); INC( 8UL );
      60           0 :   if( FD_UNLIKELY( genesis->account_cnt>genesis->account_max ) ) {
      61           0 :     FD_LOG_WARNING(( "genesis account count %lu exceeds account table capacity %lu (a %lu byte blob holds at most %lu accounts; malformed genesis?)",
      62           0 :                      genesis->account_cnt, genesis->account_max, bin_sz, fd_genesis_account_max( bin_sz ) ));
      63           0 :     return NULL;
      64           0 :   }
      65           0 :   for( ulong i=0UL; i<genesis->account_cnt; i++ ) {
      66           0 :     fd_genesis_account_off_t * account = &genesis->account[ i ];
      67             : 
      68           0 :     account->pubkey_off = _i;
      69           0 :     CHECK_LEFT( 32UL );                                            INC( 32UL ); /* pubkey */
      70           0 :     CHECK_LEFT(  8UL );                                            INC(  8UL ); /* lamports */
      71           0 :     CHECK_LEFT(  8UL ); ulong data_len = FD_LOAD( ulong, CURSOR ); INC(  8UL );
      72           0 :     if( FD_UNLIKELY( data_len>FD_RUNTIME_ACC_SZ_MAX ) ) {
      73           0 :       FD_LOG_WARNING(( "genesis builtin account data length %lu exceeds max size %lu", data_len, FD_RUNTIME_ACC_SZ_MAX ));
      74           0 :       return NULL;
      75           0 :     }
      76           0 :     CHECK_LEFT( data_len ); INC( data_len ); /* data */
      77             : 
      78           0 :     account->owner_off = _i;
      79           0 :     CHECK_LEFT( 32UL ); INC( 32UL ); /* owner */
      80           0 :     CHECK_LEFT(  1UL ); CHECK( FD_LOAD( uchar, CURSOR )<=1U ); INC(  1UL ); /* executable */
      81           0 :     CHECK_LEFT(  8UL ); INC(  8UL ); /* rent epoch */
      82           0 :   }
      83             : 
      84           0 :   CHECK_LEFT( 8UL ); genesis->builtin_cnt = FD_LOAD( ulong, CURSOR ); INC( 8UL );
      85           0 :   if( FD_UNLIKELY( genesis->builtin_cnt>FD_GENESIS_BUILTIN_MAX_COUNT ) ) {
      86           0 :     FD_LOG_WARNING(( "genesis builtin count %lu exceeds max %lu", genesis->builtin_cnt, FD_GENESIS_BUILTIN_MAX_COUNT ));
      87           0 :     return NULL;
      88           0 :   }
      89           0 :   for( ulong i=0UL; i<genesis->builtin_cnt; i++ ) {
      90           0 :     fd_genesis_builtin_off_t * account = &genesis->builtin[ i ];
      91             : 
      92           0 :     account->data_len_off = _i;
      93           0 :     CHECK_LEFT( 8UL ); ulong data_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
      94           0 :     if( FD_UNLIKELY( data_len>FD_RUNTIME_ACC_SZ_MAX ) ) {
      95           0 :       FD_LOG_WARNING(( "genesis builtin account data length %lu exceeds supported max size %lu", data_len, FD_RUNTIME_ACC_SZ_MAX ));
      96           0 :       return NULL;
      97           0 :     }
      98           0 :     CHECK_LEFT( data_len ); INC( data_len ); /* data */
      99             : 
     100           0 :     account->pubkey_off = _i;
     101           0 :     CHECK_LEFT( 32UL ); INC( 32UL ); /* pubkey */
     102           0 :   }
     103             : 
     104           0 :   CHECK_LEFT( 8UL ); ulong rewards_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     105           0 :   for( ulong i=0UL; i<rewards_len; i++ ) {
     106           0 :     CHECK_LEFT( 32UL );                                        INC( 32UL ); /* pubkey */
     107           0 :     CHECK_LEFT(  8UL );                                        INC(  8UL ); /* lamports */
     108           0 :     CHECK_LEFT(  8UL ); ulong dlen = FD_LOAD( ulong, CURSOR ); INC(  8UL ); /* dlen */
     109           0 :     CHECK_LEFT( dlen );                                        INC( dlen ); /* data */
     110           0 :     CHECK_LEFT( 32UL );                                        INC( 32UL ); /* owner */
     111           0 :     CHECK_LEFT(  1UL ); CHECK( FD_LOAD( uchar, CURSOR )<=1U ); INC(  1UL ); /* executable */
     112           0 :     CHECK_LEFT(  8UL );                                        INC(  8UL ); /* rent epoch */
     113           0 :   }
     114             : 
     115           0 :   CHECK_LEFT( 8UL ); genesis->poh.ticks_per_slot = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     116           0 :   if( FD_UNLIKELY( !genesis->poh.ticks_per_slot ) ) {
     117           0 :     FD_LOG_WARNING(( "genesis ticks_per_slot must be non-zero" ));
     118           0 :     return NULL;
     119           0 :   }
     120             : 
     121           0 :   CHECK_LEFT( sizeof(ulong) ); INC( sizeof(ulong) ); /* unused */
     122             : 
     123           0 :   CHECK_LEFT( 8UL ); genesis->poh.tick_duration_secs = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     124           0 :   CHECK_LEFT( 4UL ); genesis->poh.tick_duration_ns   = FD_LOAD( uint,  CURSOR ); INC( 4UL );
     125           0 :   CHECK_LEFT( 1UL ); int has_target_tick_count       = FD_LOAD( uchar, CURSOR ); INC( 1UL );
     126           0 :   CHECK( has_target_tick_count<=1 );
     127           0 :   if( has_target_tick_count ) { CHECK_LEFT( 8UL ); genesis->poh.target_tick_count = FD_LOAD( ulong, CURSOR ); INC( 8UL ); }
     128           0 :   else                                            genesis->poh.target_tick_count = 0UL;
     129           0 :   CHECK_LEFT( 1UL ); int has_hashes_per_tick       = FD_LOAD( uchar, CURSOR ); INC( 1UL );
     130           0 :   CHECK( has_hashes_per_tick<=1 );
     131           0 :   if( has_hashes_per_tick ) { CHECK_LEFT( 8UL ); genesis->poh.hashes_per_tick = FD_LOAD( ulong, CURSOR ); INC( 8UL ); }
     132           0 :   else                                          genesis->poh.hashes_per_tick = 0UL;
     133             : 
     134           0 :   CHECK_LEFT( sizeof(ulong) ); INC( sizeof(ulong) ); /* backward compat v23 */
     135             : 
     136           0 :   CHECK_LEFT( 8UL ); genesis->fee_rate_governor.target_lamports_per_signature = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     137           0 :   CHECK_LEFT( 8UL ); genesis->fee_rate_governor.target_signatures_per_slot    = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     138           0 :   CHECK_LEFT( 8UL ); genesis->fee_rate_governor.min_lamports_per_signature    = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     139           0 :   CHECK_LEFT( 8UL ); genesis->fee_rate_governor.max_lamports_per_signature    = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     140           0 :   CHECK_LEFT( 1UL ); genesis->fee_rate_governor.burn_percent                  = FD_LOAD( uchar, CURSOR ); INC( 1UL );
     141             : 
     142           0 :   CHECK_LEFT( 8UL ); genesis->rent.lamports_per_uint8_year = FD_LOAD( ulong, CURSOR );  INC( 8UL );
     143           0 :   CHECK_LEFT( 8UL ); genesis->rent.exemption_threshold     = FD_LOAD( double, CURSOR ); INC( 8UL );
     144           0 :   CHECK_LEFT( 1UL ); genesis->rent.burn_percent            = FD_LOAD( uchar, CURSOR );  INC( 1UL );
     145             : 
     146           0 :   CHECK_LEFT( 8UL ); genesis->inflation.initial         = FD_LOAD( double, CURSOR ); INC( 8UL );
     147           0 :   CHECK_LEFT( 8UL ); genesis->inflation.terminal        = FD_LOAD( double, CURSOR ); INC( 8UL );
     148           0 :   CHECK_LEFT( 8UL ); genesis->inflation.taper           = FD_LOAD( double, CURSOR ); INC( 8UL );
     149           0 :   CHECK_LEFT( 8UL ); genesis->inflation.foundation      = FD_LOAD( double, CURSOR ); INC( 8UL );
     150           0 :   CHECK_LEFT( 8UL ); genesis->inflation.foundation_term = FD_LOAD( double, CURSOR ); INC( 8UL );
     151           0 :   CHECK_LEFT( 8UL );                                                                 INC( 8UL ); /* unused */
     152             : 
     153           0 :   CHECK_LEFT( 8UL ); genesis->epoch_schedule.slots_per_epoch             = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     154           0 :   if( FD_UNLIKELY( genesis->epoch_schedule.slots_per_epoch>FD_RUNTIME_SLOTS_PER_EPOCH ) ) {
     155           0 :     FD_LOG_WARNING(( "genesis slots_per_epoch %lu exceeds supported max %lu", genesis->epoch_schedule.slots_per_epoch, FD_RUNTIME_SLOTS_PER_EPOCH ));
     156           0 :     return NULL;
     157           0 :   }
     158           0 :   CHECK_LEFT( 8UL ); genesis->epoch_schedule.leader_schedule_slot_offset = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     159           0 :   CHECK_LEFT( 1UL ); genesis->epoch_schedule.warmup                      = FD_LOAD( uchar, CURSOR ); INC( 1UL );
     160           0 :   CHECK( genesis->epoch_schedule.warmup<=1U );
     161           0 :   CHECK_LEFT( 8UL ); genesis->epoch_schedule.first_normal_epoch          = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     162           0 :   CHECK_LEFT( 8UL ); genesis->epoch_schedule.first_normal_slot           = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     163             : 
     164           0 :   CHECK_LEFT( 4UL ); genesis->cluster_type = FD_LOAD( uint, CURSOR ); INC( 4UL );
     165             : 
     166           0 : # undef CHECK
     167           0 : # undef CHECK_LEFT
     168           0 : # undef INC
     169           0 : # undef CUR_OFFSET
     170           0 : # undef CURSOR
     171             : 
     172           0 :   if( _i!=_payload_sz ) {
     173           0 :     FD_LOG_WARNING(( "genesis blob has %lu trailing unrecognized bytes. Perhaps this Firedancer build is too old?", _payload_sz-_i ));
     174           0 :     return NULL;
     175           0 :   }
     176             : 
     177           0 :   return genesis;
     178           0 : }
     179             : 
     180             : fd_genesis_account_t *
     181             : fd_genesis_account( fd_genesis_t const *   genesis,
     182             :                     uchar const *          bin,
     183             :                     fd_genesis_account_t * out,
     184           0 :                     ulong                  idx ) {
     185           0 :   fd_genesis_account_off_t const * off = &genesis->account[ idx ];
     186           0 :   out->pubkey   = FD_LOAD( fd_pubkey_t, bin+off->pubkey_off      );
     187           0 :   out->lamports = FD_LOAD( ulong,       bin+off->pubkey_off+32UL );
     188           0 :   out->data_len = (uint)FD_LOAD( ulong, bin+off->pubkey_off+40UL );
     189           0 :   out->data     = bin+off->pubkey_off+48UL;
     190           0 :   memcpy( out->owner.uc, bin+off->owner_off, sizeof(fd_pubkey_t) );
     191           0 :   out->executable = !!bin[ off->owner_off+32UL ];
     192           0 :   return out;
     193           0 : }
     194             : 
     195             : fd_genesis_builtin_t *
     196             : fd_genesis_builtin( fd_genesis_t const *   genesis,
     197             :                     uchar const *          bin,
     198             :                     fd_genesis_builtin_t * out,
     199           0 :                     ulong                  idx ) {
     200           0 :   fd_genesis_builtin_off_t const * off = &genesis->builtin[ idx ];
     201           0 :   out->pubkey   = FD_LOAD( fd_pubkey_t, bin+off->pubkey_off   );
     202           0 :   out->data_len = FD_LOAD( ulong,       bin+off->data_len_off );
     203           0 :   out->data     = bin+off->data_len_off+8UL;
     204           0 :   return out;
     205           0 : }

Generated by: LCOV version 1.14