LCOV - code coverage report
Current view: top level - app/shared_dev/commands/configure - genesis.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 309 0.0 %
Date: 2025-11-08 04:42:58 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #define FD_SCRATCH_USE_HANDHOLDING 1
       3             : #include "../../../shared/commands/configure/configure.h"
       4             : 
       5             : #include "../../../platform/fd_file_util.h"
       6             : #include "../../../../ballet/poh/fd_poh.h"
       7             : #include "../../../../disco/keyguard/fd_keyload.h"
       8             : #include "../../../../discof/genesis/genesis_hash.h"
       9             : #include "../../../../flamenco/features/fd_features.h"
      10             : #include "../../../../flamenco/genesis/fd_genesis_create.h"
      11             : #include "../../../../flamenco/types/fd_types_custom.h"
      12             : #include "../../../../flamenco/runtime/sysvar/fd_sysvar_clock.h"
      13             : 
      14             : #include <stdio.h>
      15             : #include <unistd.h>
      16             : #include <dirent.h>
      17             : #include <sys/stat.h>
      18             : #include <sys/wait.h>
      19             : 
      20             : #define NAME "genesis"
      21             : 
      22             : /* default_enable_features is a table of features enabled by default */
      23             : 
      24             : static void
      25           0 : default_enable_features( fd_features_t * features ) {
      26           0 :   features->index_erasure_conflict_duplicate_proofs = 0UL;
      27           0 :   features->curve25519_restrict_msm_length = 0UL;
      28           0 :   features->commission_updates_only_allowed_in_first_half_of_epoch = 0UL;
      29           0 :   features->validate_fee_collector_account = 0UL;
      30           0 :   features->incremental_snapshot_only_incremental_hash_calculation = 0UL;
      31           0 :   features->timely_vote_credits = 0UL;
      32           0 :   features->apply_cost_tracker_during_replay = 0UL;
      33           0 :   features->reject_callx_r10 = 1UL;
      34           0 :   features->update_hashes_per_tick = 0UL;
      35           0 :   features->pico_inflation = 0UL;
      36           0 :   features->remaining_compute_units_syscall_enabled = 0UL;
      37           0 :   features->simplify_writable_program_account_check = 0UL;
      38           0 :   features->enable_bpf_loader_set_authority_checked_ix = 0UL;
      39           0 :   features->consume_blockstore_duplicate_proofs = 0UL;
      40           0 :   features->disable_deploy_of_alloc_free_syscall = 0UL;
      41           0 :   features->disable_bpf_loader_instructions = 0UL;
      42           0 :   features->full_inflation_enable = 0UL;
      43           0 :   features->vote_state_add_vote_latency = 0UL;
      44           0 :   features->curve25519_syscall_enabled = 0UL;
      45           0 :   features->error_on_syscall_bpf_function_hash_collisions = 0UL;
      46           0 :   features->update_hashes_per_tick3 = 0UL;
      47           0 :   features->update_hashes_per_tick4 = 0UL;
      48           0 :   features->enable_bpf_loader_extend_program_ix = 0UL;
      49           0 :   features->enable_loader_v4 = 0UL;
      50           0 :   features->increase_tx_account_lock_limit = 0UL;
      51           0 :   features->stake_raise_minimum_delegation_to_1_sol = 0UL;
      52           0 :   features->enable_alt_bn128_syscall = 0UL;
      53           0 :   features->revise_turbine_epoch_stakes = 0UL;
      54           0 :   features->clean_up_delegation_errors = 0UL;
      55           0 :   features->update_hashes_per_tick5 = 0UL;
      56           0 :   features->full_inflation_vote = 0UL;
      57           0 :   features->skip_rent_rewrites = 0UL;
      58           0 :   features->switch_to_new_elf_parser = 0UL;
      59           0 :   features->require_rent_exempt_split_destination = 0UL;
      60           0 :   features->enable_turbine_fanout_experiments = 0UL;
      61           0 :   features->devnet_and_testnet = 0UL;
      62           0 :   features->enable_big_mod_exp_syscall = 0UL;
      63           0 :   features->enable_alt_bn128_compression_syscall = 0UL;
      64           0 :   features->update_hashes_per_tick2 = 0UL;
      65           0 :   features->account_data_direct_mapping = 0UL;
      66           0 :   features->stricter_abi_and_runtime_constraints = 0UL;
      67           0 :   features->bpf_account_data_direct_mapping = 0UL;
      68           0 :   features->relax_authority_signer_check_for_lookup_table_creation = 0UL;
      69           0 :   features->update_hashes_per_tick6 = 0UL;
      70           0 :   features->enable_poseidon_syscall = 0UL;
      71           0 :   features->better_error_codes_for_tx_lamport_check = 0UL;
      72           0 :   features->stake_minimum_delegation_for_rewards = 0UL;
      73           0 :   features->loosen_cpi_size_restriction = 0UL;
      74           0 :   features->drop_legacy_shreds = 0UL;
      75           0 :   features->deprecate_rewards_sysvar = 0UL;
      76           0 :   features->warp_timestamp_again = 0UL;
      77           0 :   features->reduce_stake_warmup_cooldown = 0UL;
      78           0 :   features->disable_turbine_fanout_experiments = 0UL;
      79           0 :   features->blake3_syscall_enabled = 0UL;
      80           0 :   features->last_restart_slot_sysvar = 0UL;
      81           0 :   features->disable_fees_sysvar = 0UL;
      82           0 : }
      83             : 
      84             : /* estimate_hashes_per_tick approximates the PoH hashrate of the current
      85             :    tile.  Spins PoH hashing for estimate_dur_ns nanoseconds.  Returns
      86             :    the hashes per tick achieved, where tick_mhz is the target tick rate
      87             :    in ticks per microsecond (MHz).  Assumes that the estimate duration
      88             :    is larger than the tick duration. */
      89             : 
      90             : static ulong
      91             : estimate_hashes_per_tick( ulong tick_mhz,
      92           0 :                           ulong estimate_dur_ns ) {
      93           0 :   ulong const batch    = 1UL<<20;
      94           0 :   long const  deadline = fd_log_wallclock() + (long)estimate_dur_ns;
      95             : 
      96           0 :   uchar poh_hash[ 32 ] = {0};
      97           0 :   ulong          hash_cnt = 0UL;
      98           0 :   do {
      99           0 :     fd_poh_append( poh_hash, batch );
     100           0 :     hash_cnt += batch;
     101           0 :   } while( fd_log_wallclock() < deadline );
     102             : 
     103           0 :   double hash_cnt_dbl = (double)hash_cnt;
     104           0 :   double tick_cnt_dbl = (double)estimate_dur_ns / ( (double)tick_mhz * 1000.0 );
     105           0 :   if( tick_cnt_dbl < 1.0 ) return 0UL;
     106             : 
     107             :   /* Apply 50% factor to the maximum machine hash rate. */
     108           0 :   double hashes_per_tick = hash_cnt_dbl / tick_cnt_dbl / 2.0;
     109           0 :   return (ulong)hashes_per_tick;
     110           0 : }
     111             : 
     112             : 
     113             : /* Create a new genesis.bin file contents into the provided blob buffer
     114             :    and return the size of the buffer.  Will abort on error if the
     115             :    provided buffer is not large enough. */
     116             : 
     117             : static ulong
     118             : create_genesis( config_t const * config,
     119             :                 uchar *          blob,
     120           0 :                 ulong            blob_max ) {
     121             : 
     122           0 :   fd_genesis_options_t options[1];
     123             : 
     124             :   /* Read in keys */
     125             : 
     126           0 :   uchar const * identity_pubkey_ = fd_keyload_load( config->paths.identity_key, 1 );
     127           0 :   if( FD_UNLIKELY( !identity_pubkey_ ) ) FD_LOG_ERR(( "Failed to load identity key" ));
     128           0 :   memcpy( options->identity_pubkey.key, identity_pubkey_, 32 );
     129           0 :   fd_keyload_unload( identity_pubkey_, 1 );
     130             : 
     131           0 :   char file_path[ PATH_MAX ];
     132           0 :   FD_TEST( fd_cstr_printf_check( file_path, PATH_MAX, NULL, "%s/faucet.json", config->paths.base ) );
     133           0 :   uchar const * faucet_pubkey_ = fd_keyload_load( file_path, 1 );
     134           0 :   if( FD_UNLIKELY( !faucet_pubkey_ ) ) FD_LOG_ERR(( "Failed to load faucet key" ));
     135           0 :   memcpy( options->faucet_pubkey.key, faucet_pubkey_, 32 );
     136           0 :   fd_keyload_unload( faucet_pubkey_, 1 );
     137             : 
     138           0 :   FD_TEST( fd_cstr_printf_check( file_path, PATH_MAX, NULL, "%s/stake-account.json", config->paths.base ) );
     139           0 :   uchar const * stake_pubkey_ = fd_keyload_load( file_path, 1 );
     140           0 :   if( FD_UNLIKELY( !stake_pubkey_ ) ) FD_LOG_ERR(( "Failed to load stake account key" ));
     141           0 :   memcpy( options->stake_pubkey.key, stake_pubkey_, 32 );
     142           0 :   fd_keyload_unload( stake_pubkey_, 1 );
     143             : 
     144           0 :   if( !strcmp( config->paths.vote_account, "" ) ) {
     145           0 :     FD_TEST( fd_cstr_printf_check( file_path, PATH_MAX, NULL, "%s/vote-account.json", config->paths.base ) );
     146           0 :   } else {
     147           0 :     fd_cstr_fini( fd_cstr_append_cstr_safe( fd_cstr_init( file_path ), config->paths.vote_account, PATH_MAX-1UL ) );
     148           0 :   }
     149             : 
     150           0 :   uchar const * vote_pubkey_ = fd_keyload_load( file_path, 1 );
     151           0 :   if( FD_UNLIKELY( !vote_pubkey_ ) ) FD_LOG_ERR(( "Failed to load vote account key" ));
     152           0 :   memcpy( options->vote_pubkey.key, vote_pubkey_, 32 );
     153           0 :   fd_keyload_unload( vote_pubkey_, 1 );
     154             : 
     155           0 :   options->creation_time      = (ulong)fd_log_wallclock() / (ulong)1e9;
     156           0 :   options->faucet_balance     = 500000000000000000UL;
     157           0 :   options->vote_account_stake = config->development.genesis.vote_account_stake_lamports;
     158             : 
     159             :   /* Set up PoH config */
     160             : 
     161           0 :   if( 0UL==config->development.genesis.hashes_per_tick ) {
     162             : 
     163             :     /* set hashes_per_tick to whatever machine is capable of */
     164           0 :     ulong hashes_per_tick =
     165           0 :       estimate_hashes_per_tick( config->development.genesis.target_tick_duration_micros,
     166           0 :                                 (ulong)3e9 /* 3 seconds */ );
     167             : 
     168           0 :     if( hashes_per_tick == 0UL ) {
     169           0 :       FD_LOG_WARNING(( "PoH rate estimation failed.  Defaulting to %lu",
     170           0 :                         FD_SYSVAR_CLOCK_DEFAULT_HASHES_PER_TICK ));
     171           0 :       hashes_per_tick = FD_SYSVAR_CLOCK_DEFAULT_HASHES_PER_TICK;
     172           0 :     }
     173             : 
     174           0 :     options->hashes_per_tick = hashes_per_tick;
     175             : 
     176           0 :   } else if( 1UL==config->development.genesis.hashes_per_tick ) {
     177             : 
     178             :     /* set hashes_per_tick field to 0, which means sleep mode */
     179           0 :     options->hashes_per_tick = 0UL;
     180             : 
     181           0 :   } else {
     182             : 
     183             :     /* set hashes_per_tick to the specified value */
     184           0 :     options->hashes_per_tick = config->development.genesis.hashes_per_tick;
     185             : 
     186           0 :   }
     187             : 
     188           0 :   options->ticks_per_slot               = config->development.genesis.ticks_per_slot;
     189           0 :   options->target_tick_duration_micros  = config->development.genesis.target_tick_duration_micros;
     190             : 
     191           0 :   options->fund_initial_accounts        = config->development.genesis.fund_initial_accounts;
     192           0 :   options->fund_initial_amount_lamports = config->development.genesis.fund_initial_amount_lamports;
     193             : 
     194           0 :   options->warmup_epochs                = config->development.genesis.warmup_epochs;
     195             : 
     196           0 :   fd_features_t features[1];
     197           0 :   fd_features_disable_all( features );
     198           0 :   fd_cluster_version_t cluster_version = {
     199           0 :     .major = FD_DEFAULT_AGAVE_CLUSTER_VERSION_MAJOR,
     200           0 :     .minor = FD_DEFAULT_AGAVE_CLUSTER_VERSION_MINOR,
     201           0 :     .patch = FD_DEFAULT_AGAVE_CLUSTER_VERSION_PATCH
     202           0 :   };
     203           0 :   fd_features_enable_cleaned_up( features, &cluster_version );
     204           0 :   default_enable_features( features );
     205             : 
     206           0 :   options->features = features;
     207             : 
     208             :   /* Serialize blob */
     209             : 
     210           0 :   static uchar scratch_smem[ 1<<24UL ];  /* fits at least 32k accounts */
     211           0 :          ulong scratch_fmem[ 4 ];
     212           0 :   fd_scratch_attach( scratch_smem, scratch_fmem,
     213           0 :                      sizeof(scratch_smem), sizeof(scratch_fmem)/sizeof(ulong) );
     214             : 
     215           0 :   ulong blob_sz = fd_genesis_create( blob, blob_max, options );
     216           0 :   if( FD_UNLIKELY( !blob_sz ) ) FD_LOG_ERR(( "Failed to create genesis blob" ));
     217             : 
     218           0 :   fd_scratch_detach( NULL );
     219             : 
     220           0 :   return blob_sz;
     221           0 : }
     222             : 
     223             : static void
     224           0 : init( config_t const * config ) {
     225           0 :   int bootstrap = !config->gossip.entrypoints_cnt;
     226           0 :   if( FD_LIKELY( !bootstrap ) ) return;
     227             : 
     228           0 :   char _genesis_path[ PATH_MAX ];
     229           0 :   char const * genesis_path;
     230           0 :   if( FD_LIKELY( config->is_firedancer ) ) genesis_path = config->paths.genesis;
     231           0 :   else {
     232           0 :     genesis_path = _genesis_path;
     233           0 :     FD_TEST( fd_cstr_printf_check( _genesis_path, PATH_MAX, NULL, "%s/genesis.bin", config->frankendancer.paths.ledger ) );
     234           0 :   }
     235             : 
     236           0 :   if( FD_UNLIKELY( -1==fd_file_util_mkdir_all( genesis_path, config->uid, config->gid, 0 ) ) )
     237           0 :     FD_LOG_ERR(( "could not create ledger directory `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     238             : 
     239           0 :   static uchar blob[ 1UL<<24UL ];
     240           0 :   ulong blob_sz = create_genesis( config, blob, sizeof(blob) );
     241             : 
     242             :   /* Switch to target user in the configuration when creating the
     243             :      genesis.bin file so it is permissioned correctly. */
     244             : 
     245           0 :   gid_t gid = getgid();
     246           0 :   uid_t uid = getuid();
     247           0 :   if( FD_LIKELY( gid == 0 && setegid( config->gid ) ) )
     248           0 :     FD_LOG_ERR(( "setegid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     249           0 :   if( FD_LIKELY( uid == 0 && seteuid( config->uid ) ) )
     250           0 :     FD_LOG_ERR(( "seteuid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     251             : 
     252           0 :   mode_t previous = umask( S_IRWXO | S_IRWXG );
     253             : 
     254           0 :   do {
     255           0 :     FILE * genesis_file = fopen( genesis_path, "w" );
     256           0 :     FD_TEST( genesis_file );
     257           0 :     FD_TEST( 1L == fwrite( blob, blob_sz, 1L, genesis_file ) );
     258           0 :     FD_TEST( !fclose( genesis_file ) );
     259           0 :   } while(0);
     260             : 
     261           0 :   umask( previous );
     262             : 
     263           0 :   if( FD_UNLIKELY( seteuid( uid ) ) ) FD_LOG_ERR(( "seteuid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     264           0 :   if( FD_UNLIKELY( setegid( gid ) ) ) FD_LOG_ERR(( "setegid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     265             : 
     266           0 :   uchar genesis_hash[ 32 ];
     267           0 :   char  genesis_hash_cstr[ FD_BASE58_ENCODED_32_SZ ];
     268             : 
     269           0 :   ushort shred_version;
     270           0 :   int result = compute_shred_version( genesis_path, &shred_version, genesis_hash );
     271           0 :   if( FD_UNLIKELY( -1==result ) ) FD_LOG_ERR(( "could not compute shred version from genesis file `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     272             : 
     273           0 :   FD_LOG_INFO(( "Created %s:  genesis_hash=%s sz=%lu",
     274           0 :                 genesis_path,
     275           0 :                 fd_base58_encode_32( genesis_hash, NULL, genesis_hash_cstr ),
     276           0 :                 blob_sz ));
     277           0 :   FD_LOG_INFO(( "Shred version: %hu", shred_version ));
     278           0 : }
     279             : 
     280             : static int
     281             : fini( config_t const * config,
     282           0 :       int              pre_init ) {
     283           0 :   (void)pre_init;
     284             : 
     285           0 :   char _genesis_path[ PATH_MAX ];
     286           0 :   char const * genesis_path;
     287           0 :   if( FD_LIKELY( config->is_firedancer ) ) genesis_path = config->paths.genesis;
     288           0 :   else {
     289           0 :     genesis_path = _genesis_path;
     290           0 :     FD_TEST( fd_cstr_printf_check( _genesis_path, PATH_MAX, NULL, "%s/genesis.bin", config->frankendancer.paths.ledger ) );
     291           0 :   }
     292             : 
     293           0 :   if( FD_UNLIKELY( -1==unlink( genesis_path ) && errno!=ENOENT ) )
     294           0 :     FD_LOG_ERR(( "could not remove genesis.bin file `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     295           0 :   return 0;
     296           0 : }
     297             : 
     298             : static configure_result_t
     299             : check( config_t const * config,
     300           0 :        int              check_type FD_PARAM_UNUSED ) {
     301           0 :   if( FD_LIKELY( config->gossip.entrypoints_cnt ) ) CONFIGURE_OK();
     302             : 
     303           0 :   char _genesis_path[ PATH_MAX ];
     304           0 :   char const * genesis_path;
     305           0 :   if( FD_LIKELY( config->is_firedancer ) ) genesis_path = config->paths.genesis;
     306           0 :   else {
     307           0 :     genesis_path = _genesis_path;
     308           0 :     FD_TEST( fd_cstr_printf_check( _genesis_path, PATH_MAX, NULL, "%s/genesis.bin", config->frankendancer.paths.ledger ) );
     309           0 :   }
     310             : 
     311           0 :   struct stat st;
     312           0 :   int err = stat( genesis_path, &st );
     313           0 :   if( FD_UNLIKELY( -1==err && errno!=ENOENT ) ) FD_LOG_ERR(( "could not stat genesis.bin file at `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     314           0 :   else if( FD_UNLIKELY( -1==err ) ) NOT_CONFIGURED( "`%s` does not exist", genesis_path );
     315             : 
     316           0 :   if( FD_UNLIKELY( !config->is_firedancer ) ) CHECK( check_dir( config->frankendancer.paths.ledger, config->uid, config->gid, S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR ) );
     317           0 :   CHECK( check_file( genesis_path, config->uid, config->gid, S_IFREG | S_IRUSR | S_IWUSR ) );
     318             : 
     319           0 :   static uchar buffer[ 1UL<<24UL ]; /* 16 MiB buffer should be enough for genesis */
     320           0 :   if( FD_UNLIKELY( (ulong)st.st_size>sizeof(buffer) ) ) FD_LOG_ERR(( "genesis file at `%s` too large (%lu bytes, max %lu)", genesis_path, (ulong)st.st_size, sizeof(buffer) ));
     321             : 
     322           0 :   ulong bytes_read = 0UL;
     323           0 :   int fd = open( genesis_path, O_RDONLY );
     324           0 :   if( FD_UNLIKELY( -1==fd ) ) FD_LOG_ERR(( "could not open genesis.bin file at `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     325             : 
     326           0 :   while( bytes_read < (ulong)st.st_size ) {
     327           0 :     long result = read( fd, buffer + bytes_read, (ulong)st.st_size - bytes_read );
     328           0 :     if( FD_UNLIKELY( -1==result ) ) FD_LOG_ERR(( "could not read genesis.bin file at `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     329           0 :     if( FD_UNLIKELY( !result ) )  FD_LOG_ERR(( "read() returned 0 before reading full genesis.bin file at `%s`", genesis_path ));
     330           0 :     bytes_read += (ulong)result;
     331           0 :   }
     332             : 
     333           0 :   fd_bincode_decode_ctx_t decode_ctx = {
     334           0 :     .data    = buffer,
     335           0 :     .dataend = buffer+st.st_size,
     336           0 :   };
     337             : 
     338           0 :   if( FD_UNLIKELY( -1==close( fd ) ) ) FD_LOG_ERR(( "could not close genesis.bin file at `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     339             : 
     340           0 :   ulong genesis_sz = 0UL;
     341           0 :   err = fd_genesis_solana_decode_footprint( &decode_ctx, &genesis_sz );
     342           0 :   if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) FD_LOG_ERR(( "malformed genesis file at `%s`", genesis_path ));
     343             : 
     344           0 :   static char _genesis[ 1UL<<24UL ] __attribute__((aligned(alignof(fd_genesis_solana_global_t)))); /* 16 MiB for decoded genesis */
     345           0 :   if( FD_UNLIKELY( genesis_sz>sizeof(_genesis) ) ) FD_LOG_ERR(( "genesis file at `%s` decode footprint too large (%lu bytes, max %lu)", genesis_path, genesis_sz, sizeof(_genesis) ));
     346             : 
     347           0 :   fd_genesis_solana_global_t * genesis = fd_genesis_solana_decode_global( _genesis, &decode_ctx );
     348             : 
     349           0 :   ulong tmp_genesis_sz = create_genesis( config, buffer, sizeof(buffer) );
     350             : 
     351           0 :   decode_ctx = (fd_bincode_decode_ctx_t){
     352           0 :     .data    = buffer,
     353           0 :     .dataend = buffer+tmp_genesis_sz,
     354           0 :   };
     355             : 
     356           0 :   genesis_sz = 0UL;
     357           0 :   err = fd_genesis_solana_decode_footprint( &decode_ctx, &genesis_sz );
     358           0 :   if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) FD_LOG_ERR(( "malformed genesis file generated for comparison for `%s`", genesis_path ));
     359             : 
     360           0 :   static char _tmp_genesis[ 1UL<<24UL ] __attribute__((aligned(alignof(fd_genesis_solana_global_t)))); /* 16 MiB for decoded genesis */
     361           0 :   if( FD_UNLIKELY( genesis_sz>sizeof(_tmp_genesis) ) ) FD_LOG_ERR(( "genesis file generated for comparison for `%s` decode footprint too large (%lu bytes, max %lu)", genesis_path, genesis_sz, sizeof(_tmp_genesis) ));
     362             : 
     363           0 :   fd_genesis_solana_global_t * tmp_genesis = fd_genesis_solana_decode_global( _tmp_genesis, &decode_ctx );
     364             : 
     365             :   // ulong creation_time;
     366             : 
     367           0 :   if( FD_UNLIKELY( tmp_genesis->accounts_len!=genesis->accounts_len ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected accounts_len", genesis_path );
     368           0 :   fd_pubkey_account_pair_global_t * accounts = fd_genesis_solana_accounts_join( genesis );
     369           0 :   fd_pubkey_account_pair_global_t * tmp_accounts = fd_genesis_solana_accounts_join( tmp_genesis );
     370           0 :   for( ulong i=0UL; i<genesis->accounts_len; i++ ) {
     371           0 :     if( FD_UNLIKELY( memcmp( accounts[ i ].key.uc, tmp_accounts[ i ].key.uc, 32 ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account key at index %lu", genesis_path, i );
     372           0 :     if( FD_UNLIKELY( accounts[ i ].account.lamports!=tmp_accounts[ i ].account.lamports ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account lamports at index %lu", genesis_path, i );
     373           0 :     if( FD_UNLIKELY( accounts[ i ].account.data_len!=tmp_accounts[ i ].account.data_len ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account data_len at index %lu", genesis_path, i );
     374           0 :     if( FD_UNLIKELY( memcmp( accounts[ i ].account.owner.uc, tmp_accounts[ i ].account.owner.uc, 32 ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account owner at index %lu", genesis_path, i );
     375           0 :     if( FD_UNLIKELY( accounts[ i ].account.executable!=tmp_accounts[ i ].account.executable ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account executable flag at index %lu", genesis_path, i );
     376           0 :     if( FD_UNLIKELY( accounts[ i ].account.rent_epoch!=tmp_accounts[ i ].account.rent_epoch ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account rent_epoch at index %lu", genesis_path, i );
     377             : 
     378           0 :     uchar const * data = fd_solana_account_data_join( &accounts[ i ].account );
     379           0 :     uchar const * tmp_data = fd_solana_account_data_join( &tmp_accounts[ i ].account );
     380           0 :     if( FD_UNLIKELY( memcmp( data, tmp_data, accounts[ i ].account.data_len ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected account data at index %lu", genesis_path, i );
     381           0 :   }
     382             : 
     383           0 :   if( FD_UNLIKELY( tmp_genesis->native_instruction_processors_len!=genesis->native_instruction_processors_len ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected native_instruction_processors_len", genesis_path );
     384           0 :   fd_string_pubkey_pair_global_t * native_instruction_processors = fd_genesis_solana_native_instruction_processors_join( genesis );
     385           0 :   fd_string_pubkey_pair_global_t * tmp_native_instruction_processors = fd_genesis_solana_native_instruction_processors_join( tmp_genesis );
     386           0 :   for( ulong i=0UL; i<genesis->native_instruction_processors_len; i++ ) {
     387           0 :     if( FD_UNLIKELY( memcmp( native_instruction_processors[ i ].pubkey.uc, tmp_native_instruction_processors[ i ].pubkey.uc, 32 ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected native_instruction_processors pubkey at index %lu", genesis_path, i );
     388           0 :     if( FD_UNLIKELY( native_instruction_processors[ i ].string_len!=tmp_native_instruction_processors[ i ].string_len ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected native_instruction_processors string_len at index %lu", genesis_path, i );
     389           0 :     uchar const * str = fd_string_pubkey_pair_string_join( &native_instruction_processors[ i ] );
     390           0 :     uchar const * tmp_str = fd_string_pubkey_pair_string_join( &tmp_native_instruction_processors[ i ] );
     391           0 :     if( FD_UNLIKELY( memcmp( str, tmp_str, native_instruction_processors[ i ].string_len ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected native_instruction_processors string at index %lu", genesis_path, i );
     392           0 :   }
     393             : 
     394           0 :   if( FD_UNLIKELY( tmp_genesis->rewards_pools_len!=genesis->rewards_pools_len ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pools_len", genesis_path );
     395           0 :   fd_pubkey_account_pair_global_t * rewards_pool = fd_genesis_solana_rewards_pools_join( genesis );
     396           0 :   fd_pubkey_account_pair_global_t * tmp_rewards_pool = fd_genesis_solana_rewards_pools_join( tmp_genesis );
     397           0 :   for( ulong i=0UL; i<genesis->rewards_pools_len; i++ ) {
     398           0 :     if( FD_UNLIKELY( memcmp( rewards_pool[ i ].key.uc, tmp_rewards_pool[ i ].key.uc, 32 ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool key at index %lu", genesis_path, i );
     399           0 :     if( FD_UNLIKELY( rewards_pool[ i ].account.lamports!=tmp_rewards_pool[ i ].account.lamports ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool account lamports at index %lu", genesis_path, i );
     400           0 :     if( FD_UNLIKELY( rewards_pool[ i ].account.data_len!=tmp_rewards_pool[ i ].account.data_len ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool account data_len at index %lu", genesis_path, i );
     401           0 :     if( FD_UNLIKELY( memcmp( rewards_pool[ i ].account.owner.uc, tmp_rewards_pool[ i ].account.owner.uc, 32 ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool account owner at index %lu", genesis_path, i );
     402           0 :     if( FD_UNLIKELY( rewards_pool[ i ].account.executable!=tmp_rewards_pool[ i ].account.executable ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool account executable flag at index %lu", genesis_path, i );
     403           0 :     if( FD_UNLIKELY( rewards_pool[ i ].account.rent_epoch!=tmp_rewards_pool[ i ].account.rent_epoch ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool account rent_epoch at index %lu", genesis_path, i );
     404             : 
     405           0 :     uchar const * data = fd_solana_account_data_join( &rewards_pool[ i ].account );
     406           0 :     uchar const * tmp_data = fd_solana_account_data_join( &tmp_rewards_pool[ i ].account );
     407           0 :     if( FD_UNLIKELY( memcmp( data, tmp_data, rewards_pool[ i ].account.data_len ) ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rewards_pool account data at index %lu", genesis_path, i );
     408           0 :   }
     409             : 
     410           0 :   if( FD_UNLIKELY( tmp_genesis->ticks_per_slot!=config->development.genesis.ticks_per_slot ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected ticks_per_slot", genesis_path );
     411             : 
     412             :   // ulong unused;
     413             : 
     414           0 :   if( FD_UNLIKELY( tmp_genesis->poh_config.target_tick_duration.seconds!=genesis->poh_config.target_tick_duration.seconds ) )  PARTIALLY_CONFIGURED( "`%s` has unexpected poh_config.target_tick_duration.seconds", genesis_path );
     415           0 :   if( FD_UNLIKELY( tmp_genesis->poh_config.target_tick_duration.nanoseconds!=genesis->poh_config.target_tick_duration.nanoseconds ) )  PARTIALLY_CONFIGURED( "`%s` has unexpected poh_config.target_tick_duration.nanoseconds", genesis_path );
     416           0 :   if( FD_UNLIKELY( tmp_genesis->poh_config.target_tick_count!=genesis->poh_config.target_tick_count ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected poh_config.target_tick_count", genesis_path );
     417           0 :   if( FD_UNLIKELY( tmp_genesis->poh_config.has_target_tick_count!=genesis->poh_config.has_target_tick_count ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected poh_config.has_target_tick_count", genesis_path );
     418           0 :   if( FD_UNLIKELY( tmp_genesis->poh_config.hashes_per_tick!=genesis->poh_config.hashes_per_tick ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected poh_config.hashes_per_tick", genesis_path );
     419           0 :   if( FD_UNLIKELY( tmp_genesis->poh_config.has_hashes_per_tick!=genesis->poh_config.has_hashes_per_tick ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected poh_config.has_hashes_per_tick", genesis_path );
     420             : 
     421             :   // ulong __backwards_compat_with_v0_23;
     422             : 
     423           0 :   if( FD_UNLIKELY( tmp_genesis->fee_rate_governor.target_lamports_per_signature!=genesis->fee_rate_governor.target_lamports_per_signature ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected fee_rate_governor.target_lamports_per_signature", genesis_path );
     424           0 :   if( FD_UNLIKELY( tmp_genesis->fee_rate_governor.target_signatures_per_slot!=genesis->fee_rate_governor.target_signatures_per_slot ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected fee_rate_governor.target_signatures_per_slot", genesis_path );
     425           0 :   if( FD_UNLIKELY( tmp_genesis->fee_rate_governor.min_lamports_per_signature!=genesis->fee_rate_governor.min_lamports_per_signature ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected fee_rate_governor.min_lamports_per_signature", genesis_path );
     426           0 :   if( FD_UNLIKELY( tmp_genesis->fee_rate_governor.max_lamports_per_signature!=genesis->fee_rate_governor.max_lamports_per_signature ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected fee_rate_governor.max_lamports_per_signature", genesis_path );
     427           0 :   if( FD_UNLIKELY( tmp_genesis->fee_rate_governor.burn_percent!=genesis->fee_rate_governor.burn_percent ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected fee_rate_governor.burn_percent", genesis_path );
     428             : 
     429           0 :   if( FD_UNLIKELY( tmp_genesis->rent.lamports_per_uint8_year!=genesis->rent.lamports_per_uint8_year ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rent.lamports_per_uint8_year", genesis_path );
     430           0 :   if( FD_UNLIKELY( tmp_genesis->rent.exemption_threshold!=genesis->rent.exemption_threshold ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rent.exemption_threshold", genesis_path );
     431           0 :   if( FD_UNLIKELY( tmp_genesis->rent.burn_percent!=genesis->rent.burn_percent ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected rent.burn_percent", genesis_path );
     432             : 
     433           0 :   if( FD_UNLIKELY( tmp_genesis->inflation.initial!=genesis->inflation.initial ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected inflation.initial", genesis_path );
     434           0 :   if( FD_UNLIKELY( tmp_genesis->inflation.terminal!=genesis->inflation.terminal ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected inflation.terminal", genesis_path );
     435           0 :   if( FD_UNLIKELY( tmp_genesis->inflation.taper!=genesis->inflation.taper ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected inflation.taper", genesis_path );
     436           0 :   if( FD_UNLIKELY( tmp_genesis->inflation.foundation!=genesis->inflation.foundation ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected inflation.foundation", genesis_path );
     437           0 :   if( FD_UNLIKELY( tmp_genesis->inflation.foundation_term!=genesis->inflation.foundation_term ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected inflation.foundation_term", genesis_path );
     438             :   // double inflation.unused
     439             : 
     440           0 :   if( FD_UNLIKELY( tmp_genesis->epoch_schedule.slots_per_epoch!=genesis->epoch_schedule.slots_per_epoch ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected epoch_schedule.slots_per_epoch", genesis_path );
     441           0 :   if( FD_UNLIKELY( tmp_genesis->epoch_schedule.leader_schedule_slot_offset!=genesis->epoch_schedule.leader_schedule_slot_offset ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected epoch_schedule.leader_schedule_slot_offset", genesis_path );
     442           0 :   if( FD_UNLIKELY( tmp_genesis->epoch_schedule.warmup!=genesis->epoch_schedule.warmup ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected epoch_schedule.warmup", genesis_path );
     443           0 :   if( FD_UNLIKELY( tmp_genesis->epoch_schedule.first_normal_epoch!=genesis->epoch_schedule.first_normal_epoch ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected epoch_schedule.first_normal_epoch", genesis_path );
     444           0 :   if( FD_UNLIKELY( tmp_genesis->epoch_schedule.first_normal_slot!=genesis->epoch_schedule.first_normal_slot ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected epoch_schedule.first_normal_slot", genesis_path );
     445             : 
     446           0 :   if( FD_UNLIKELY( tmp_genesis->cluster_type!=genesis->cluster_type ) ) PARTIALLY_CONFIGURED( "`%s` has unexpected cluster_type", genesis_path );
     447             : 
     448           0 :   CONFIGURE_OK();
     449           0 : }
     450             : 
     451             : configure_stage_t fd_cfg_stage_genesis = {
     452             :   .name  = NAME,
     453             :   .init  = init,
     454             :   .fini  = fini,
     455             :   .check = check,
     456             : };
     457             : 
     458             : #undef NAME

Generated by: LCOV version 1.14