LCOV - code coverage report
Current view: top level - app/fddev/configure - genesis.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 180 0.0 %
Date: 2024-11-13 11:58:15 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #define FD_SCRATCH_USE_HANDHOLDING 1
       3             : #include "../../fdctl/configure/configure.h"
       4             : 
       5             : #include <math.h>
       6             : #include <stdio.h>
       7             : #include <unistd.h>
       8             : #include <dirent.h>
       9             : #include <sys/stat.h>
      10             : #include <sys/wait.h>
      11             : 
      12             : #include "../../../ballet/poh/fd_poh.h"
      13             : #include "../../../disco/keyguard/fd_keyload.h"
      14             : #include "../../../flamenco/features/fd_features.h"
      15             : #include "../../../flamenco/genesis/fd_genesis_create.h"
      16             : #include "../../../flamenco/types/fd_types_custom.h"
      17             : #include "../../../flamenco/runtime/sysvar/fd_sysvar_clock.h"
      18             : #include "../genesis_hash.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->enable_partitioned_epoch_reward = 0UL;
      36           0 :   features->pico_inflation = 0UL;
      37           0 :   features->remaining_compute_units_syscall_enabled = 0UL;
      38           0 :   features->simplify_writable_program_account_check = 0UL;
      39           0 :   features->enable_bpf_loader_set_authority_checked_ix = 0UL;
      40           0 :   features->consume_blockstore_duplicate_proofs = 0UL;
      41           0 :   features->disable_deploy_of_alloc_free_syscall = 0UL;
      42           0 :   features->disable_bpf_loader_instructions = 0UL;
      43           0 :   features->full_inflation_enable = 0UL;
      44           0 :   features->vote_state_add_vote_latency = 0UL;
      45           0 :   features->curve25519_syscall_enabled = 0UL;
      46           0 :   features->error_on_syscall_bpf_function_hash_collisions = 0UL;
      47           0 :   features->update_hashes_per_tick3 = 0UL;
      48           0 :   features->update_hashes_per_tick4 = 0UL;
      49           0 :   features->enable_bpf_loader_extend_program_ix = 0UL;
      50           0 :   features->enable_program_runtime_v2_and_loader_v4 = 0UL;
      51           0 :   features->increase_tx_account_lock_limit = 0UL;
      52           0 :   features->stake_raise_minimum_delegation_to_1_sol = 0UL;
      53           0 :   features->enable_alt_bn128_syscall = 0UL;
      54           0 :   features->revise_turbine_epoch_stakes = 0UL;
      55           0 :   features->clean_up_delegation_errors = 0UL;
      56           0 :   features->update_hashes_per_tick5 = 0UL;
      57           0 :   features->full_inflation_vote = 0UL;
      58           0 :   features->skip_rent_rewrites = 0UL;
      59           0 :   features->switch_to_new_elf_parser = 0UL;
      60           0 :   features->require_rent_exempt_split_destination = 0UL;
      61           0 :   features->enable_turbine_fanout_experiments = 0UL;
      62           0 :   features->devnet_and_testnet = 0UL;
      63           0 :   features->enable_big_mod_exp_syscall = 0UL;
      64           0 :   features->enable_alt_bn128_compression_syscall = 0UL;
      65           0 :   features->update_hashes_per_tick2 = 0UL;
      66           0 :   features->bpf_account_data_direct_mapping = 0UL;
      67           0 :   features->relax_authority_signer_check_for_lookup_table_creation = 0UL;
      68           0 :   features->update_hashes_per_tick6 = 0UL;
      69           0 :   features->enable_poseidon_syscall = 0UL;
      70           0 :   features->better_error_codes_for_tx_lamport_check = 0UL;
      71           0 :   features->stake_minimum_delegation_for_rewards = 0UL;
      72           0 :   features->loosen_cpi_size_restriction = 0UL;
      73           0 :   features->drop_legacy_shreds = 0UL;
      74           0 :   features->deprecate_rewards_sysvar = 0UL;
      75           0 :   features->warp_timestamp_again = 0UL;
      76           0 :   features->reduce_stake_warmup_cooldown = 0UL;
      77           0 :   features->disable_turbine_fanout_experiments = 0UL;
      78           0 :   features->blake3_syscall_enabled = 0UL;
      79           0 :   features->last_restart_slot_sysvar = 0UL;
      80           0 :   features->disable_fees_sysvar = 0UL;
      81           0 : }
      82             : 
      83             : /* estimate_hashes_per_tick approximates the PoH hashrate of the current
      84             :    tile.  Spins PoH hashing for estimate_dur_ns nanoseconds.  Returns
      85             :    the hashes per tick achieved, where tick_mhz is the target tick rate
      86             :    in ticks per microsecond (MHz).  Assumes that the estimate duration
      87             :    is larger than the tick duration. */
      88             : 
      89             : static ulong
      90             : estimate_hashes_per_tick( ulong tick_mhz,
      91           0 :                           ulong estimate_dur_ns ) {
      92           0 :   ulong const batch    = 1UL<<20;
      93           0 :   long const  deadline = fd_log_wallclock() + (long)estimate_dur_ns;
      94             : 
      95           0 :   uchar poh_hash[ 32 ] = {0};
      96           0 :   ulong          hash_cnt = 0UL;
      97           0 :   do {
      98           0 :     fd_poh_append( poh_hash, batch );
      99           0 :     hash_cnt += batch;
     100           0 :   } while( fd_log_wallclock() < deadline );
     101             : 
     102           0 :   double hash_cnt_dbl = (double)hash_cnt;
     103           0 :   double tick_cnt_dbl = (double)estimate_dur_ns / ( (double)tick_mhz * 1000.0 );
     104           0 :   if( tick_cnt_dbl < 1.0 ) return 0UL;
     105             : 
     106             :   /* Apply 50% factor to the maximum machine hash rate. */
     107           0 :   double hashes_per_tick = hash_cnt_dbl / tick_cnt_dbl / 2.0;
     108           0 :   return (ulong)hashes_per_tick;
     109           0 : }
     110             : 
     111             : 
     112             : /* Create a new genesis.bin file contents into the provided blob buffer
     113             :    and return the size of the buffer.  Will abort on error if the
     114             :    provided buffer is not large enough. */
     115             : 
     116             : static ulong
     117             : create_genesis( config_t * const config,
     118             :                 uchar *          blob,
     119           0 :                 ulong            blob_sz ) {
     120             : 
     121           0 :   fd_genesis_options_t options[1];
     122             : 
     123             :   /* Read in keys */
     124             : 
     125           0 :   uchar const * identity_pubkey_ = fd_keyload_load( config->consensus.identity_path, 1 );
     126           0 :   if( FD_UNLIKELY( !identity_pubkey_ ) ) FD_LOG_ERR(( "Failed to load identity key" ));
     127           0 :   memcpy( options->identity_pubkey.key, identity_pubkey_, 32 );
     128             : 
     129           0 :   char file_path[ PATH_MAX ];
     130           0 :   FD_TEST( fd_cstr_printf_check( file_path, PATH_MAX, NULL, "%s/faucet.json", config->scratch_directory ) );
     131           0 :   uchar const * faucet_pubkey_ = fd_keyload_load( file_path, 1 );
     132           0 :   if( FD_UNLIKELY( !faucet_pubkey_ ) ) FD_LOG_ERR(( "Failed to load faucet key" ));
     133           0 :   memcpy( options->faucet_pubkey.key, faucet_pubkey_, 32 );
     134             : 
     135           0 :   FD_TEST( fd_cstr_printf_check( file_path, PATH_MAX, NULL, "%s/stake-account.json", config->scratch_directory ) );
     136           0 :   uchar const * stake_pubkey_ = fd_keyload_load( file_path, 1 );
     137           0 :   if( FD_UNLIKELY( !stake_pubkey_ ) ) FD_LOG_ERR(( "Failed to load stake account key" ));
     138           0 :   memcpy( options->stake_pubkey.key, stake_pubkey_, 32 );
     139             : 
     140           0 :   FD_TEST( fd_cstr_printf_check( file_path, PATH_MAX, NULL, "%s/vote-account.json", config->scratch_directory ) );
     141           0 :   uchar const * vote_pubkey_ = fd_keyload_load( file_path, 1 );
     142           0 :   if( FD_UNLIKELY( !vote_pubkey_ ) ) FD_LOG_ERR(( "Failed to load vote account key" ));
     143           0 :   memcpy( options->vote_pubkey.key, vote_pubkey_, 32 );
     144             : 
     145             : 
     146           0 :   options->creation_time      = (ulong)fd_log_wallclock() / (ulong)1e9;
     147           0 :   options->faucet_balance     = 500000000000000000UL;
     148           0 :   options->vote_account_stake = config->development.genesis.vote_account_stake_lamports;
     149             : 
     150             :   /* Set up PoH config */
     151             : 
     152           0 :   if( 0UL==config->development.genesis.hashes_per_tick ) {
     153             : 
     154             :     /* set hashes_per_tick to whatever machine is capable of */
     155           0 :     ulong hashes_per_tick =
     156           0 :       estimate_hashes_per_tick( config->development.genesis.target_tick_duration_micros,
     157           0 :                                 (ulong)3e9 /* 3 seconds */ );
     158             : 
     159           0 :     if( hashes_per_tick == 0UL ) {
     160           0 :       FD_LOG_WARNING(( "PoH rate estimation failed.  Defaulting to %lu",
     161           0 :                         FD_SYSVAR_CLOCK_DEFAULT_HASHES_PER_TICK ));
     162           0 :       hashes_per_tick = FD_SYSVAR_CLOCK_DEFAULT_HASHES_PER_TICK;
     163           0 :     }
     164             : 
     165           0 :     options->hashes_per_tick = hashes_per_tick;
     166             : 
     167           0 :   } else if( 1UL==config->development.genesis.hashes_per_tick ) {
     168             : 
     169             :     /* set hashes_per_tick field to 0, which means sleep mode */
     170           0 :     options->hashes_per_tick = 0UL;
     171             : 
     172           0 :   } else {
     173             : 
     174             :     /* set hashes_per_tick to the specified value */
     175           0 :     options->hashes_per_tick = config->development.genesis.hashes_per_tick;
     176             : 
     177           0 :   }
     178             : 
     179           0 :   options->ticks_per_slot               = config->development.genesis.ticks_per_slot;
     180           0 :   options->target_tick_duration_micros  = config->development.genesis.target_tick_duration_micros;
     181             : 
     182           0 :   options->fund_initial_accounts        = config->development.genesis.fund_initial_accounts;
     183           0 :   options->fund_initial_amount_lamports = config->development.genesis.fund_initial_amount_lamports;
     184             : 
     185           0 :   options->warmup_epochs                = config->development.genesis.warmup_epochs;
     186             : 
     187           0 :   fd_features_t features[1];
     188           0 :   fd_features_disable_all( features );
     189           0 :   uint version[] = {FD_DEFAULT_AGAVE_CLUSTER_VERSION_MAJOR, FD_DEFAULT_AGAVE_CLUSTER_VERSION_MINOR, FD_DEFAULT_AGAVE_CLUSTER_VERSION_PATCH};
     190           0 :   fd_features_enable_cleaned_up(features, version);
     191           0 :   default_enable_features( features );
     192             : 
     193           0 :   options->features = features;
     194             : 
     195             :   /* Serialize blob */
     196             : 
     197           0 :   static uchar scratch_smem[ 16<<20UL ];  /* fits at least 32k accounts */
     198           0 :          ulong scratch_fmem[ 4 ];
     199           0 :   fd_scratch_attach( scratch_smem, scratch_fmem,
     200           0 :                      sizeof(scratch_smem), sizeof(scratch_fmem)/sizeof(ulong) );
     201             : 
     202           0 :   ulong blob_len = fd_genesis_create( blob, blob_sz, options );
     203           0 :   if( FD_UNLIKELY( !blob_sz ) ) FD_LOG_ERR(( "Failed to create genesis blob" ));
     204             : 
     205           0 :   fd_scratch_detach( NULL );
     206             : 
     207           0 :   fd_keyload_unload( identity_pubkey_, 1 );
     208           0 :   fd_keyload_unload( faucet_pubkey_, 1 );
     209           0 :   fd_keyload_unload( stake_pubkey_, 1 );
     210           0 :   fd_keyload_unload( vote_pubkey_, 1 );
     211             : 
     212           0 :   return blob_len;
     213           0 : }
     214             : 
     215             : static void
     216           0 : init( config_t * const config ) {
     217           0 :   mkdir_all( config->ledger.path, config->uid, config->gid );
     218             : 
     219           0 :   static uchar blob[ 16<<20UL ];
     220           0 :   ulong blob_sz = create_genesis( config, blob, sizeof(blob) );
     221             : 
     222             :   /* Switch to target user in the configuration when creating the
     223             :      genesis.bin file so it is permissioned correctly. */
     224             : 
     225           0 :   gid_t gid = getgid();
     226           0 :   uid_t uid = getuid();
     227           0 :   if( FD_LIKELY( gid == 0 && setegid( config->gid ) ) )
     228           0 :     FD_LOG_ERR(( "setegid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     229           0 :   if( FD_LIKELY( uid == 0 && seteuid( config->uid ) ) )
     230           0 :     FD_LOG_ERR(( "seteuid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     231             : 
     232           0 :   mode_t previous = umask( S_IRWXO | S_IRWXG );
     233             : 
     234           0 :   char genesis_path[ PATH_MAX ];
     235           0 :   FD_TEST( fd_cstr_printf_check( genesis_path, PATH_MAX, NULL, "%s/genesis.bin", config->ledger.path ) );
     236           0 :   do {
     237           0 :     FILE * genesis_file = fopen( genesis_path, "w" );
     238           0 :     FD_TEST( genesis_file );
     239           0 :     FD_TEST( 1L == fwrite( blob, blob_sz, 1L, genesis_file ) );
     240           0 :     FD_TEST( !fclose( genesis_file ) );
     241           0 :   } while(0);
     242             : 
     243           0 :   umask( previous );
     244             : 
     245           0 :   if( FD_UNLIKELY( seteuid( uid ) ) ) FD_LOG_ERR(( "seteuid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     246           0 :   if( FD_UNLIKELY( setegid( gid ) ) ) FD_LOG_ERR(( "setegid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     247             : 
     248           0 :   uchar genesis_hash[ 32 ];
     249           0 :   char  genesis_hash_cstr[ FD_BASE58_ENCODED_32_SZ ];
     250           0 :   ushort shred_version = compute_shred_version( genesis_path, genesis_hash );
     251             : 
     252           0 :   FD_LOG_INFO(( "Created %s:  genesis_hash=%s sz=%lu",
     253           0 :                 genesis_path,
     254           0 :                 fd_base58_encode_32( genesis_hash, NULL, genesis_hash_cstr ),
     255           0 :                 blob_sz ));
     256           0 :   FD_LOG_INFO(( "Shred version: %hu", shred_version ));
     257           0 : }
     258             : 
     259             : static void
     260             : fini( config_t * const config,
     261           0 :       int              pre_init ) {
     262           0 :   (void)pre_init;
     263             : 
     264           0 :   char genesis_path[ PATH_MAX ];
     265           0 :   FD_TEST( fd_cstr_printf_check( genesis_path, PATH_MAX, NULL, "%s/genesis.bin", config->ledger.path ) );
     266           0 :   if( FD_UNLIKELY( unlink( genesis_path ) && errno!=ENOENT ) )
     267           0 :     FD_LOG_ERR(( "could not remove genesis.bin file `%s` (%i-%s)", genesis_path, errno, fd_io_strerror( errno ) ));
     268           0 : }
     269             : 
     270             : static configure_result_t
     271           0 : check( config_t * const config ) {
     272           0 :   char genesis_path[ PATH_MAX ];
     273           0 :   fd_cstr_printf_check( genesis_path, PATH_MAX, NULL, "%s/genesis.bin", config->ledger.path );
     274             : 
     275           0 :   struct stat st;
     276           0 :   if( FD_UNLIKELY( stat( genesis_path, &st ) && errno==ENOENT ) )
     277           0 :     NOT_CONFIGURED( "`%s` does not exist", genesis_path );
     278             : 
     279           0 :   CHECK( check_dir( config->ledger.path, config->uid, config->gid, S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR ) );
     280           0 :   CHECK( check_file( genesis_path, config->uid, config->gid, S_IFREG | S_IRUSR | S_IWUSR ) );
     281             : 
     282           0 :   PARTIALLY_CONFIGURED( "`%s` already exists", genesis_path );
     283           0 : }
     284             : 
     285             : configure_stage_t genesis = {
     286             :   .name            = NAME,
     287             :   .init            = init,
     288             :   .fini            = fini,
     289             :   .check           = check,
     290             :   /* It might be nice to not regenerate the genesis.bin if the
     291             :      parameters didn't change here, but it has a timestamp in it and
     292             :      also a variable number of hashes per tick in some configurations,
     293             :      which we would need to pull out and skip in the comparison, so we
     294             :      just always recreate it for now. */
     295             :   .always_recreate = 1,
     296             : };
     297             : 
     298             : #undef NAME

Generated by: LCOV version 1.14