LCOV - code coverage report
Current view: top level - discof/restore/utils - fd_ssload.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 129 0.0 %
Date: 2025-08-05 05:04:49 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include "fd_ssload.h"
       2             : 
       3             : #include "../../../flamenco/runtime/context/fd_exec_slot_ctx.h"
       4             : #include "../../../flamenco/runtime/program/fd_vote_program.h"
       5             : #include "fd_ssmsg.h"
       6             : 
       7             : void
       8             : blockhashes_recover( fd_blockhashes_t *                       blockhashes,
       9             :                      fd_snapshot_manifest_blockhash_t const * ages,
      10             :                      ulong                                    age_cnt,
      11           0 :                      ulong                                    seed ) {
      12           0 :   FD_TEST( fd_blockhashes_init( blockhashes, seed ) );
      13           0 :   FD_TEST( age_cnt && age_cnt<=FD_BLOCKHASHES_MAX );
      14             : 
      15             :   /* For depressing reasons, the ages array is not sorted when ingested
      16             :      from a snapshot.  The hash_index field is also not validated.
      17             :      Firedancer assumes that the sequence of hash_index numbers is
      18             :      gapless and does not wrap around. */
      19             : 
      20           0 :   ulong seq_min = ULONG_MAX-1;
      21           0 :   for( ulong i=0UL; i<age_cnt; i++ ) {
      22           0 :     seq_min = fd_ulong_min( seq_min, ages[ i ].hash_index );
      23           0 :   }
      24           0 :   ulong seq_max;
      25           0 :   if( FD_UNLIKELY( __builtin_uaddl_overflow( seq_min, age_cnt, &seq_max ) ) ) {
      26             :     /* TODO: Move to snapin validations so we can retry */
      27           0 :     FD_LOG_ERR(( "Corrupt snapshot: blockhash queue sequence number wraparound (seq_min=%lu age_cnt=%lu)", seq_min, age_cnt ));
      28           0 :   }
      29             : 
      30             :   /* Reset */
      31             : 
      32           0 :   for( ulong i=0UL; i<age_cnt; i++ ) {
      33           0 :     fd_blockhash_info_t * ele = fd_blockhash_deq_push_tail_nocopy( blockhashes->d.deque );
      34           0 :     memset( ele, 0, sizeof(fd_blockhash_info_t) );
      35           0 :   }
      36             : 
      37             :   /* Load hashes */
      38             : 
      39           0 :   for( ulong i=0UL; i<age_cnt; i++ ) {
      40           0 :     fd_snapshot_manifest_blockhash_t const * elem = &ages[ i ];
      41           0 :     ulong idx;
      42           0 :     if( FD_UNLIKELY( __builtin_usubl_overflow( elem->hash_index, seq_min, &idx ) ) ) {
      43             :       /* TODO: Move to snapin validations so we can retry */
      44           0 :       FD_LOG_ERR(( "Corrupt snapshot: gap in blockhash queue (seq=[%lu,%lu) idx=%lu)",
      45           0 :                    seq_min, seq_max, elem->hash_index ));
      46           0 :     }
      47           0 :     fd_blockhash_info_t * info = &blockhashes->d.deque[ idx ];
      48           0 :     if( FD_UNLIKELY( info->exists ) ) {
      49             :       /* TODO: Move to snapin validations so we can retry */
      50           0 :       FD_LOG_HEXDUMP_NOTICE(( "info", info, sizeof(fd_blockhash_info_t) ));
      51           0 :       FD_LOG_ERR(( "Corrupt snapshot: duplicate blockhash queue index %lu", idx ));
      52           0 :     }
      53           0 :     info->exists         = 1;
      54           0 :     fd_memcpy( info->hash.uc, elem->hash, 32UL );
      55           0 :     info->fee_calculator.lamports_per_signature = elem->lamports_per_signature;
      56           0 :     fd_blockhash_map_idx_insert( blockhashes->map, idx, blockhashes->d.deque );
      57           0 :   }
      58           0 : }
      59             : 
      60             : void
      61             : fd_ssload_recover( fd_snapshot_manifest_t * manifest,
      62           0 :                    fd_exec_slot_ctx_t *     slot_ctx ) {
      63           0 :   slot_ctx->bank = fd_banks_rekey_root_bank( slot_ctx->banks, manifest->slot );
      64           0 :   FD_TEST( slot_ctx->bank );
      65             : 
      66             :   /* Bank Hash */
      67             : 
      68           0 :   fd_hash_t hash;
      69           0 :   fd_memcpy( &hash.uc, manifest->bank_hash, 32UL );
      70           0 :   fd_bank_bank_hash_set( slot_ctx->bank, hash );
      71             : 
      72           0 :   fd_hash_t parent_hash;
      73           0 :   fd_memcpy( &parent_hash.uc, manifest->parent_bank_hash, 32UL );
      74           0 :   fd_bank_prev_bank_hash_set( slot_ctx->bank, parent_hash );
      75             : 
      76           0 :   fd_fee_rate_governor_t * fee_rate_governor = fd_bank_fee_rate_governor_modify( slot_ctx->bank );
      77           0 :   fee_rate_governor->target_lamports_per_signature = manifest->fee_rate_governor.target_lamports_per_signature;
      78           0 :   fee_rate_governor->target_signatures_per_slot    = manifest->fee_rate_governor.target_signatures_per_slot;
      79           0 :   fee_rate_governor->min_lamports_per_signature    = manifest->fee_rate_governor.min_lamports_per_signature;
      80           0 :   fee_rate_governor->max_lamports_per_signature    = manifest->fee_rate_governor.max_lamports_per_signature;
      81           0 :   fee_rate_governor->burn_percent                  = manifest->fee_rate_governor.burn_percent;
      82             : 
      83           0 :   fd_inflation_t * inflation = fd_bank_inflation_modify( slot_ctx->bank );
      84           0 :   inflation->initial         = manifest->inflation_params.initial;
      85           0 :   inflation->terminal        = manifest->inflation_params.terminal;
      86           0 :   inflation->taper           = manifest->inflation_params.taper;
      87           0 :   inflation->foundation      = manifest->inflation_params.foundation;
      88           0 :   inflation->foundation_term = manifest->inflation_params.foundation_term;
      89           0 :   inflation->unused          = 0.0;
      90             : 
      91           0 :   fd_epoch_schedule_t * epoch_schedule = fd_bank_epoch_schedule_modify( slot_ctx->bank );
      92           0 :   epoch_schedule->slots_per_epoch             = manifest->epoch_schedule_params.slots_per_epoch;
      93           0 :   epoch_schedule->leader_schedule_slot_offset = manifest->epoch_schedule_params.leader_schedule_slot_offset;
      94           0 :   epoch_schedule->warmup                      = manifest->epoch_schedule_params.warmup;
      95           0 :   epoch_schedule->first_normal_epoch          = manifest->epoch_schedule_params.first_normal_epoch;
      96           0 :   epoch_schedule->first_normal_slot           = manifest->epoch_schedule_params.first_normal_slot;
      97             : 
      98           0 :   fd_rent_t * rent = fd_bank_rent_modify( slot_ctx->bank );
      99           0 :   rent->lamports_per_uint8_year = manifest->rent_params.lamports_per_uint8_year;
     100           0 :   rent->exemption_threshold     = manifest->rent_params.exemption_threshold;
     101           0 :   rent->burn_percent            = manifest->rent_params.burn_percent;
     102             : 
     103           0 :   if( FD_LIKELY( manifest->has_hashes_per_tick ) ) fd_bank_hashes_per_tick_set( slot_ctx->bank, manifest->hashes_per_tick );
     104           0 :   else                                             fd_bank_hashes_per_tick_set( slot_ctx->bank, 0UL );
     105             : 
     106           0 :   if( FD_LIKELY( manifest->has_epoch_account_hash ) ) {
     107           0 :     fd_hash_t epoch_account_hash;
     108           0 :     fd_memcpy( &epoch_account_hash.uc, manifest->epoch_account_hash, 32UL );
     109           0 :     fd_bank_epoch_account_hash_set( slot_ctx->bank, epoch_account_hash );
     110           0 :   } else {
     111           0 :     fd_hash_t epoch_account_hash = {0};
     112           0 :     fd_bank_epoch_account_hash_set( slot_ctx->bank, epoch_account_hash );
     113           0 :   }
     114             : 
     115           0 :   if( FD_LIKELY( manifest->has_accounts_lthash ) ) {
     116           0 :     fd_slot_lthash_t lthash;
     117           0 :     fd_memcpy( lthash.lthash, manifest->accounts_lthash, 2048UL );
     118           0 :     fd_bank_lthash_set( slot_ctx->bank, lthash );
     119           0 :   } else {
     120           0 :     fd_slot_lthash_t lthash = {0};
     121           0 :     fd_bank_lthash_set( slot_ctx->bank, lthash );
     122           0 :   }
     123             : 
     124           0 :   fd_blockhashes_t * blockhashes = fd_bank_block_hash_queue_modify( slot_ctx->bank );
     125           0 :   blockhashes_recover( blockhashes, manifest->blockhashes, manifest->blockhashes_len, 42UL /* TODO */ );
     126             : 
     127             :   /* PoH */
     128           0 :   fd_blockhashes_t const * bhq = fd_bank_block_hash_queue_query( slot_ctx->bank );
     129           0 :   fd_hash_t const * last_hash = fd_blockhashes_peek_last( bhq );
     130           0 :   if( FD_LIKELY( last_hash ) ) fd_bank_poh_set( slot_ctx->bank, *last_hash );
     131             : 
     132           0 :   fd_bank_capitalization_set( slot_ctx->bank, manifest->capitalization );
     133           0 :   fd_bank_lamports_per_signature_set( slot_ctx->bank, manifest->lamports_per_signature );
     134           0 :   fd_bank_prev_lamports_per_signature_set( slot_ctx->bank, manifest->lamports_per_signature );
     135           0 :   fd_bank_transaction_count_set( slot_ctx->bank, manifest->transaction_count );
     136           0 :   fd_bank_parent_signature_cnt_set( slot_ctx->bank, manifest->signature_count );
     137           0 :   fd_bank_tick_height_set( slot_ctx->bank, manifest->tick_height );
     138           0 :   fd_bank_max_tick_height_set( slot_ctx->bank, manifest->max_tick_height );
     139           0 :   fd_bank_ns_per_slot_set( slot_ctx->bank, manifest->ns_per_slot );
     140           0 :   fd_bank_ticks_per_slot_set( slot_ctx->bank, manifest->ticks_per_slot );
     141           0 :   fd_bank_genesis_creation_time_set( slot_ctx->bank, manifest->creation_time_millis );
     142           0 :   fd_bank_slots_per_year_set( slot_ctx->bank, manifest->slots_per_year );
     143           0 :   fd_bank_block_height_set( slot_ctx->bank, manifest->block_height );
     144           0 :   fd_bank_parent_slot_set( slot_ctx->bank, manifest->parent_slot );
     145           0 :   fd_bank_execution_fees_set( slot_ctx->bank, manifest->collector_fees );
     146           0 :   fd_bank_priority_fees_set( slot_ctx->bank, 0UL );
     147             : 
     148             :   /* FIXME: Remove the magic number here. */
     149           0 :   fd_clock_timestamp_votes_global_t * clock_timestamp_votes = fd_bank_clock_timestamp_votes_locking_modify( slot_ctx->bank );
     150           0 :   uchar * clock_pool_mem = (uchar *)fd_ulong_align_up( (ulong)clock_timestamp_votes + sizeof(fd_clock_timestamp_votes_global_t), fd_clock_timestamp_vote_t_map_align() );
     151           0 :   fd_clock_timestamp_vote_t_mapnode_t * clock_pool = fd_clock_timestamp_vote_t_map_join( fd_clock_timestamp_vote_t_map_new(clock_pool_mem, 30000UL ) );
     152           0 :   clock_timestamp_votes->votes_pool_offset = (ulong)fd_clock_timestamp_vote_t_map_leave( clock_pool) - (ulong)clock_timestamp_votes;
     153           0 :   clock_timestamp_votes->votes_root_offset = 0UL;
     154           0 :   fd_bank_clock_timestamp_votes_end_locking_modify( slot_ctx->bank );
     155             : 
     156           0 :   for( ulong i=0UL; i<manifest->vote_accounts_len; i++ ) {
     157           0 :     fd_snapshot_manifest_vote_account_t * account = &manifest->vote_accounts[ i ];
     158           0 :     fd_pubkey_t vote_account_pubkey;
     159           0 :     fd_memcpy( vote_account_pubkey.uc, account->vote_account_pubkey, 32UL );
     160           0 :     if( FD_LIKELY( account->last_slot || account->stake ) ) {
     161           0 :       fd_vote_record_timestamp_vote_with_slot( &vote_account_pubkey, account->last_timestamp, account->last_slot, slot_ctx->bank );
     162           0 :     }
     163           0 :   }
     164             : 
     165             :   /* Update last restart slot
     166             :      https://github.com/solana-labs/solana/blob/30531d7a5b74f914dde53bfbb0bc2144f2ac92bb/runtime/src/bank.rs#L2152
     167             : 
     168             :      old_bank->hard_forks is sorted ascending by slot number.
     169             :      To find the last restart slot, take the highest hard fork slot
     170             :      number that is less or equal than the current slot number.
     171             :      (There might be some hard forks in the future, ignore these)
     172             : 
     173             :      SIMD-0047: The first restart slot should be `0` */
     174           0 :   fd_sol_sysvar_last_restart_slot_t * last_restart_slot = fd_bank_last_restart_slot_modify( slot_ctx->bank );
     175           0 :   last_restart_slot->slot = 0UL;
     176           0 :   if( FD_LIKELY( manifest->hard_forks_len ) ) {
     177           0 :     for( ulong i=0UL; i<manifest->hard_forks_len; i++ ) {
     178           0 :       ulong slot = manifest->hard_forks[ manifest->hard_forks_len-1UL-i ];
     179           0 :       if( FD_LIKELY( slot<=manifest->slot ) ) {
     180           0 :         last_restart_slot->slot = slot;
     181           0 :         break;
     182           0 :       }
     183           0 :     }
     184           0 :   }
     185           0 : }

Generated by: LCOV version 1.14