LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_prog_load.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 71 91 78.0 %
Date: 2026-04-01 06:30:45 Functions: 5 6 83.3 %

          Line data    Source code
       1             : #include "fd_prog_load.h"
       2             : #include "../runtime/program/fd_bpf_loader_program.h"
       3             : #include "../runtime/program/fd_loader_v4_program.h"
       4             : #include "../runtime/sysvar/fd_sysvar_epoch_schedule.h"
       5             : #include "../runtime/fd_system_ids.h"
       6             : 
       7             : static fd_prog_info_t *
       8             : fd_prog_info_v4( fd_prog_info_t *      out,
       9           0 :                  fd_accdb_ro_t const * ro ) {
      10             : 
      11           0 :   ulong data_sz = fd_accdb_ref_data_sz( ro );
      12           0 :   if( FD_UNLIKELY( data_sz<LOADER_V4_PROGRAM_DATA_OFFSET ) ) {
      13           0 :     FD_LOG_WARNING(( "program data account is invalid" ));
      14           0 :     return NULL;
      15           0 :   }
      16             : 
      17           0 :   fd_loader_v4_state_t state = FD_LOAD( fd_loader_v4_state_t, fd_accdb_ref_data_const( ro ) );
      18           0 :   if( FD_UNLIKELY( state.status==FD_LOADER_V4_STATUS_ENUM_RETRACTED ) ) {
      19           0 :     FD_LOG_WARNING(( "program data account is not executable" ));
      20           0 :     return NULL;
      21           0 :   }
      22             : 
      23           0 :   *out = (fd_prog_info_t) {
      24           0 :     .elf_off = LOADER_V4_PROGRAM_DATA_OFFSET,
      25           0 :     .elf_sz  = data_sz - LOADER_V4_PROGRAM_DATA_OFFSET,
      26           0 :     .deploy_slot = state.slot
      27           0 :   };
      28           0 :   return out;
      29           0 : }
      30             : 
      31             : static fd_prog_info_t *
      32             : fd_prog_info_v3( fd_prog_info_t *      out,
      33          18 :                  fd_accdb_ro_t const * ro ) {
      34             : 
      35          18 :   ulong data_sz = fd_accdb_ref_data_sz( ro );
      36          18 :   fd_bincode_decode_ctx_t decode = fd_bincode_decode_ctx( fd_accdb_ref_data_const( ro ), data_sz );
      37          18 :   ulong total_sz = 0UL;
      38          18 :   if( FD_UNLIKELY( fd_bpf_upgradeable_loader_state_decode_footprint( &decode, &total_sz )!=FD_BINCODE_SUCCESS ) ) {
      39           3 :     FD_LOG_WARNING(( "program data account is invalid" ));
      40           3 :     return NULL;
      41           3 :   }
      42          15 :   if( FD_UNLIKELY( fd_accdb_ref_data_sz( ro )<PROGRAMDATA_METADATA_SIZE ) ) {
      43           3 :     FD_LOG_WARNING(( "program data account is too small" ));
      44           3 :     return NULL;
      45           3 :   }
      46          12 :   fd_bpf_upgradeable_loader_state_t state;
      47          12 :   fd_bpf_upgradeable_loader_state_decode( &state, &decode );
      48          12 :   if( FD_UNLIKELY( state.discriminant!=fd_bpf_upgradeable_loader_state_enum_program_data ) ) {
      49           3 :     FD_LOG_WARNING(( "loader v3 account is not a program data account" ));
      50           3 :     return NULL;
      51           3 :   }
      52             : 
      53           9 :   *out = (fd_prog_info_t) {
      54           9 :     .elf_off = PROGRAMDATA_METADATA_SIZE,
      55           9 :     .elf_sz  = data_sz - PROGRAMDATA_METADATA_SIZE,
      56           9 :     .deploy_slot = state.inner.program_data.slot
      57           9 :   };
      58           9 :   return out;
      59          12 : }
      60             : 
      61             : static fd_prog_info_t *
      62             : fd_prog_info_v1( fd_prog_info_t *      out,
      63          75 :                  fd_accdb_ro_t const * ro ) {
      64          75 :   *out = (fd_prog_info_t) {
      65          75 :     .elf_off = 0UL,
      66          75 :     .elf_sz  = fd_accdb_ref_data_sz( ro ),
      67          75 :     .deploy_slot = 0UL
      68          75 :   };
      69          75 :   return out;
      70          75 : }
      71             : 
      72             : /* We determine the BPF loader type based off of the program acount owner,
      73             :    instead of the programdata owner.
      74             :    https://github.com/anza-xyz/agave/blob/v4.0.0-beta.5/svm/src/program_loader.rs#L29 */
      75             : fd_prog_info_t *
      76             : fd_prog_info( fd_prog_info_t     * out,
      77             :               fd_accdb_ro_t      * ro,
      78          96 :               fd_pubkey_t const  * program_owner ){
      79          96 :   if( fd_pubkey_eq( program_owner, &fd_solana_bpf_loader_upgradeable_program_id ) ) {
      80          18 :     return fd_prog_info_v3( out, ro );
      81          78 :   } else if( fd_pubkey_eq( program_owner, &fd_solana_bpf_loader_v4_program_id ) ) {
      82           0 :     return fd_prog_info_v4( out, ro );
      83          78 :   } else if( fd_pubkey_eq( program_owner, &fd_solana_bpf_loader_program_id ) ||
      84          78 :              fd_pubkey_eq( program_owner, &fd_solana_bpf_loader_deprecated_program_id ) ) {
      85          75 :     return fd_prog_info_v1( out, ro );
      86          75 :   } else {
      87           3 :     FD_BASE58_ENCODE_32_BYTES( fd_accdb_ref_address( ro ),  addr_b58  );
      88           3 :     FD_BASE58_ENCODE_32_BYTES( program_owner->key,          owner_b58 );
      89           3 :     FD_LOG_WARNING(( "unsupported program data account (address=%s program_owner=%s)", addr_b58, owner_b58 ));
      90           3 :     return NULL;
      91           3 :   }
      92          96 : }
      93             : 
      94             : FD_FN_PURE fd_prog_versions_t
      95             : fd_prog_versions( fd_features_t const * features,
      96          81 :                   ulong                 slot ) {
      97          81 :   int disable_v0  = FD_FEATURE_ACTIVE( slot, features, disable_sbpf_v0_execution );
      98          81 :   int reenable_v0 = FD_FEATURE_ACTIVE( slot, features, reenable_sbpf_v0_execution );
      99          81 :   int enable_v0   = !disable_v0 || reenable_v0;
     100          81 :   int enable_v1   = FD_FEATURE_ACTIVE( slot, features, enable_sbpf_v1_deployment_and_execution );
     101          81 :   int enable_v2   = FD_FEATURE_ACTIVE( slot, features, enable_sbpf_v2_deployment_and_execution );
     102             : 
     103          81 :   fd_prog_versions_t v = {0};
     104          81 :   if( enable_v2 ) {
     105          75 :     v.max_sbpf_version = FD_SBPF_V2;
     106          75 :   } else if( enable_v1 ) {
     107           0 :     v.max_sbpf_version = FD_SBPF_V1;
     108           6 :   } else {
     109           6 :     v.max_sbpf_version = FD_SBPF_V0;
     110           6 :   }
     111          81 :   v.min_sbpf_version = enable_v0 ? FD_SBPF_V0 : fd_uint_min( FD_SBPF_V2, v.max_sbpf_version );
     112          81 :   return v;
     113          81 : }
     114             : 
     115             : fd_prog_load_env_t *
     116             : fd_prog_load_env_from_bank( fd_prog_load_env_t * env,
     117           6 :                             fd_bank_t const *    bank ) {
     118           6 :   *env = (fd_prog_load_env_t) {
     119           6 :     .features    = &bank->f.features,
     120           6 :     .epoch       = bank->f.epoch,
     121           6 :     .epoch_slot0 = fd_epoch_slot0( &bank->f.epoch_schedule, bank->f.epoch )
     122           6 :   };
     123           6 :   return env;
     124           6 : }

Generated by: LCOV version 1.14