LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_bpf_loader_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1157 1605 72.1 %
Date: 2026-11-11 12:40:43 Functions: 16 16 100.0 %

          Line data    Source code
       1             : #include "fd_bpf_loader_program.h"
       2             : #include "fd_system_program.h"
       3             : 
       4             : /* For additional context see https://solana.com/docs/programs/deploying#state-accounts */
       5             : 
       6             : #include "../../progcache/fd_progcache_user.h"
       7             : #include "../fd_runtime_helpers.h"
       8             : #include "../fd_executor.h"
       9             : #include "../tests/fd_dump_pb.h"
      10             : #include "../sysvar/fd_sysvar.h"
      11             : #include "../fd_pubkey_utils.h"
      12             : #include "../fd_borrowed_account.h"
      13             : #include "../fd_system_ids.h"
      14             : #include "fd_bpf_loader_serialization.h"
      15             : #include "fd_builtin_programs.h"
      16             : #include "fd_native_cpi.h"
      17             : 
      18             : /* https://github.com/anza-xyz/agave/blob/ced98f1ebe73f7e9691308afa757323003ff744f/sdk/program/src/program_error.rs#L290-L335 */
      19             : static inline int
      20             : program_error_to_instr_error( ulong  err,
      21          47 :                               uint * custom_err ) {
      22          47 :   switch( err ) {
      23           2 :     case CUSTOM_ZERO:
      24           2 :       *custom_err = 0;
      25           2 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      26           0 :     case INVALID_ARGUMENT:
      27           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
      28           2 :     case INVALID_INSTRUCTION_DATA:
      29           2 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
      30           0 :     case INVALID_ACCOUNT_DATA:
      31           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      32           0 :     case ACCOUNT_DATA_TOO_SMALL:
      33           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
      34           0 :     case INSUFFICIENT_FUNDS:
      35           0 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
      36           0 :     case INCORRECT_PROGRAM_ID:
      37           0 :       return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
      38           0 :     case MISSING_REQUIRED_SIGNATURES:
      39           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
      40           0 :     case ACCOUNT_ALREADY_INITIALIZED:
      41           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
      42           0 :     case UNINITIALIZED_ACCOUNT:
      43           0 :       return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT;
      44           6 :     case NOT_ENOUGH_ACCOUNT_KEYS:
      45           6 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
      46           0 :     case ACCOUNT_BORROW_FAILED:
      47           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
      48           0 :     case MAX_SEED_LENGTH_EXCEEDED:
      49           0 :       return FD_EXECUTOR_INSTR_ERR_MAX_SEED_LENGTH_EXCEEDED;
      50           0 :     case INVALID_SEEDS:
      51           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_SEEDS;
      52           0 :     case BORSH_IO_ERROR:
      53           0 :       return FD_EXECUTOR_INSTR_ERR_BORSH_IO_ERROR;
      54           0 :     case ACCOUNT_NOT_RENT_EXEMPT:
      55           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_NOT_RENT_EXEMPT;
      56           0 :     case UNSUPPORTED_SYSVAR:
      57           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
      58           0 :     case ILLEGAL_OWNER:
      59           0 :       return FD_EXECUTOR_INSTR_ERR_ILLEGAL_OWNER;
      60           0 :     case MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED:
      61           0 :       return FD_EXECUTOR_INSTR_ERR_MAX_ACCS_DATA_ALLOCS_EXCEEDED;
      62           0 :     case INVALID_ACCOUNT_DATA_REALLOC:
      63           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
      64           0 :     case MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED:
      65           0 :       return FD_EXECUTOR_INSTR_ERR_MAX_INSN_TRACE_LENS_EXCEEDED;
      66           0 :     case BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS:
      67           0 :       return FD_EXECUTOR_INSTR_ERR_BUILTINS_MUST_CONSUME_CUS;
      68           1 :     case INVALID_ACCOUNT_OWNER:
      69           1 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
      70           0 :     case ARITHMETIC_OVERFLOW:
      71           0 :       return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
      72           0 :     case IMMUTABLE:
      73           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
      74           0 :     case INCORRECT_AUTHORITY:
      75           0 :       return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
      76          36 :     default:
      77          36 :       if( err>>BUILTIN_BIT_SHIFT == 0 ) {
      78          36 :         *custom_err = (uint)err;
      79          36 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      80          36 :       }
      81           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ERR;
      82          47 :   }
      83          47 : }
      84             : 
      85             : /* https://github.com/anza-xyz/agave/blob/9b22f28104ec5fd606e4bb39442a7600b38bb671/programs/bpf_loader/src/lib.rs#L216-L229 */
      86             : static ulong
      87        4231 : calculate_heap_cost( ulong heap_size, ulong heap_cost ) {
      88        8462 :   #define KIBIBYTE_MUL_PAGES       (1024UL * 32UL)
      89        4231 :   #define KIBIBYTE_MUL_PAGES_SUB_1 (KIBIBYTE_MUL_PAGES - 1UL)
      90             : 
      91        4231 :   heap_size = fd_ulong_sat_add( heap_size, KIBIBYTE_MUL_PAGES_SUB_1 );
      92             : 
      93        4231 :   heap_size = fd_ulong_sat_mul( fd_ulong_sat_sub( heap_size / KIBIBYTE_MUL_PAGES, 1UL ), heap_cost );
      94        4231 :   return heap_size;
      95             : 
      96        4231 :   #undef KIBIBYTE_MUL_PAGES
      97        4231 :   #undef KIBIBYTE_MUL_PAGES_SUB_1
      98        4231 : }
      99             : 
     100             : /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L105-L171
     101             : 
     102             :    Our arguments to deploy_program are different from the Agave version because
     103             :    we handle the caching of deployed programs differently. In Firedancer we
     104             :    lack the concept of ProgramCacheEntryType entirely.
     105             :    https://github.com/anza-xyz/agave/blob/114d94a25e9631f9bf6349c4b833d7900ef1fb1c/program-runtime/src/loaded_programs.rs#L158
     106             : 
     107             :    In Agave there is a separate caching structure that is used to store the
     108             :    deployed programs. In Firedancer the deployed, validated program is stored as
     109             :    metadata for the account.
     110             : 
     111             :    See https://github.com/firedancer-io/firedancer/blob/9c1df680b3f38bebb0597e089766ec58f3b41e85/src/flamenco/runtime/program/fd_bpf_loader_v3_program.c#L1640
     112             :    for how we handle the concept of 'LoadedProgramType::DelayVisibility' in Firedancer.
     113             : 
     114             :    As a concrete example, our version of deploy_program does not have the
     115             :    'account_size' argument because we do not update the record here. */
     116             : 
     117             : struct fd_bpf_deploy_scratch {
     118             :   uchar rodata        [ FD_RUNTIME_ACC_SZ_MAX     ] __attribute__((aligned(FD_SBPF_PROG_RODATA_ALIGN)));
     119             :   uchar sbpf_footprint[ FD_SBPF_PROGRAM_FOOTPRINT ] __attribute__((aligned(alignof(fd_sbpf_program_t))));
     120             :   uchar programdata   [ FD_RUNTIME_ACC_SZ_MAX     ] __attribute__((aligned(FD_ACCOUNT_REC_ALIGN)));
     121             : };
     122             : typedef struct fd_bpf_deploy_scratch fd_bpf_deploy_scratch_t;
     123             : 
     124             : FD_STATIC_ASSERT( sizeof (fd_bpf_deploy_scratch_t)<=BPF_LOADER_SERIALIZATION_FOOTPRINT, bpf_deploy_scratch_sz    );
     125             : FD_STATIC_ASSERT( alignof(fd_bpf_deploy_scratch_t)<=FD_BPF_FRAMES_ALIGN,                bpf_deploy_scratch_align );
     126             : 
     127             : static int
     128             : deploy_program( fd_exec_instr_ctx_t *     instr_ctx,
     129             :                 uchar const *             programdata,
     130             :                 ulong                     programdata_size,
     131             :                 int                       disable_sbpf_v0_v1_v2_deployment,
     132         248 :                 fd_bpf_deploy_scratch_t * scratch ) {
     133         248 :   int deploy_mode                            = 1;
     134         248 :   int direct_mapping                         = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, account_data_direct_mapping );
     135         248 :   int syscall_parameter_address_restrictions = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, syscall_parameter_address_restrictions );
     136         248 :   int virtual_address_space_adjustments      = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, virtual_address_space_adjustments );
     137             : 
     138         248 :   uchar syscalls_mem[ FD_SBPF_SYSCALLS_FOOTPRINT ] __attribute__((aligned(FD_SBPF_SYSCALLS_ALIGN)));
     139         248 :   fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_join( fd_sbpf_syscalls_new( syscalls_mem ) );
     140         248 :   if( FD_UNLIKELY( !syscalls ) ) {
     141             :     //TODO: full log including err
     142           0 :     fd_log_collector_msg_literal( instr_ctx, "Failed to register syscalls" );
     143           0 :     return FD_EXECUTOR_INSTR_ERR_PROGRAM_ENVIRONMENT_SETUP_FAILURE;
     144           0 :   }
     145             : 
     146             :   /* Agave uses the feature set from the next slot for deployment
     147             :      verification (DELAY_VISIBILITY_SLOT_OFFSET = 1).  This matters at
     148             :      epoch boundaries where features activate: a deployment at the last
     149             :      slot of an epoch should see features that activate at the boundary.
     150             :      https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank.rs#L3280-L3295 */
     151         248 :   ulong deploy_slot = instr_ctx->bank->f.slot+1UL;
     152             : 
     153         248 :   fd_vm_syscall_register_slot( syscalls,
     154         248 :                                deploy_slot,
     155         248 :                                &instr_ctx->bank->f.features,
     156         248 :                                1 );
     157             : 
     158             :   /* Load executable */
     159         248 :   fd_sbpf_elf_info_t elf_info[ 1UL ];
     160         248 :   fd_prog_versions_t versions = fd_prog_versions( &instr_ctx->bank->f.features, deploy_slot );
     161             : 
     162             :   /* SIMD-0500: when active, restrict program deployment to SBPF v3+.
     163             :      Older SBPF versions remain executable.
     164             :      TODO: fix link when 4.1 is released
     165             :      https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/program-runtime/src/deploy.rs#L30-L32 */
     166         248 :   if( disable_sbpf_v0_v1_v2_deployment ) {
     167           0 :     versions.min_sbpf_version = FD_SBPF_V3;
     168           0 :   }
     169             : 
     170         248 :   fd_sbpf_loader_config_t config = { 0 };
     171         248 :   config.elf_deploy_checks = deploy_mode;
     172         248 :   config.sbpf_min_version = versions.min_sbpf_version;
     173         248 :   config.sbpf_max_version = versions.max_sbpf_version;
     174             : 
     175         248 :   if( FD_UNLIKELY( fd_sbpf_elf_peek( elf_info, programdata, programdata_size, &config )<0 ) ) {
     176           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     177           0 :   }
     178             : 
     179         248 :   fd_sbpf_program_t * prog = fd_sbpf_program_new( scratch->sbpf_footprint, elf_info, scratch->rodata );
     180         248 :   if( FD_UNLIKELY( !prog ) ) {
     181           0 :     FD_LOG_ERR(( "fd_sbpf_program_new() failed" ));
     182           0 :   }
     183             : 
     184             :   /* Load program */
     185         248 :   int err = fd_sbpf_program_load( prog, programdata, programdata_size, syscalls, &config, scratch->programdata, programdata_size );
     186         248 :   if( FD_UNLIKELY( err ) ) {
     187          71 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     188          71 :   }
     189             : 
     190             :   /* Validate the program */
     191         177 :   fd_vm_t _vm[ 1UL ];
     192         177 :   fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
     193             : 
     194         177 :   vm = fd_vm_init(
     195         177 :     /* vm                                     */ vm,
     196         177 :     /* instr_ctx                              */ instr_ctx,
     197         177 :     /* heap_max                               */ instr_ctx->txn_out->details.compute_budget.heap_size,
     198         177 :     /* entry_cu                               */ instr_ctx->txn_out->details.compute_budget.compute_meter,
     199         177 :     /* rodata                                 */ prog->rodata,
     200         177 :     /* rodata_sz                              */ prog->rodata_sz,
     201         177 :     /* text                                   */ prog->text,
     202         177 :     /* text_cnt                               */ prog->info.text_cnt,
     203         177 :     /* text_off                               */ prog->info.text_off, /* FIXME: What if text_off is not multiple of 8 */
     204         177 :     /* text_sz                                */ prog->info.text_sz,
     205         177 :     /* entry_pc                               */ prog->entry_pc,
     206         177 :     /* calldests                              */ prog->calldests,
     207         177 :     /* sbpf_version                           */ elf_info->sbpf_version,
     208         177 :     /* syscalls                               */ syscalls,
     209             :     /* trace                                  */ NULL,
     210             :     /* sha                                    */ NULL,
     211             :     /* mem_regions                            */ NULL,
     212         177 :     /* mem_regions_cnt                        */ 0,
     213             :     /* mem_region_accs                        */ NULL,
     214         177 :     /* is_deprecated                          */ 0,
     215         177 :     /* direct mapping                         */ direct_mapping,
     216         177 :     /* syscall_parameter_address_restrictions */ syscall_parameter_address_restrictions,
     217         177 :     /* virtual_address_space_adjustments      */ virtual_address_space_adjustments,
     218         177 :     /* dump_syscall_to_pb                     */ 0,
     219         177 :     /* r2_initial_value                       */ 0UL );
     220         177 :   if ( FD_UNLIKELY( vm == NULL ) ) {
     221           0 :     FD_LOG_WARNING(( "NULL vm" ));
     222           0 :     return FD_EXECUTOR_INSTR_ERR_PROGRAM_ENVIRONMENT_SETUP_FAILURE;
     223           0 :   }
     224             : 
     225         177 :   int validate_result = fd_vm_validate( vm );
     226         177 :   if( FD_UNLIKELY( validate_result!=FD_VM_SUCCESS ) ) {
     227           1 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     228           1 :   }
     229             : 
     230         176 :   return FD_EXECUTOR_INSTR_SUCCESS;
     231         177 : }
     232             : 
     233             : int
     234             : fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx,
     235             :                    uchar const *         programdata,
     236             :                    ulong                 programdata_size,
     237         248 :                    int                   disable_sbpf_v0_v1_v2_deployment ) {
     238             :   /* The loader runs as a builtin, so its stack level holds no frame and
     239             :      can borrow one under the same rules as fd_bpf_execute. */
     240         248 :   fd_runtime_t * runtime = instr_ctx->runtime;
     241         248 :   uchar *        frame   = fd_bpf_frames_acquire( runtime->bpf_frames, fd_progcache_spill_held( runtime->progcache ) );
     242         248 :   int err = deploy_program( instr_ctx, programdata, programdata_size, disable_sbpf_v0_v1_v2_deployment, (fd_bpf_deploy_scratch_t *)frame );
     243         248 :   fd_bpf_frames_release( runtime->bpf_frames, frame );
     244         248 :   return err;
     245         248 : }
     246             : 
     247             : /* SIMD-0500 finalize gate: when the feature is active and the ELF
     248             :    embedded in `programdata` parses as SBPFv0/v1/v2, reject;
     249             :    otherwise accept (including the short-programdata case, which
     250             :    mirrors the let-chain short-circuit in agave).  See the call site
     251             :    in `process_loader_upgradeable_instruction` for the SetAuthority
     252             :    handler.
     253             :    https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/bpf_loader/src/lib.rs#L580-L591 */
     254             : int
     255             : fd_bpf_loader_finalize_v3_check( int           feature_active,
     256             :                                  uchar const * programdata,
     257          12 :                                  ulong         programdata_len ) {
     258          12 :   ulong const off = PROGRAMDATA_METADATA_SIZE + 48UL; /* ELF64 e_flags */
     259          12 :   if( !feature_active                         ) return FD_EXECUTOR_INSTR_SUCCESS;
     260           0 :   if( programdata_len < off + sizeof(uint)    ) return FD_EXECUTOR_INSTR_SUCCESS;
     261           0 :   if( FD_LOAD( uint, programdata+off )<FD_SBPF_V3 ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     262           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     263           0 : }
     264             : 
     265             : /* SIMD-0433 ProgramData sizing for the Loader V3 Upgrade instruction.
     266             :    https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.6/programs/bpf_loader/src/lib.rs#L443-L468 */
     267             : int
     268             : fd_bpf_loader_v3_upgrade_sizing( int               set_programdata_to_elf_len,
     269             :                                  ulong             programdata_current_len,
     270             :                                  ulong             buffer_data_len,
     271             :                                  fd_rent_t const * rent,
     272             :                                  ulong *           out_programdata_len,
     273         249 :                                  ulong *           out_balance_required ) {
     274         249 :   ulong programdata_len;
     275         249 :   if( set_programdata_to_elf_len ) {
     276           0 :     programdata_len      = fd_ulong_sat_add( PROGRAMDATA_METADATA_SIZE, buffer_data_len );
     277           0 :     *out_programdata_len = programdata_len;
     278           0 :     if( FD_UNLIKELY( programdata_len>MAX_PERMITTED_DATA_LENGTH ) ) {
     279           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     280           0 :     }
     281         249 :   } else {
     282         249 :     programdata_len      = programdata_current_len;
     283         249 :     *out_programdata_len = programdata_len;
     284         249 :     if( FD_UNLIKELY( programdata_len<fd_ulong_sat_add( PROGRAMDATA_METADATA_SIZE, buffer_data_len ) ) ) {
     285           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     286           0 :     }
     287         249 :   }
     288         249 :   *out_balance_required = fd_ulong_max( 1UL, fd_rent_exempt_minimum_balance( rent, programdata_len ) );
     289         249 :   return FD_EXECUTOR_INSTR_SUCCESS;
     290         249 : }
     291             : 
     292             : /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L195-L218 */
     293             : static int
     294             : write_program_data( fd_exec_instr_ctx_t *   instr_ctx,
     295             :                     ushort                  instr_acc_idx,
     296             :                     ulong                   program_data_offset,
     297             :                     uchar const *           bytes,
     298         260 :                     ulong                   bytes_len ) {
     299         260 :   int err;
     300             : 
     301             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L202 */
     302         260 :   fd_guarded_borrowed_account_t program = {0};
     303         260 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, instr_acc_idx, &program );
     304             : 
     305             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L203 */
     306         260 :   uchar * data = NULL;
     307         260 :   ulong   dlen = 0UL;
     308         260 :   err = fd_borrowed_account_get_data_mut( &program, &data, &dlen );
     309         260 :   if( FD_UNLIKELY( err ) ) {
     310           1 :     return err;
     311           1 :   }
     312             : 
     313         259 :   ulong write_offset = fd_ulong_sat_add( program_data_offset, bytes_len );
     314         259 :   if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &program )<write_offset ) ) {
     315             :     /* Max msg_sz: 24 - 6 + 2*20 = 58 < 127 => we can use printf */
     316           0 :     fd_log_collector_printf_dangerous_max_127( instr_ctx,
     317           0 :       "Write overflow: %lu < %lu", fd_borrowed_account_get_data_len( &program ), write_offset );
     318           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     319           0 :   }
     320             : 
     321         259 :   if( FD_UNLIKELY( program_data_offset>dlen ) ) {
     322           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     323           0 :   }
     324             : 
     325         259 :   if( FD_LIKELY( bytes_len ) ) {
     326         259 :     fd_memcpy( data+program_data_offset, bytes, bytes_len );
     327         259 :   }
     328             : 
     329         259 :   return FD_EXECUTOR_INSTR_SUCCESS;
     330         259 : }
     331             : 
     332             : int
     333             : fd_bpf_loader_program_get_state( fd_acc_t const * acc,
     334       23812 :                                  fd_bpf_state_t * state ) {
     335       23812 :   if( FD_UNLIKELY( fd_bpf_state_decode( state, acc->data, acc->data_len ) ) ) {
     336         632 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     337         632 :   }
     338       23180 :   return FD_EXECUTOR_INSTR_SUCCESS;
     339       23812 : }
     340             : 
     341             :   int
     342             :   fd_bpf_loader_program_get_state2( uchar const *    data,
     343             :                                     ulong            data_len,
     344       28272 :                                     fd_bpf_state_t * state ) {
     345       28272 :   if( FD_UNLIKELY( fd_bpf_state_decode( state, data, data_len ) ) ) {
     346        4034 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     347        4034 :   }
     348       24238 :   return FD_EXECUTOR_INSTR_SUCCESS;
     349       28272 : }
     350             : 
     351             : /* Mirrors solana_sdk::transaction_context::BorrowedAccount::set_state()
     352             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L973 */
     353             : int
     354             : fd_bpf_loader_v3_program_set_state( fd_borrowed_account_t * borrowed_acct,
     355        1350 :                                     fd_bpf_state_t *        state ) {
     356        1350 :   ulong state_size = fd_bpf_state_size( state );
     357             : 
     358        1350 :   uchar * data = NULL;
     359        1350 :   ulong   dlen = 0UL;
     360             : 
     361        1350 :   int err = fd_borrowed_account_get_data_mut( borrowed_acct, &data, &dlen );
     362        1350 :   if( FD_UNLIKELY( err ) ) {
     363           0 :     return err;
     364           0 :   }
     365             : 
     366        1350 :   if( FD_UNLIKELY( state_size>dlen ) ) {
     367         297 :     return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     368         297 :   }
     369             : 
     370        1053 :   ulong out_sz = 0UL;
     371        1053 :   if( FD_UNLIKELY( fd_bpf_state_encode( state, data, state_size, &out_sz ) ) ) {
     372           0 :     return FD_EXECUTOR_INSTR_ERR_GENERIC_ERR;
     373           0 :   }
     374             : 
     375        1053 :   return FD_EXECUTOR_INSTR_SUCCESS;
     376        1053 : }
     377             : 
     378             : /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1299-L1331 */
     379             : static int
     380             : common_close_account( fd_pubkey_t *         authority_address,
     381             :                       fd_exec_instr_ctx_t * instr_ctx,
     382         161 :                       fd_bpf_state_t *      state ) {
     383         161 :   int err;
     384             : 
     385             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L1307 */
     386         161 :   if( FD_UNLIKELY( !authority_address ) ) {
     387           0 :     fd_log_collector_msg_literal( instr_ctx, "Account is immutable" );
     388           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     389           0 :   }
     390             : 
     391             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L1312-L1313 */
     392         161 :   fd_pubkey_t const * acc_key = NULL;
     393         161 :   err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 2UL, &acc_key );
     394         161 :   if( FD_UNLIKELY( err ) ) {
     395           0 :     return err;
     396           0 :   }
     397             : 
     398         161 :   if( FD_UNLIKELY( memcmp( authority_address, acc_key, sizeof(fd_pubkey_t) ) ) ) {
     399          15 :     fd_log_collector_msg_literal( instr_ctx, "Incorrect authority provided" );
     400          15 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     401          15 :   }
     402             : 
     403             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L1319-L1322 */
     404         146 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 2UL, &err ) ) ) {
     405             :     /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
     406           5 :     if( FD_UNLIKELY( !!err ) ) return err;
     407           5 :     fd_log_collector_msg_literal( instr_ctx, "Authority did not sign" );
     408           5 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     409           5 :   }
     410             : 
     411             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1324 */
     412         141 :   fd_guarded_borrowed_account_t close_account = {0};
     413         141 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &close_account );
     414             : 
     415             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1326 */
     416         141 :   fd_guarded_borrowed_account_t recipient_account = {0};
     417         141 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 1UL, &recipient_account );
     418             : 
     419         141 :   err = fd_borrowed_account_checked_add_lamports( &recipient_account,
     420         141 :                                                   fd_borrowed_account_get_lamports( &close_account ) );
     421         141 :   if( FD_UNLIKELY( err ) ) {
     422           0 :     return err;
     423           0 :   }
     424             : 
     425         141 :   err = fd_borrowed_account_set_lamports( &close_account, 0UL );
     426         141 :   if( FD_UNLIKELY( err ) ) {
     427           0 :     return err;
     428           0 :   }
     429             : 
     430             :   /* https://github.com/anza-xyz/agave/blob/v4.4.0-beta.0/programs/bpf_loader/src/lib.rs#L1043 */
     431         141 :   err = fd_borrowed_account_set_data_length( &close_account, SIZE_OF_UNINITIALIZED );
     432         141 :   if( FD_UNLIKELY( err ) ) {
     433           0 :     return err;
     434           0 :   }
     435             : 
     436         141 :   state->discriminant = FD_BPF_STATE_UNINITIALIZED;
     437         141 :   err = fd_bpf_loader_v3_program_set_state( &close_account, state );
     438         141 :   if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
     439           0 :     return err;
     440           0 :   }
     441             : 
     442         141 :   return FD_EXECUTOR_INSTR_SUCCESS;
     443         141 : }
     444             : 
     445             : 
     446             : /* Every loader-owned BPF program goes through this function, which goes into the VM.
     447             : 
     448             :    https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1332-L1501 */
     449             : static int
     450             : bpf_execute( fd_exec_instr_ctx_t *      instr_ctx,
     451             :              fd_progcache_rec_t const * cache_entry,
     452        4231 :              uchar                      is_deprecated ) {
     453        4231 :   long const regime0 = fd_tickcount();
     454             : 
     455        4231 :   int err = FD_EXECUTOR_INSTR_SUCCESS;
     456             : 
     457        4231 :   uchar syscalls_mem[ FD_SBPF_SYSCALLS_FOOTPRINT ] __attribute__((aligned(FD_SBPF_SYSCALLS_ALIGN)));
     458        4231 :   fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_join( fd_sbpf_syscalls_new( syscalls_mem ) );
     459        4231 :   if( FD_UNLIKELY( !syscalls ) ) {
     460           0 :     FD_LOG_CRIT(( "Unable to allocate syscalls" ));
     461           0 :   }
     462             : 
     463             :   /* TODO do we really need to re-do this on every instruction? */
     464        4231 :   fd_vm_syscall_register_slot( syscalls,
     465        4231 :                                instr_ctx->bank->f.slot,
     466        4231 :                                &instr_ctx->bank->f.features,
     467        4231 :                                0 );
     468             : 
     469             :   /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1362-L1368 */
     470        4231 :   ulong                   input_sz                                 = 0UL;
     471        4231 :   ulong                   pre_lens[256];
     472        4231 :   fd_vm_input_region_t    input_mem_regions[1000]; /* We can have a max of (3 * num accounts + 1) regions */
     473        4231 :   fd_vm_acc_region_meta_t acc_region_metas[256];   /* instr acc idx to idx */
     474        4231 :   uint                    input_mem_regions_cnt                    = 0U;
     475        4231 :   int                     direct_mapping                           = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, account_data_direct_mapping );
     476        4231 :   int                     syscall_parameter_address_restrictions   = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, syscall_parameter_address_restrictions );
     477        4231 :   int                     virtual_address_space_adjustments        = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, virtual_address_space_adjustments );
     478        4231 :   int                     provide_instruction_data_offset_in_vm_r2 = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, provide_instruction_data_offset_in_vm_r2 );
     479        4231 :   int                     direct_account_pointers_in_program_input = FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, direct_account_pointers_in_program_input );
     480             : 
     481        4231 :   ulong instruction_data_offset = 0UL;
     482             :   /* 16-byte aligned buffer:
     483             :      https://github.com/anza-xyz/agave/blob/v3.0.0/program-runtime/src/serialization.rs#L60 */
     484        4231 :   uchar * input = instr_ctx->runtime->bpf_loader_serialization.frame[ instr_ctx->runtime->instr.stack_sz-1UL ];
     485        4231 :   err = fd_bpf_loader_input_serialize_parameters( instr_ctx, pre_lens,
     486        4231 :                                                   input_mem_regions, &input_mem_regions_cnt,
     487        4231 :                                                   acc_region_metas, virtual_address_space_adjustments, direct_mapping,
     488        4231 :                                                   direct_account_pointers_in_program_input, is_deprecated,
     489        4231 :                                                   &instruction_data_offset, &input_sz );
     490        4231 :   if( FD_UNLIKELY( err ) ) {
     491           0 :     return err;
     492           0 :   }
     493             : 
     494        4231 :   fd_sha256_t _sha[1];
     495        4231 :   fd_sha256_t * sha = fd_sha256_join( fd_sha256_new( _sha ) );
     496             : 
     497        4231 :   fd_vm_t _vm[1];
     498        4231 :   fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
     499             : 
     500        4231 :   ulong pre_insn_cus = instr_ctx->txn_out->details.compute_budget.compute_meter;
     501        4231 :   ulong heap_size    = instr_ctx->txn_out->details.compute_budget.heap_size;
     502             : 
     503             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L275-L278 */
     504        4231 :   ulong heap_cost = calculate_heap_cost( heap_size, FD_VM_HEAP_COST );
     505        4231 :   int heap_cost_result = fd_executor_consume_cus( instr_ctx->txn_out, heap_cost );
     506        4231 :   if( FD_UNLIKELY( heap_cost_result ) ) {
     507           0 :     return FD_EXECUTOR_INSTR_ERR_PROGRAM_ENVIRONMENT_SETUP_FAILURE;
     508           0 :   }
     509             : 
     510             :   /* For dumping syscalls for seed corpora */
     511        4231 :   int dump_syscall_to_pb = instr_ctx->runtime->log.dump_proto_ctx &&
     512        4231 :                            instr_ctx->bank->f.slot>=instr_ctx->runtime->log.dump_proto_ctx->dump_proto_start_slot &&
     513        4231 :                            instr_ctx->runtime->log.dump_proto_ctx->dump_syscall_to_pb;
     514             : 
     515             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/bpf_loader/src/lib.rs#L1525-L1528 */
     516        4231 :   ulong r2_initial_value = provide_instruction_data_offset_in_vm_r2 ? instruction_data_offset : 0UL;
     517             : 
     518             :   /* TODO: (topointon): correctly set check_size in vm setup */
     519        4231 :   fd_wksp_t * progcache_wksp = instr_ctx->runtime->progcache->join->data_base;
     520        4231 :   void const * rodata = fd_progcache_rec_rodata( cache_entry, progcache_wksp );
     521        4231 :   vm = fd_vm_init(
     522        4231 :     /* vm                                     */ vm,
     523        4231 :     /* instr_ctx                              */ instr_ctx,
     524        4231 :     /* heap_max                               */ heap_size,
     525        4231 :     /* entry_cu                               */ instr_ctx->txn_out->details.compute_budget.compute_meter,
     526        4231 :     /* rodata                                 */ rodata,
     527        4231 :     /* rodata_sz                              */ cache_entry->rodata_sz,
     528        4231 :     /* text (note: text_off is byte offset)   */ (ulong *)( (ulong)rodata + cache_entry->text_off ),
     529        4231 :     /* text_cnt                               */ cache_entry->text_cnt,
     530        4231 :     /* text_off                               */ cache_entry->text_off,
     531        4231 :     /* text_sz                                */ cache_entry->text_sz,
     532        4231 :     /* entry_pc                               */ cache_entry->entry_pc,
     533        4231 :     /* calldests                              */ fd_progcache_rec_calldests( cache_entry, progcache_wksp ),
     534        4231 :     /* sbpf_version                           */ cache_entry->sbpf_version,
     535        4231 :     /* syscalls                               */ syscalls,
     536             :     /* trace                                  */ NULL,
     537        4231 :     /* sha                                    */ sha,
     538        4231 :     /* input_mem_regions                      */ input_mem_regions,
     539        4231 :     /* input_mem_regions_cnt                  */ input_mem_regions_cnt,
     540        4231 :     /* acc_region_metas                       */ acc_region_metas,
     541        4231 :     /* is_deprecated                          */ is_deprecated,
     542        4231 :     /* direct_mapping                         */ direct_mapping,
     543        4231 :     /* syscall_parameter_address_restrictions */ syscall_parameter_address_restrictions,
     544        4231 :     /* virtual_address_space_adjustments      */ virtual_address_space_adjustments,
     545        4231 :     /* dump_syscall_to_pb                     */ dump_syscall_to_pb,
     546        4231 :     /* r2_initial_value                       */ r2_initial_value );
     547        4231 :   if( FD_UNLIKELY( !vm ) ) {
     548             :     /* We throw an error here because it could be the case that the given heap_size > HEAP_MAX.
     549             :        In this case, Agave fails the transaction but does not error out.
     550             : 
     551             :        https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1396 */
     552           0 :     return FD_EXECUTOR_INSTR_ERR_PROGRAM_ENVIRONMENT_SETUP_FAILURE;
     553           0 :   }
     554             : 
     555        4231 :   if( FD_UNLIKELY( instr_ctx->runtime->log.enable_vm_tracing && instr_ctx->runtime->log.tracing_mem ) ) {
     556           0 :     vm->trace = fd_vm_trace_join( fd_vm_trace_new( instr_ctx->runtime->log.tracing_mem + ((instr_ctx->runtime->instr.stack_sz-1UL) * FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT), FD_RUNTIME_VM_TRACE_EVENT_MAX ));
     557           0 :     if( FD_UNLIKELY( !vm->trace ) ) FD_LOG_ERR(( "unable to create trace; make sure you've compiled with sufficient spad size " ));
     558           0 :   }
     559             : 
     560        4231 :   long const regime1 = fd_tickcount();
     561             : 
     562        4231 :   int exec_err = fd_vm_exec( vm );
     563        4231 :   instr_ctx->txn_out->details.compute_budget.compute_meter = vm->cu;
     564             : 
     565        4231 :   long const regime2 = fd_tickcount();
     566             : 
     567        4231 :   if( instr_ctx->instr->stack_height==1 ) {
     568        3600 :     instr_ctx->runtime->metrics.vm_setup_cum_ticks  += (ulong)( regime1-regime0 );
     569        3600 :     instr_ctx->runtime->metrics.vm_exec_cum_ticks   += (ulong)( regime2-regime1 );
     570        3600 :   } else {
     571         631 :     instr_ctx->runtime->metrics.cpi_setup_cum_ticks += (ulong)( regime1-regime0 );
     572         631 :   }
     573             : 
     574        4231 :   if( FD_UNLIKELY( vm->trace ) ) {
     575           0 :     err = fd_vm_trace_printf( vm->trace );
     576           0 :     if( FD_UNLIKELY( err ) ) {
     577           0 :       FD_LOG_WARNING(( "fd_vm_trace_printf failed (%i-%s)", err, fd_vm_strerror( err ) ));
     578           0 :     }
     579           0 :   }
     580             : 
     581             :   /* Log consumed compute units and return data.
     582             :      https://github.com/anza-xyz/agave/blob/v4.3.0/program-runtime/src/vm.rs#L347-L353 */
     583        4231 :   fd_log_collector_program_consumed( instr_ctx, pre_insn_cus-heap_cost-vm->cu, pre_insn_cus );
     584        4231 :   if( FD_UNLIKELY( instr_ctx->txn_out->details.return_data.len ) ) {
     585         150 :     fd_log_collector_program_return( instr_ctx );
     586         150 :   }
     587             : 
     588             :   /* We have a big error-matching arm here
     589             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1674-L1744 */
     590             : 
     591             :   /* Handle non-zero return status with successful VM execution. This is
     592             :      the Ok(status) case, hence exec_err must be 0 for this case to be hit.
     593             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1675-L1678 */
     594        4231 :   if( FD_LIKELY( !exec_err ) ) {
     595        1635 :     ulong status = vm->reg[0];
     596        1635 :     if( FD_UNLIKELY( status ) ) {
     597          47 :       err = program_error_to_instr_error( status, &instr_ctx->txn_out->err.custom_err );
     598          47 :       FD_VM_PREPARE_ERR_OVERWRITE( vm );
     599          47 :       FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     600          47 :       return err;
     601          47 :     }
     602        2596 :   } else {
     603             :     /* https://github.com/anza-xyz/agave/blob/v2.1.13/programs/bpf_loader/src/lib.rs#L1434-L1439 */
     604             :     /* (SIMD-182) Consume ALL requested CUs on non-Syscall errors */
     605        2596 :     if( FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, deplete_cu_meter_on_vm_failure ) &&
     606        2596 :         exec_err!=FD_VM_ERR_EBPF_SYSCALL_ERROR ) {
     607           0 :       instr_ctx->txn_out->details.compute_budget.compute_meter = 0UL;
     608           0 :     }
     609             : 
     610             :     /* With virtual_address_space_adjustments, remap load and store
     611             :        access violations to more specific account errors.
     612             :        https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1556-L1618 */
     613        2596 :     if( FD_UNLIKELY( virtual_address_space_adjustments &&
     614        2596 :                      ( exec_err==FD_VM_ERR_EBPF_ACCESS_VIOLATION || instr_ctx->txn_out->err.exec_err==FD_VM_ERR_EBPF_ACCESS_VIOLATION ) &&
     615        2596 :                      vm->segv_vaddr!=ULONG_MAX ) ) {
     616             : 
     617             :       /* If the vaddr of the access violation falls within the bounds of a
     618             :          serialized account vaddr range, then try to retrieve a more specific
     619             :          vm error based on the account's access permissions. */
     620         796 :       for( ushort i=0UL; i<instr_ctx->instr->acct_cnt; i++ ) {
     621             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1455 */
     622             : 
     623             :         /* Find the input memory region that corresponds to the access
     624             :            https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1566-L1617 */
     625         784 :         ulong idx = acc_region_metas[i].region_idx;
     626         784 :         fd_vm_input_region_t const * input_mem_region = &input_mem_regions[idx];
     627         784 :         fd_vm_acc_region_meta_t const * acc_region_meta = &acc_region_metas[i];
     628             : 
     629             :         /* https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1484-L1492 */
     630         784 :         ulong region_data_vaddr_start = FD_VM_MEM_MAP_INPUT_REGION_START + input_mem_region->vaddr_offset + input_mem_region->region_sz;
     631         784 :         ulong region_data_vaddr_end   = fd_ulong_sat_add( region_data_vaddr_start, acc_region_meta->original_data_len );
     632         784 :         if( FD_LIKELY( !is_deprecated ) ) {
     633         432 :           region_data_vaddr_end       = fd_ulong_sat_add( region_data_vaddr_end, MAX_PERMITTED_DATA_INCREASE );
     634         432 :         }
     635             : 
     636         784 :         if( vm->segv_vaddr >= region_data_vaddr_start && vm->segv_vaddr <= region_data_vaddr_end ) {
     637             : 
     638             :           /* https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1575-L1616 */
     639           5 :           fd_guarded_borrowed_account_t instr_acc = {0};
     640           5 :           FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, i, &instr_acc );
     641             : 
     642             :           /* https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1581-L1616 */
     643           5 :           if( fd_ulong_sat_add( vm->segv_vaddr, vm->segv_access_len ) <= region_data_vaddr_end ) {
     644             :             /* https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1592-L1601 */
     645           4 :             if( vm->segv_access_type==FD_VM_ACCESS_TYPE_ST ) {
     646           1 :               int borrow_err = FD_EXECUTOR_INSTR_SUCCESS;
     647           1 :               if( !fd_borrowed_account_can_data_be_changed( &instr_acc, &borrow_err ) || borrow_err != FD_EXECUTOR_INSTR_SUCCESS ) {
     648           1 :                 err = borrow_err;
     649           1 :               } else {
     650           0 :                 err = FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     651           0 :               }
     652           3 :             } else if( vm->segv_access_type==FD_VM_ACCESS_TYPE_LD ) {
     653           3 :               int borrow_err = FD_EXECUTOR_INSTR_SUCCESS;
     654           3 :               if( !fd_borrowed_account_can_data_be_changed( &instr_acc, &borrow_err ) || borrow_err != FD_EXECUTOR_INSTR_SUCCESS ) {
     655           3 :                 err = FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     656           3 :               } else {
     657           0 :                 err = FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     658           0 :               }
     659           3 :             } else {
     660           0 :               FD_LOG_CRIT(( "invariant violation: unsupported access type: %i", vm->segv_access_type ));
     661           0 :             }
     662             : 
     663           4 :             FD_VM_PREPARE_ERR_OVERWRITE( vm );
     664           4 :             FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     665           4 :             return err;
     666           4 :           }
     667           5 :         }
     668         784 :       }
     669          16 :     }
     670             : 
     671             :     /* The error kind should have been set in the VM. Match it and set
     672             :        the error code accordingly. There are no direct permalinks here -
     673             :        this is all a result of Agave's complex nested error-code handling
     674             :        and our design decisions for making our error codes match. */
     675             : 
     676             :     /* Instr error case. Set the error kind and return the instruction error */
     677        2592 :     if( instr_ctx->txn_out->err.exec_err_kind==FD_EXECUTOR_ERR_KIND_INSTR ) {
     678         575 :       err = instr_ctx->txn_out->err.exec_err;
     679         575 :       FD_VM_PREPARE_ERR_OVERWRITE( vm );
     680         575 :       FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     681         575 :       return err;
     682         575 :     }
     683             : 
     684             :     /* Syscall error case. The VM would have also set the syscall error
     685             :        code in the txn_ctx exec_err. */
     686        2017 :     if( instr_ctx->txn_out->err.exec_err_kind==FD_EXECUTOR_ERR_KIND_SYSCALL ) {
     687         317 :       err = instr_ctx->txn_out->err.exec_err;
     688         317 :       FD_VM_PREPARE_ERR_OVERWRITE( vm );
     689         317 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, err );
     690         317 :       return FD_EXECUTOR_INSTR_ERR_PROGRAM_FAILED_TO_COMPLETE;
     691         317 :     }
     692             : 
     693             :     /* An access violation that takes place inside a syscall will
     694             :        cause `exec_res` to be set to EbpfError::SyscallError,
     695             :       'but the `txn_ctx->err.exec_err_kind` will be set to EBPF and
     696             :        `txn_ctx->err.exec_err` will be set to the EBPF error. In this
     697             :        specific case, there is nothing to do since the error and error
     698             :        kind area already set correctly. Otherwise, we need to log the
     699             :        EBPF error. */
     700        1700 :     if( exec_err!=FD_VM_ERR_EBPF_SYSCALL_ERROR ) {
     701        1646 :       FD_VM_PREPARE_ERR_OVERWRITE( vm );
     702        1646 :       FD_VM_ERR_FOR_LOG_EBPF( vm, exec_err );
     703        1646 :     }
     704             : 
     705        1700 :     return FD_EXECUTOR_INSTR_ERR_PROGRAM_FAILED_TO_COMPLETE;
     706        2017 :   }
     707             : 
     708        1588 :   err = fd_bpf_loader_input_deserialize_parameters(
     709        1588 :     instr_ctx, pre_lens, input, input_sz, virtual_address_space_adjustments, direct_mapping, is_deprecated );
     710             : 
     711        1588 :   long const regime3 = fd_tickcount();
     712        1588 :   if( instr_ctx->instr->stack_height==1 ) {
     713        1217 :     instr_ctx->runtime->metrics.vm_commit_cum_ticks += (ulong)( regime3-regime2 );
     714        1217 :   } else {
     715         371 :     instr_ctx->runtime->metrics.cpi_commit_cum_ticks  += (ulong)( regime3-regime2 );
     716         371 :   }
     717             : 
     718        1588 :   return err;
     719        4231 : }
     720             : 
     721             : int
     722             : fd_bpf_execute( fd_exec_instr_ctx_t *      instr_ctx,
     723             :                 fd_progcache_rec_t const * cache_entry,
     724        4231 :                 uchar                      is_deprecated ) {
     725             :   /* Tiles holding frames can wait on the program cache spill lock, so
     726             :      its holder must never wait for a frame. */
     727        4231 :   fd_runtime_t * runtime = instr_ctx->runtime;
     728        4231 :   uchar *        frame   = fd_bpf_frames_acquire( runtime->bpf_frames, fd_progcache_spill_held( runtime->progcache ) );
     729        4231 :   runtime->bpf_loader_serialization.frame[ runtime->instr.stack_sz-1UL ] = frame;
     730        4231 :   int err = bpf_execute( instr_ctx, cache_entry, is_deprecated );
     731        4231 :   fd_bpf_frames_release( runtime->bpf_frames, frame );
     732        4231 :   return err;
     733        4231 : }
     734             : 
     735             : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1358-L1539 */
     736             : static int
     737             : common_extend_program( fd_exec_instr_ctx_t * instr_ctx,
     738             :                        uint                  additional_bytes,
     739         381 :                        uchar                 check_authority ) {
     740         381 :   int err;
     741             : 
     742             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1366 */
     743         381 :   fd_pubkey_t const * program_id = NULL;
     744         381 :   err = fd_exec_instr_ctx_get_last_program_key( instr_ctx, &program_id );
     745         381 :   if( FD_UNLIKELY( err ) ) {
     746           0 :     return err;
     747           0 :   }
     748             : 
     749             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1368-L1370 */
     750         381 :   #define PROGRAM_DATA_ACCOUNT_INDEX (0)
     751         381 :   #define PROGRAM_ACCOUNT_INDEX      (1)
     752         381 :   #define AUTHORITY_ACCOUNT_INDEX    (2)
     753             : 
     754             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1371-L1372 */
     755         381 :   uchar optional_payer_account_index = check_authority ? 4 : 3;
     756             : 
     757             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1374-L1377 */
     758         381 :   if( FD_UNLIKELY( additional_bytes==0U ) ) {
     759           0 :     fd_log_collector_msg_literal( instr_ctx, "Additional bytes must be greater than 0" );
     760           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     761           0 :   }
     762             : 
     763             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1379-L1381 */
     764         381 :   fd_guarded_borrowed_account_t programdata_account = {0};
     765         381 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, PROGRAM_DATA_ACCOUNT_INDEX, &programdata_account );
     766         381 :   fd_pubkey_t const * programdata_key = (fd_pubkey_t*)programdata_account.acc->pubkey;
     767             : 
     768             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1383-L1386 */
     769         381 :   if( FD_UNLIKELY( memcmp( program_id, fd_borrowed_account_get_owner( &programdata_account ), sizeof(fd_pubkey_t) ) ) ) {
     770           7 :     fd_log_collector_msg_literal( instr_ctx, "ProgramData owner is invalid" );
     771           7 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     772           7 :   }
     773             : 
     774             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1387-L1390 */
     775         374 :   if( FD_UNLIKELY( !fd_borrowed_account_is_writable( &programdata_account ) ) ) {
     776           0 :     fd_log_collector_msg_literal( instr_ctx, "ProgramData is not writable" );
     777           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     778           0 :   }
     779             : 
     780             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1392-L1393 */
     781         374 :   fd_guarded_borrowed_account_t program_account = {0};
     782         374 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, PROGRAM_ACCOUNT_INDEX, &program_account );
     783             : 
     784             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1394-L1397 */
     785         374 :   if( FD_UNLIKELY( !fd_borrowed_account_is_writable( &program_account ) ) ) {
     786           0 :     fd_log_collector_msg_literal( instr_ctx, "Program account is not writable" );
     787           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     788           0 :   }
     789             : 
     790             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1398-L1401 */
     791         374 :   if( FD_UNLIKELY( memcmp( program_id, fd_borrowed_account_get_owner( &program_account ), sizeof(fd_pubkey_t) ) ) ) {
     792           1 :     fd_log_collector_msg_literal( instr_ctx, "Program account not owned by loader" );
     793           1 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     794           1 :   }
     795             : 
     796             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1403-L1419 */
     797         373 :   fd_bpf_state_t program_state[1];
     798         373 :   err = fd_bpf_loader_program_get_state( program_account.acc, program_state );
     799         373 :   if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
     800           0 :     return err;
     801           0 :   }
     802             : 
     803         373 :   if( program_state->discriminant==FD_BPF_STATE_PROGRAM ) {
     804         373 :     if( FD_UNLIKELY( memcmp( &program_state->inner.program.programdata_address, programdata_key, sizeof(fd_pubkey_t) ) ) ) {
     805          83 :       fd_log_collector_msg_literal( instr_ctx, "Program account does not match ProgramData account" );
     806          83 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     807          83 :     }
     808         373 :   } else {
     809           0 :     fd_log_collector_msg_literal( instr_ctx, "Invalid Program account" );
     810           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     811           0 :   }
     812             : 
     813             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1420 */
     814         290 :   fd_borrowed_account_drop( &program_account );
     815             : 
     816             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1422-L1432 */
     817         290 :   ulong old_len = fd_borrowed_account_get_data_len( &programdata_account );
     818         290 :   ulong new_len = fd_ulong_sat_add( old_len, additional_bytes );
     819         290 :   if( FD_UNLIKELY( new_len>MAX_PERMITTED_DATA_LENGTH ) ) {
     820             :     /* Max msg_sz: 85 - 6 + 2*20 = 119 < 127 => we can use printf */
     821           0 :     fd_log_collector_printf_dangerous_max_127( instr_ctx,
     822           0 :       "Extended ProgramData length of %lu bytes exceeds max account data length of %lu bytes", new_len, MAX_PERMITTED_DATA_LENGTH );
     823           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     824           0 :   }
     825             : 
     826             :   /* https://github.com/anza-xyz/agave/blob/v4.1.0-beta.1/programs/bpf_loader/src/lib.rs#L861-L883 */
     827         290 :   if( FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, loader_v3_minimum_extend_program_size ) ) {
     828         290 :     ulong headroom = fd_ulong_sat_sub( MAX_PERMITTED_DATA_LENGTH, old_len );
     829         290 :     if( FD_UNLIKELY( additional_bytes<MINIMUM_EXTEND_PROGRAM_BYTES && additional_bytes!=headroom ) ) {
     830             :       /* Max msg_sz: 113 - (3+2) + (5+10) = 123 < 127 => we can use printf */
     831         288 :       fd_log_collector_printf_dangerous_max_127(
     832         288 :         instr_ctx,
     833         288 :         "ExtendProgram requires a minimum of %lu additional bytes or to extend to maximum size, but only %u were requested",
     834         288 :         MINIMUM_EXTEND_PROGRAM_BYTES,
     835         288 :         additional_bytes
     836         288 :       );
     837         288 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     838         288 :     }
     839         290 :   }
     840             : 
     841             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1434-L1437 */
     842           2 :   fd_sol_sysvar_clock_t clock[1];
     843           2 :   if( FD_UNLIKELY( !fd_sysvar_cache_clock_read( instr_ctx->sysvar_cache, clock ) ) ) {
     844           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     845           0 :   }
     846           2 :   ulong clock_slot = clock->slot;
     847             : 
     848             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1439-L1478 */
     849           2 :   fd_pubkey_t * upgrade_authority_address = NULL;
     850           2 :   fd_bpf_state_t programdata_state[1];
     851           2 :   err = fd_bpf_loader_program_get_state( programdata_account.acc, programdata_state );
     852           2 :   if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
     853           0 :     return err;
     854           0 :   }
     855           2 :   if( programdata_state->discriminant==FD_BPF_STATE_PROGRAM_DATA ) {
     856             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1444-L1447 */
     857           2 :     if( FD_UNLIKELY( clock_slot==programdata_state->inner.program_data.slot ) ) {
     858           0 :       fd_log_collector_msg_literal( instr_ctx, "Program was extended in this block already" );
     859           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     860           0 :     }
     861             : 
     862             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1449-L1455 */
     863           2 :     if( FD_UNLIKELY( !programdata_state->inner.program_data.has_upgrade_authority_address ) ) {
     864           0 :       fd_log_collector_msg_literal( instr_ctx, "Cannot extend ProgramData accounts that are not upgradeable" );
     865           0 :       return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     866           0 :     }
     867             : 
     868             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1457-L1472 */
     869           2 :     if( check_authority ) {
     870             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1458-L1463 */
     871           0 :       fd_pubkey_t const * authority_key = NULL;
     872           0 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, AUTHORITY_ACCOUNT_INDEX, &authority_key );
     873           0 :       if( FD_UNLIKELY( err ) ) {
     874           0 :         return err;
     875           0 :       }
     876             : 
     877             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1464-L1467 */
     878           0 :       if( FD_UNLIKELY( !fd_pubkey_eq( &programdata_state->inner.program_data.upgrade_authority_address, authority_key ) ) ) {
     879           0 :         fd_log_collector_msg_literal( instr_ctx, "Incorrect upgrade authority provided" );
     880           0 :         return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     881           0 :       }
     882             : 
     883             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1468-L1471 */
     884           0 :       if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, AUTHORITY_ACCOUNT_INDEX, &err ) ) ) {
     885             :         /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
     886           0 :         if( FD_UNLIKELY( !!err ) ) return err;
     887           0 :         fd_log_collector_msg_literal( instr_ctx, "Upgrade authority did not sign" );
     888           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     889           0 :       }
     890           0 :     }
     891             : 
     892             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1474 */
     893           2 :     fd_bpf_state_program_data_t * pd = &programdata_state->inner.program_data;
     894           2 :     upgrade_authority_address = pd->has_upgrade_authority_address ? &pd->upgrade_authority_address : NULL;
     895           2 :   } else {
     896             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1476-L1477 */
     897           0 :     fd_log_collector_msg_literal( instr_ctx, "ProgramData state is invalid" );
     898           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     899           0 :   }
     900             : 
     901             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1480-L1485 */
     902           2 :   fd_rent_t rent_;
     903           2 :   fd_rent_t const * rent = fd_sysvar_cache_rent_read( instr_ctx->sysvar_cache, &rent_ );
     904           2 :   if( FD_UNLIKELY( !rent ) ) {
     905           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     906           0 :   }
     907             : 
     908           2 :   ulong balance          = fd_borrowed_account_get_lamports( &programdata_account );
     909           2 :   ulong min_balance      = fd_ulong_max( fd_rent_exempt_minimum_balance( rent, new_len ), 1UL );
     910           2 :   ulong required_payment = fd_ulong_sat_sub( min_balance, balance );
     911             : 
     912             :   /* Borrowed accounts need to be dropped before native invocations. Note:
     913             :      the programdata account is manually released and acquired within the
     914             :      extend instruction to preserve the local variable scoping to maintain
     915             :      readability. The scoped macro still successfully handles the case of
     916             :      freeing a write lock in case of an early termination. */
     917             : 
     918             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1488 */
     919           2 :   fd_borrowed_account_drop( &programdata_account );
     920             : 
     921             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1492-L1502 */
     922           2 :   if( FD_UNLIKELY( required_payment>0UL ) ) {
     923             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1493-L1496 */
     924           2 :     fd_pubkey_t const * payer_key = NULL;
     925           2 :     err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, optional_payer_account_index, &payer_key );
     926           2 :     if( FD_UNLIKELY( err ) ) {
     927           0 :       return err;
     928           0 :     }
     929             : 
     930             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1498-L1501 */
     931           2 :     uchar instr_data[FD_TXN_MTU];
     932           2 :     fd_system_program_instruction_t instr = {
     933           2 :       .discriminant = FD_SYSTEM_PROGRAM_INSTR_TRANSFER,
     934           2 :       .inner = {
     935           2 :         .transfer = required_payment
     936           2 :       }
     937           2 :     };
     938             : 
     939           2 :     ulong instr_data_sz;
     940           2 :     int err = fd_system_program_instruction_encode( &instr, instr_data, FD_TXN_MTU, &instr_data_sz );
     941           2 :     if( FD_UNLIKELY( err ) ) {
     942           0 :       FD_LOG_CRIT(( "Failed to encode SystemInstruction with error %d", err ));
     943           0 :     }
     944             : 
     945           2 :     fd_vm_rust_account_meta_t acct_metas[ 2UL ];
     946           2 :     fd_native_cpi_create_account_meta( payer_key,       1UL, 1UL, &acct_metas[ 0UL ] );
     947           2 :     fd_native_cpi_create_account_meta( programdata_key, 0UL, 1UL, &acct_metas[ 1UL ] );
     948             : 
     949           2 :     err = fd_native_cpi_native_invoke( instr_ctx,
     950           2 :                                        &fd_solana_system_program_id,
     951           2 :                                        instr_data,
     952           2 :                                        instr_data_sz,
     953           2 :                                        acct_metas,
     954           2 :                                        2UL,
     955           2 :                                        NULL,
     956           2 :                                        0UL );
     957           2 :     if( FD_UNLIKELY( err ) ) {
     958           2 :       return err;
     959           2 :     }
     960           2 :   }
     961             : 
     962             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1506-L1507 */
     963           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, PROGRAM_DATA_ACCOUNT_INDEX, &programdata_account );
     964             : 
     965             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1508 */
     966           0 :   err = fd_borrowed_account_set_data_length( &programdata_account, new_len );
     967           0 :   if( FD_UNLIKELY( err ) ) {
     968           0 :     return err;
     969           0 :   }
     970             : 
     971             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1510 */
     972           0 :   ulong programdata_data_offset = PROGRAMDATA_METADATA_SIZE;
     973             : 
     974             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1517-L1520 */
     975           0 :   if( FD_UNLIKELY( programdata_data_offset>fd_borrowed_account_get_data_len( &programdata_account ) ) ) {
     976           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     977           0 :   }
     978           0 :   uchar const * programdata_data = fd_borrowed_account_get_data( &programdata_account ) + programdata_data_offset;
     979           0 :   ulong         programdata_size = new_len - PROGRAMDATA_METADATA_SIZE;
     980             : 
     981             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1512-L1522 */
     982             :   /* SIMD-0500: extend_program is exempt from the deployment-version gate. */
     983           0 :   err = fd_deploy_program( instr_ctx, programdata_data, programdata_size, /* disable_sbpf_v0_v1_v2_deployment */ 0 );
     984           0 :   if( FD_UNLIKELY( err ) ) {
     985           0 :     return err;
     986           0 :   }
     987             : 
     988             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1523 */
     989           0 :   fd_borrowed_account_drop( &programdata_account );
     990             : 
     991             :   /* Setting the discriminant and upgrade authority address here can likely
     992             :      be a no-op because these values shouldn't change. These can probably be
     993             :      removed, but can help to mirror against Agave client's implementation.
     994             :      The set_state function also contains an ownership check. */
     995             : 
     996             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1525-L1526 */
     997           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &programdata_account );
     998             : 
     999             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1527-L1530 */
    1000           0 :   programdata_state->discriminant            = FD_BPF_STATE_PROGRAM_DATA;
    1001           0 :   programdata_state->inner.program_data.slot = clock_slot;
    1002           0 :   programdata_state->inner.program_data.has_upgrade_authority_address = !!upgrade_authority_address;
    1003           0 :   if( upgrade_authority_address ) programdata_state->inner.program_data.upgrade_authority_address = *upgrade_authority_address;
    1004             : 
    1005           0 :   err = fd_bpf_loader_v3_program_set_state( &programdata_account, programdata_state );
    1006           0 :   if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1007           0 :     return err;
    1008           0 :   }
    1009           0 :   programdata_account.acc->pd_write = 1;
    1010             : 
    1011             :   /* Max msg_sz: 41 - 2 + 20 = 57 < 127 => we can use printf
    1012             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1532-L1536 */
    1013           0 :   fd_log_collector_printf_dangerous_max_127( instr_ctx,
    1014           0 :     "Extended ProgramData account by %u bytes", additional_bytes );
    1015             : 
    1016             :   /* programdata account is dropped when it goes out of scope */
    1017             : 
    1018           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1019             : 
    1020           0 :   #undef PROGRAM_DATA_ACCOUNT_INDEX
    1021           0 :   #undef PROGRAM_ACCOUNT_INDEX
    1022           0 :   #undef AUTHORITY_ACCOUNT_INDEX
    1023           0 : }
    1024             : 
    1025             : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L566-L1444 */
    1026             : static int
    1027        3704 : process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) {
    1028        3704 :   fd_bpf_instruction_t instruction[1] = {0};
    1029        3704 :   if( FD_UNLIKELY( fd_bpf_instruction_decode(
    1030        3704 :       instruction,
    1031        3704 :       instr_ctx->instr->data,
    1032        3704 :       instr_ctx->instr->data_sz ) ) ) {
    1033          51 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1034          51 :   }
    1035             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/bpf_loader/src/lib.rs#L510 */
    1036        3653 :   fd_pubkey_t const * program_id = NULL;
    1037        3653 :   int err = fd_exec_instr_ctx_get_last_program_key( instr_ctx, &program_id );
    1038        3653 :   if( FD_UNLIKELY( err ) ) {
    1039           0 :     return err;
    1040           0 :   }
    1041             : 
    1042        3653 :   switch( instruction->discriminant ) {
    1043             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L476-L493 */
    1044         311 :     case FD_BPF_INSTR_INITIALIZE_BUFFER: {
    1045         311 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 2U ) ) ) {
    1046           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1047           0 :       }
    1048             : 
    1049             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L479 */
    1050         311 :       fd_guarded_borrowed_account_t buffer = {0};
    1051         311 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &buffer );
    1052             : 
    1053         311 :       fd_bpf_state_t buffer_state[1];
    1054         311 :       err = fd_bpf_loader_program_get_state( buffer.acc, buffer_state );
    1055         311 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1056           0 :         return err;
    1057           0 :       }
    1058             : 
    1059         311 :       if( FD_UNLIKELY( buffer_state->discriminant!=FD_BPF_STATE_UNINITIALIZED ) ) {
    1060           0 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account already initialized" );
    1061           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
    1062           0 :       }
    1063             : 
    1064             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L487-L489 */
    1065         311 :       fd_pubkey_t const * authority_key = NULL;
    1066         311 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 1UL, &authority_key );
    1067         311 :       if( FD_UNLIKELY( err ) ) {
    1068           0 :         return err;
    1069           0 :       }
    1070             : 
    1071         311 :       buffer_state->discriminant                       = FD_BPF_STATE_BUFFER;
    1072         311 :       buffer_state->inner.buffer.has_authority_address = 1;
    1073         311 :       buffer_state->inner.buffer.authority_address     = *authority_key;
    1074             : 
    1075         311 :       err = fd_bpf_loader_v3_program_set_state( &buffer, buffer_state );
    1076         311 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1077         297 :         return err;
    1078         297 :       }
    1079             : 
    1080             :       /* implicit drop of buffer account */
    1081             : 
    1082          14 :       break;
    1083         311 :     }
    1084             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L494-L525 */
    1085         278 :     case FD_BPF_INSTR_WRITE: {
    1086         278 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 2U ) ) ) {
    1087           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1088           0 :       }
    1089             : 
    1090             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L497 */
    1091         278 :       fd_guarded_borrowed_account_t buffer = {0};
    1092         278 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &buffer );
    1093             : 
    1094         278 :       fd_bpf_state_t loader_state[1];
    1095         278 :       err = fd_bpf_loader_program_get_state( buffer.acc, loader_state );
    1096         278 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1097          16 :         return err;
    1098          16 :       }
    1099             : 
    1100         262 :       if( loader_state->discriminant==FD_BPF_STATE_BUFFER ) {
    1101         262 :         if( FD_UNLIKELY( !loader_state->inner.buffer.has_authority_address ) ) {
    1102           0 :           fd_log_collector_msg_literal( instr_ctx, "Buffer is immutable" );
    1103           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
    1104           0 :         }
    1105             : 
    1106             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L505-L507 */
    1107         262 :         fd_pubkey_t const * authority_key = NULL;
    1108         262 :         err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 1UL, &authority_key );
    1109         262 :         if( FD_UNLIKELY( err ) ) {
    1110           0 :           return err;
    1111           0 :         }
    1112             : 
    1113         262 :         if( FD_UNLIKELY( !fd_pubkey_eq( &loader_state->inner.buffer.authority_address, authority_key ) ) ) {
    1114           1 :           fd_log_collector_msg_literal( instr_ctx, "Incorrect buffer authority provided" );
    1115           1 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1116           1 :         }
    1117         261 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 1UL, &err ) ) ) {
    1118             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1119           1 :           if( FD_UNLIKELY( !!err ) ) return err;
    1120           1 :           fd_log_collector_msg_literal( instr_ctx, "Buffer authority did not sign" );
    1121           1 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1122           1 :         }
    1123         261 :       } else {
    1124           0 :         fd_log_collector_msg_literal( instr_ctx, "Invalid Buffer account" );
    1125           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1126           0 :       }
    1127             : 
    1128             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L520 */
    1129         260 :       fd_borrowed_account_drop( &buffer );
    1130             : 
    1131         260 :       ulong program_data_offset = fd_ulong_sat_add( BUFFER_METADATA_SIZE, instruction->inner.write.offset );
    1132         260 :       err = write_program_data( instr_ctx,
    1133         260 :                                 0UL,
    1134         260 :                                 program_data_offset,
    1135         260 :                                 instruction->inner.write.bytes,
    1136         260 :                                 instruction->inner.write.bytes_len );
    1137         260 :       if( FD_UNLIKELY( err ) ) {
    1138           1 :         return err;
    1139           1 :       }
    1140             : 
    1141         259 :       break;
    1142         260 :     }
    1143             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L526-L702 */
    1144         360 :     case FD_BPF_INSTR_DEPLOY_WITH_MAX_DATA_LEN: {
    1145             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L527-L541 */
    1146         360 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 4U ) ) ) {
    1147           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1148           0 :       }
    1149             : 
    1150             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L529-L534 */
    1151         360 :       fd_pubkey_t const * payer_key       = NULL;
    1152         360 :       fd_pubkey_t const * programdata_key = NULL;
    1153             : 
    1154         360 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 0UL, &payer_key );
    1155         360 :       if( FD_UNLIKELY( err ) ) {
    1156           0 :         return err;
    1157           0 :       }
    1158             : 
    1159         360 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 1UL, &programdata_key );
    1160         360 :       if( FD_UNLIKELY( err ) ) {
    1161           0 :         return err;
    1162           0 :       }
    1163             : 
    1164         360 :       err = fd_sysvar_instr_acct_check( instr_ctx, 4UL, &fd_sysvar_rent_id );
    1165         360 :       if( FD_UNLIKELY( err ) ) {
    1166           2 :         return err;
    1167           2 :       }
    1168             : 
    1169         358 :       fd_rent_t rent_;
    1170         358 :       fd_rent_t const * rent = fd_sysvar_cache_rent_read( instr_ctx->sysvar_cache, &rent_ );
    1171         358 :       if( FD_UNLIKELY( !rent ) ) {
    1172           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1173           0 :       }
    1174             : 
    1175         358 :       err = fd_sysvar_instr_acct_check( instr_ctx, 5UL, &fd_sysvar_clock_id );
    1176         358 :       if( FD_UNLIKELY( err ) ) {
    1177          22 :         return err;
    1178          22 :       }
    1179             : 
    1180         336 :       fd_sol_sysvar_clock_t clock_;
    1181         336 :       fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( instr_ctx->sysvar_cache, &clock_ );
    1182         336 :       if( FD_UNLIKELY( !clock ) ) {
    1183           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1184           0 :       }
    1185             : 
    1186             :       /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L538 */
    1187         336 :       if( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 8U ) ) {
    1188           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1189           0 :       }
    1190             : 
    1191             :       /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L539-L541 */
    1192         336 :       fd_pubkey_t const * authority_key = NULL;
    1193         336 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 7UL, &authority_key );
    1194         336 :       if( FD_UNLIKELY( err ) ) return err;
    1195             : 
    1196             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L542-L560 */
    1197             :       /* Verify Program account */
    1198         336 :       fd_pubkey_t const * new_program_id = NULL;
    1199             : 
    1200             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L545 */
    1201         336 :       fd_guarded_borrowed_account_t program = {0};
    1202         336 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 2UL, &program );
    1203             : 
    1204         336 :       fd_bpf_state_t loader_state[1];
    1205         336 :       int err = fd_bpf_loader_program_get_state( program.acc, loader_state );
    1206         336 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1207           0 :         return err;
    1208           0 :       }
    1209         336 :       if( FD_UNLIKELY( loader_state->discriminant!=FD_BPF_STATE_UNINITIALIZED ) ) {
    1210           0 :         fd_log_collector_msg_literal( instr_ctx, "Program account already initialized" );
    1211           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
    1212           0 :       }
    1213         336 :       if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &program )<SIZE_OF_PROGRAM ) ) {
    1214           0 :         fd_log_collector_msg_literal( instr_ctx, "Program account too small" );
    1215           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1216           0 :       }
    1217         336 :       if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &program )<
    1218         336 :                        fd_rent_exempt_minimum_balance( rent, fd_borrowed_account_get_data_len( &program ) ) ) ) {
    1219           0 :         fd_log_collector_msg_literal( instr_ctx, "Program account not rent-exempt" );
    1220           0 :         return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_ACCOUNT_NOT_RENT_EXEMPT;
    1221           0 :       }
    1222         336 :       new_program_id = (fd_pubkey_t*)program.acc->pubkey;
    1223             : 
    1224             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L560 */
    1225         336 :       fd_borrowed_account_drop( &program );
    1226             : 
    1227             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L561-L600 */
    1228             :       /* Verify Buffer account */
    1229             : 
    1230         336 :       fd_pubkey_t const* buffer_key         = NULL;
    1231         336 :       ulong              buffer_data_offset = 0UL;
    1232         336 :       ulong              buffer_data_len    = 0UL;
    1233         336 :       ulong              programdata_len    = 0UL;
    1234             : 
    1235             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L564-L565 */
    1236         336 :       fd_guarded_borrowed_account_t buffer = {0};
    1237         336 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 3UL, &buffer );
    1238             : 
    1239             :       /* https://github.com/anza-xyz/agave/blob/645f638832e19269d7d1c8614bed3b3b9badb158/programs/bpf_loader/src/lib.rs#L234-L241 */
    1240         336 :       if( FD_UNLIKELY( !fd_borrowed_account_is_writable( &buffer ) ) ) {
    1241           1 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account not writeable" );
    1242           1 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1243           1 :       }
    1244             : 
    1245         335 :       if( FD_UNLIKELY( memcmp( program_id, fd_borrowed_account_get_owner( &buffer ), sizeof(fd_pubkey_t) ) ) ) {
    1246          20 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account not owned by loader" );
    1247          20 :         return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1248          20 :       }
    1249             : 
    1250         315 :       fd_bpf_state_t buffer_state[1];
    1251         315 :       err = fd_bpf_loader_program_get_state( buffer.acc, buffer_state );
    1252         315 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1253          54 :         return err;
    1254          54 :       }
    1255             : 
    1256         261 :       if( buffer_state->discriminant==FD_BPF_STATE_BUFFER ) {
    1257         261 :         if( FD_UNLIKELY( (authority_key==NULL) != (!buffer_state->inner.buffer.has_authority_address) ||
    1258         261 :             (authority_key!=NULL && !fd_pubkey_eq( &buffer_state->inner.buffer.authority_address, authority_key ) ) ) ) {
    1259          13 :           fd_log_collector_msg_literal( instr_ctx, "Buffer and upgrade authority don't match" );
    1260          13 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1261          13 :         }
    1262         248 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 7UL, &err ) ) ) {
    1263             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1264           4 :           if( FD_UNLIKELY( !!err ) ) return err;
    1265           4 :           fd_log_collector_msg_literal( instr_ctx, "Upgrade authority did not sign" );
    1266           4 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1267           4 :         }
    1268         248 :       } else {
    1269           0 :         fd_log_collector_msg_literal( instr_ctx, "Invalid Buffer account" );
    1270           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1271           0 :       }
    1272         244 :       buffer_key         = (fd_pubkey_t*)buffer.acc->pubkey;
    1273         244 :       buffer_data_offset = BUFFER_METADATA_SIZE;
    1274         244 :       buffer_data_len    = fd_ulong_sat_sub( fd_borrowed_account_get_data_len( &buffer ), buffer_data_offset );
    1275             :       /* UpgradeableLoaderState::size_of_program_data( max_data_len ) */
    1276         244 :       programdata_len    = fd_ulong_sat_add( PROGRAMDATA_METADATA_SIZE,
    1277         244 :                                              instruction->inner.deploy_with_max_data_len.max_data_len );
    1278             : 
    1279         244 :       if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &buffer )<BUFFER_METADATA_SIZE || buffer_data_len==0UL ) ) {
    1280           0 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account too small" );
    1281           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1282           0 :       }
    1283             : 
    1284         244 :       if( FD_UNLIKELY( instruction->inner.deploy_with_max_data_len.max_data_len<buffer_data_len ) ) {
    1285           0 :         fd_log_collector_msg_literal( instr_ctx, "Max data length is too small to hold Buffer data" );
    1286           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1287           0 :       }
    1288             : 
    1289         244 :       if( FD_UNLIKELY( programdata_len>MAX_PERMITTED_DATA_LENGTH ) ) {
    1290           0 :         fd_log_collector_msg_literal( instr_ctx, "Max data length is too large" );
    1291           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1292           0 :       }
    1293             : 
    1294             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L590 */
    1295         244 :       fd_borrowed_account_drop( &buffer );
    1296             : 
    1297             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L602-L608 */
    1298             :       /* Create ProgramData account */
    1299             : 
    1300         244 :       fd_pubkey_t derived_address[ 1UL ];
    1301         244 :       uchar const * seeds[ 1UL ];
    1302         244 :       seeds[ 0UL ]    = (uchar const *)new_program_id;
    1303         244 :       ulong seed_sz   = sizeof(fd_pubkey_t);
    1304         244 :       uchar bump_seed = 0;
    1305         244 :       err = fd_pubkey_find_program_address( program_id, 1UL, seeds, &seed_sz, derived_address,
    1306         244 :                                             &bump_seed, &instr_ctx->txn_out->err.custom_err );
    1307         244 :       if( FD_UNLIKELY( err ) ) {
    1308             :         /* TODO: We should handle these errors more gracefully instead of just killing the client (e.g. excluding the transaction
    1309             :            from the block). */
    1310           0 :         FD_LOG_ERR(( "Unable to find a viable program address bump seed" )); // Solana panics, error code is undefined
    1311           0 :         return err;
    1312           0 :       }
    1313         244 :       if( FD_UNLIKELY( memcmp( derived_address, programdata_key, sizeof(fd_pubkey_t) ) ) ) {
    1314           1 :         fd_log_collector_msg_literal( instr_ctx, "ProgramData address is not derived" );
    1315           1 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1316           1 :       }
    1317             : 
    1318             :       /* Drain the Buffer account to payer before paying for programdata account in a local scope
    1319             :          https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L612-L628 */
    1320             : 
    1321         243 :       do {
    1322             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L615 */
    1323         243 :         fd_guarded_borrowed_account_t payer = {0};
    1324         243 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &payer );
    1325             : 
    1326             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L613 */
    1327         243 :         fd_guarded_borrowed_account_t buffer = {0};
    1328         243 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 3UL, &buffer );
    1329             : 
    1330         243 :         err = fd_borrowed_account_checked_add_lamports( &payer, fd_borrowed_account_get_lamports( &buffer ) );
    1331         243 :         if( FD_UNLIKELY( err ) ) {
    1332           0 :           return err;
    1333           0 :         }
    1334         243 :         err = fd_borrowed_account_set_lamports( &buffer, 0UL );
    1335         243 :         if( FD_UNLIKELY( err ) ) {
    1336           0 :           return err;
    1337           0 :         }
    1338         243 :       } while (0);
    1339             : 
    1340             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L628-L642 */
    1341             :       /* Pass an extra account to avoid the overly strict unbalanced instruction error */
    1342             :       /* Invoke the system program to create the new account */
    1343         243 :       uchar instr_data[FD_TXN_MTU];
    1344         243 :       create_account_t create_acct = {
    1345         243 :         .lamports = fd_rent_exempt_minimum_balance( rent, programdata_len ),
    1346         243 :         .space    = programdata_len,
    1347         243 :         .owner    = *program_id,
    1348         243 :       };
    1349         243 :       if( !create_acct.lamports ) {
    1350           0 :         create_acct.lamports = 1UL;
    1351           0 :       }
    1352             : 
    1353         243 :       fd_system_program_instruction_t instr = {
    1354         243 :         .discriminant = FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT,
    1355         243 :         .inner = {
    1356         243 :           .create_account = create_acct,
    1357         243 :         }
    1358         243 :       };
    1359             : 
    1360         243 :       ulong instr_data_sz;
    1361         243 :       err = fd_system_program_instruction_encode( &instr, instr_data, FD_TXN_MTU, &instr_data_sz );
    1362         243 :       if( FD_UNLIKELY( err ) ) {
    1363           0 :         FD_LOG_CRIT(( "Failed to encode SystemInstruction with error %d", err ));
    1364           0 :       }
    1365             : 
    1366         243 :       fd_vm_rust_account_meta_t acct_metas[ 3UL ];
    1367         243 :       fd_native_cpi_create_account_meta( payer_key,       1U, 1U, &acct_metas[ 0UL ] );
    1368         243 :       fd_native_cpi_create_account_meta( programdata_key, 1U, 1U, &acct_metas[ 1UL ] );
    1369         243 :       fd_native_cpi_create_account_meta( buffer_key,      0U, 1U, &acct_metas[ 2UL ] );
    1370             : 
    1371             :       /* caller_program_id == program_id */
    1372         243 :       fd_pubkey_t signers[ 1UL ];
    1373         243 :       err = fd_pubkey_derive_pda( program_id, 1UL, seeds, &seed_sz, &bump_seed, signers, &instr_ctx->txn_out->err.custom_err );
    1374         243 :       if( FD_UNLIKELY( err ) ) {
    1375           0 :         return err;
    1376           0 :       }
    1377         243 :       err = fd_native_cpi_native_invoke( instr_ctx,
    1378         243 :                                          &fd_solana_system_program_id,
    1379         243 :                                          instr_data,
    1380         243 :                                          instr_data_sz,
    1381         243 :                                          acct_metas,
    1382         243 :                                          3UL,
    1383         243 :                                          signers,
    1384         243 :                                          1UL );
    1385         243 :       if( FD_UNLIKELY( err ) ) {
    1386           0 :         return err;
    1387           0 :       }
    1388             : 
    1389             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L644-L665 */
    1390             :       /* Load and verify the program bits */
    1391             : 
    1392             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L648-L649 */
    1393         243 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 3UL, &buffer );
    1394             : 
    1395         243 :       if( FD_UNLIKELY( buffer_data_offset>fd_borrowed_account_get_data_len( &buffer ) ) ) {
    1396           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1397           0 :       }
    1398             : 
    1399         243 :       const uchar * buffer_data = fd_borrowed_account_get_data( &buffer ) + buffer_data_offset;
    1400             : 
    1401         243 :       err = fd_deploy_program( instr_ctx, buffer_data, buffer_data_len,
    1402         243 :                                FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, disable_sbpf_v0_v1_v2_deployment ) );
    1403         243 :       if( FD_UNLIKELY( err ) ) {
    1404          69 :         return err;
    1405          69 :       }
    1406             : 
    1407             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L657 */
    1408         174 :       fd_borrowed_account_drop( &buffer );
    1409             : 
    1410             :       /* Update the ProgramData account and record the program bits in a local scope
    1411             :          https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L669-L691 */
    1412         174 :       do {
    1413             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L670-L671 */
    1414         174 :         fd_guarded_borrowed_account_t programdata = {0};
    1415         174 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 1UL, &programdata );
    1416             : 
    1417         174 :         fd_bpf_state_t programdata_loader_state = {
    1418         174 :           .discriminant = FD_BPF_STATE_PROGRAM_DATA,
    1419         174 :           .inner.program_data = {
    1420         174 :             .slot                          = clock->slot,
    1421         174 :             .has_upgrade_authority_address = !!authority_key,
    1422         174 :             .upgrade_authority_address     = authority_key ? *authority_key : (fd_pubkey_t){{0}},
    1423         174 :           },
    1424         174 :         };
    1425         174 :         err = fd_bpf_loader_v3_program_set_state( &programdata, &programdata_loader_state );
    1426         174 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1427           0 :           return err;
    1428           0 :         }
    1429         174 :         programdata.acc->pd_write = 1;
    1430             : 
    1431             :         /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L675-L689 */
    1432         174 :         if( FD_UNLIKELY( PROGRAMDATA_METADATA_SIZE+buffer_data_len>fd_borrowed_account_get_data_len( &programdata ) ) ) {
    1433           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1434           0 :         }
    1435             : 
    1436         174 :         uchar * programdata_data = NULL;
    1437         174 :         ulong   programdata_dlen = 0UL;
    1438         174 :         err = fd_borrowed_account_get_data_mut( &programdata, &programdata_data, &programdata_dlen );
    1439         174 :         if( FD_UNLIKELY( err ) ) {
    1440           0 :           return err;
    1441           0 :         }
    1442             : 
    1443         174 :         uchar *   dst_slice = programdata_data + PROGRAMDATA_METADATA_SIZE;
    1444         174 :         ulong dst_slice_len = buffer_data_len;
    1445             : 
    1446             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L683-L684 */
    1447         174 :         fd_guarded_borrowed_account_t buffer = {0};
    1448         174 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 3UL, &buffer );
    1449             : 
    1450         174 :         if( FD_UNLIKELY( buffer_data_offset>fd_borrowed_account_get_data_len( &buffer ) ) ) {
    1451           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1452           0 :         }
    1453         174 :         const uchar * src_slice = fd_borrowed_account_get_data( &buffer ) + buffer_data_offset;
    1454         174 :         fd_memcpy( dst_slice, src_slice, dst_slice_len );
    1455             :         /* Update buffer data length.
    1456             :           BUFFER_METADATA_SIZE == UpgradeableLoaderState::size_of_buffer(0) */
    1457         174 :         err = fd_borrowed_account_set_data_length( &buffer, BUFFER_METADATA_SIZE );
    1458         174 :         if( FD_UNLIKELY( err ) ) {
    1459           0 :           return err;
    1460           0 :         }
    1461         174 :       } while(0);
    1462             : 
    1463             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L692-L699 */
    1464             : 
    1465             :       /* Update the Program account
    1466             :          https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L694-L695 */
    1467         174 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 2UL, &program );
    1468             : 
    1469         174 :       loader_state->discriminant = FD_BPF_STATE_PROGRAM;
    1470         174 :       loader_state->inner.program.programdata_address =  *programdata_key;
    1471         174 :       err = fd_bpf_loader_v3_program_set_state( &program, loader_state );
    1472         174 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1473           0 :         return err;
    1474           0 :       }
    1475         174 :       err = fd_borrowed_account_set_executable( &program, 1 );
    1476         174 :       if( FD_UNLIKELY( err ) ) {
    1477           0 :         return err;
    1478           0 :       }
    1479             : 
    1480         174 :       FD_BASE58_ENCODE_32_BYTES( program.acc->pubkey, program_b58 );
    1481         174 :       FD_LOG_INFO(( "Program deployed %s", program_b58 ));
    1482             : 
    1483             :       /* Max msg_sz: 19 - 2 + 45 = 62 < 127 => we can use printf */
    1484         174 :       fd_log_collector_printf_dangerous_max_127( instr_ctx, "Deployed program %s", program_b58 );
    1485             : 
    1486             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L700 */
    1487         174 :       fd_borrowed_account_drop( &program );
    1488             : 
    1489         174 :       break;
    1490         174 :     }
    1491             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L703-L891 */
    1492         497 :     case FD_BPF_INSTR_UPGRADE: {
    1493             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L704-L714 */
    1494         497 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 3U ) ) ) {
    1495           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1496           0 :       }
    1497             : 
    1498             :       /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L706-L708 */
    1499         497 :       fd_pubkey_t const * programdata_key = NULL;
    1500         497 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 0UL, &programdata_key );
    1501         497 :       if( FD_UNLIKELY( err ) ) {
    1502           0 :         return err;
    1503           0 :       }
    1504             : 
    1505             :       /* rent is accessed directly from the epoch bank and the clock from the
    1506             :         slot context. However, a check must be done to make sure that the
    1507             :         sysvars are correctly included in the set of transaction accounts. */
    1508         497 :       err = fd_sysvar_instr_acct_check( instr_ctx, 4UL, &fd_sysvar_rent_id );
    1509         497 :       if( FD_UNLIKELY( err ) ) {
    1510           1 :         return err;
    1511           1 :       }
    1512             : 
    1513         496 :       fd_rent_t rent_;
    1514         496 :       fd_rent_t const * rent = fd_sysvar_cache_rent_read( instr_ctx->sysvar_cache, &rent_ );
    1515         496 :       if( FD_UNLIKELY( !rent ) ) {
    1516           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1517           0 :       }
    1518             : 
    1519         496 :       err = fd_sysvar_instr_acct_check( instr_ctx, 5UL, &fd_sysvar_clock_id );
    1520         496 :       if( FD_UNLIKELY( err ) ) {
    1521          25 :         return err;
    1522          25 :       }
    1523             : 
    1524         471 :       fd_sol_sysvar_clock_t clock_;
    1525         471 :       fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( instr_ctx->sysvar_cache, &clock_ );
    1526         471 :       if( FD_UNLIKELY( !clock ) ) {
    1527           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1528           0 :       }
    1529             : 
    1530         471 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 7U ) ) ) {
    1531           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1532           0 :       }
    1533             : 
    1534             :       /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L713-L715 */
    1535         471 :       fd_pubkey_t const * authority_key = NULL;
    1536         471 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 6UL, &authority_key );
    1537         471 :       if( FD_UNLIKELY( err ) ) return err;
    1538             : 
    1539             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L716-L745 */
    1540             :       /* Verify Program account */
    1541             : 
    1542             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L719-L720 */
    1543         471 :       fd_guarded_borrowed_account_t program = {0};
    1544         471 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 1UL, &program );
    1545             : 
    1546         471 :       if( FD_UNLIKELY( !fd_borrowed_account_is_writable( &program ) ) ) {
    1547           0 :         fd_log_collector_msg_literal( instr_ctx, "Program account not writeable" );
    1548           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1549           0 :       }
    1550         471 :       if( FD_UNLIKELY( memcmp( fd_borrowed_account_get_owner( &program ), program_id, sizeof(fd_pubkey_t) ) ) ) {
    1551           0 :         fd_log_collector_msg_literal( instr_ctx, "Program account not owned by loader" );
    1552           0 :         return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1553           0 :       }
    1554         471 :       fd_bpf_state_t program_state[1];
    1555         471 :       err = fd_bpf_loader_program_get_state( program.acc, program_state );
    1556         471 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1557           0 :         return err;
    1558           0 :       }
    1559         471 :       if( FD_UNLIKELY( program_state->discriminant==FD_BPF_STATE_PROGRAM ) ) {
    1560         471 :         if( FD_UNLIKELY( memcmp( &program_state->inner.program.programdata_address, programdata_key, sizeof(fd_pubkey_t) ) ) ) {
    1561         211 :           fd_log_collector_msg_literal( instr_ctx, "Program and ProgramData account mismatch" );
    1562         211 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1563         211 :         }
    1564         471 :       } else {
    1565           0 :         fd_log_collector_msg_literal( instr_ctx, "Invalid Program account" );
    1566           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1567           0 :       }
    1568             : 
    1569             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L746 */
    1570         260 :       fd_pubkey_t new_program_id = *(fd_pubkey_t*)program.acc->pubkey;
    1571         260 :       fd_borrowed_account_drop( &program );
    1572             : 
    1573             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L747-L773 */
    1574             :       /* Verify Buffer account */
    1575             : 
    1576         260 :       ulong buffer_lamports    = 0UL;
    1577         260 :       ulong buffer_data_offset = 0UL;
    1578         260 :       ulong buffer_data_len    = 0UL;
    1579             : 
    1580             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L750-L751 */
    1581         260 :       fd_guarded_borrowed_account_t buffer = {0};
    1582         260 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 2UL, &buffer );
    1583             : 
    1584             :       /* https://github.com/anza-xyz/agave/blob/645f638832e19269d7d1c8614bed3b3b9badb158/programs/bpf_loader/src/lib.rs#L407-L414 */
    1585         260 :       if( FD_UNLIKELY( !fd_borrowed_account_is_writable( &buffer ) ) ) {
    1586           0 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account not writeable" );
    1587           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1588           0 :       }
    1589             : 
    1590         260 :       if( FD_UNLIKELY( memcmp( program_id, fd_borrowed_account_get_owner( &buffer ), sizeof(fd_pubkey_t) ) ) ) {
    1591           0 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account not owned by loader" );
    1592           0 :         return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1593           0 :       }
    1594             : 
    1595         260 :       fd_bpf_state_t buffer_state[1];
    1596         260 :       err = fd_bpf_loader_program_get_state( buffer.acc, buffer_state );
    1597         260 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1598           0 :         return err;
    1599           0 :       }
    1600         260 :       if( buffer_state->discriminant==FD_BPF_STATE_BUFFER ) {
    1601         260 :         if( FD_UNLIKELY( (authority_key==NULL) != (!buffer_state->inner.buffer.has_authority_address) ||
    1602         260 :             (authority_key!=NULL && !fd_pubkey_eq( &buffer_state->inner.buffer.authority_address, authority_key ) ) ) ) {
    1603           5 :           fd_log_collector_msg_literal( instr_ctx, "Buffer and upgrade authority don't match" );
    1604           5 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1605           5 :         }
    1606         255 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 6UL, &err ) ) ) {
    1607             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1608           5 :           if( FD_UNLIKELY( !!err ) ) return err;
    1609           5 :           fd_log_collector_msg_literal( instr_ctx, "Upgrade authority did not sign" );
    1610           5 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1611           5 :         }
    1612         255 :       } else {
    1613           0 :         fd_log_collector_msg_literal( instr_ctx, "Invalid Buffer account" );
    1614           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1615           0 :       }
    1616         250 :       buffer_lamports    = fd_borrowed_account_get_lamports( &buffer );
    1617         250 :       buffer_data_offset = BUFFER_METADATA_SIZE;
    1618         250 :       buffer_data_len    = fd_ulong_sat_sub( fd_borrowed_account_get_data_len( &buffer ), buffer_data_offset );
    1619         250 :       if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &buffer )<BUFFER_METADATA_SIZE || buffer_data_len==0UL ) ) {
    1620           0 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account too small" );
    1621           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1622           0 :       }
    1623             : 
    1624             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L774 */
    1625         250 :       fd_borrowed_account_drop( &buffer );
    1626             : 
    1627             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L775-L823 */
    1628             :       /* Verify ProgramData account */
    1629             : 
    1630         250 :       ulong programdata_data_offset      = PROGRAMDATA_METADATA_SIZE;
    1631         250 :       ulong programdata_len              = 0UL;
    1632         250 :       ulong programdata_balance_required = 0UL;
    1633             : 
    1634             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L778-L779 */
    1635         250 :       fd_guarded_borrowed_account_t programdata = {0};
    1636         250 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &programdata );
    1637             : 
    1638             :       /* SIMD-0433: ProgramData account is resized to hold the new ELF */
    1639         250 :       err = fd_bpf_loader_v3_upgrade_sizing(
    1640         250 :           FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, loader_v3_set_program_data_to_elf_length ),
    1641         250 :           fd_borrowed_account_get_data_len( &programdata ),
    1642         250 :           buffer_data_len,
    1643         250 :           rent,
    1644         250 :           &programdata_len,
    1645         250 :           &programdata_balance_required );
    1646         250 :       if( FD_UNLIKELY( err==FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA ) ) {
    1647           0 :         fd_log_collector_printf_dangerous_max_127( instr_ctx,
    1648           0 :           "Resized ProgramData length of %lu bytes exceeds max account data length", programdata_len );
    1649           0 :         return err;
    1650           0 :       }
    1651         250 :       if( FD_UNLIKELY( err==FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL ) ) {
    1652           0 :         fd_log_collector_msg_literal( instr_ctx, "ProgramData account not large enough" );
    1653           0 :         return err;
    1654           0 :       }
    1655         250 :       if( FD_UNLIKELY( fd_ulong_sat_add( fd_borrowed_account_get_lamports( &programdata ), buffer_lamports )<programdata_balance_required ) ) {
    1656           0 :         fd_log_collector_msg_literal( instr_ctx, "Buffer account balance too low to fund upgrade" );
    1657           0 :         return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1658           0 :       }
    1659             : 
    1660         250 :       fd_bpf_state_t programdata_state[1];
    1661         250 :       err = fd_bpf_loader_program_get_state( programdata.acc, programdata_state );
    1662         250 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1663           0 :         return err;
    1664           0 :       }
    1665             : 
    1666         250 :       if( programdata_state->discriminant==FD_BPF_STATE_PROGRAM_DATA ) {
    1667         250 :         if( FD_UNLIKELY( clock->slot==programdata_state->inner.program_data.slot ) ) {
    1668         242 :           fd_log_collector_msg_literal( instr_ctx, "Program was deployed in this block already" );
    1669         242 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1670         242 :         }
    1671           8 :         if( FD_UNLIKELY( !programdata_state->inner.program_data.has_upgrade_authority_address ) ) {
    1672           0 :           fd_log_collector_msg_literal( instr_ctx, "Program not upgradeable" );
    1673           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
    1674           0 :         }
    1675           8 :         if( FD_UNLIKELY( !fd_pubkey_eq( &programdata_state->inner.program_data.upgrade_authority_address, authority_key ) ) ) {
    1676           0 :           fd_log_collector_msg_literal( instr_ctx, "Incorrect upgrade authority provided" );
    1677           0 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1678           0 :         }
    1679           8 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 6UL, &err ) ) ) {
    1680             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1681           0 :           if( FD_UNLIKELY( !!err ) ) return err;
    1682           0 :           fd_log_collector_msg_literal( instr_ctx, "Upgrade authority did not sign" );
    1683           0 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1684           0 :         }
    1685           8 :       } else {
    1686           0 :         fd_log_collector_msg_literal( instr_ctx, "Invalid ProgramData account" );
    1687           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1688           0 :       }
    1689             : 
    1690             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L824 */
    1691           8 :       fd_borrowed_account_drop( &programdata );
    1692             : 
    1693             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L825-L845 */
    1694             :       /* Load and verify the program bits */
    1695             : 
    1696             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L827-L828 */
    1697           8 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 2UL, &buffer );
    1698             : 
    1699           8 :       if( FD_UNLIKELY( buffer_data_offset>fd_borrowed_account_get_data_len( &buffer ) ) ) {
    1700           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1701           0 :       }
    1702             : 
    1703           8 :       const uchar * buffer_data = fd_borrowed_account_get_data( &buffer ) + buffer_data_offset;
    1704           8 :       err = fd_deploy_program( instr_ctx, buffer_data, buffer_data_len,
    1705           8 :                                FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, disable_sbpf_v0_v1_v2_deployment ) );
    1706           8 :       if( FD_UNLIKELY( err ) ) {
    1707           3 :         return err;
    1708           3 :       }
    1709             : 
    1710             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L836 */
    1711           5 :       fd_borrowed_account_drop( &buffer );
    1712             : 
    1713             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L849-L850 */
    1714           5 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &programdata );
    1715             : 
    1716             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L846-L874 */
    1717             :       /* Update the ProgramData account, record the upgraded data, and zero the rest in a local scope */
    1718           5 :       do {
    1719           5 :         err = fd_borrowed_account_set_data_length( &programdata, programdata_len );
    1720           5 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1721           0 :           return err;
    1722           0 :         }
    1723             : 
    1724           5 :         programdata_state->discriminant                                     = FD_BPF_STATE_PROGRAM_DATA;
    1725           5 :         programdata_state->inner.program_data.slot                          = clock->slot;
    1726           5 :         programdata_state->inner.program_data.has_upgrade_authority_address = 1;
    1727           5 :         programdata_state->inner.program_data.upgrade_authority_address     = *authority_key;
    1728           5 :         err = fd_bpf_loader_v3_program_set_state( &programdata, programdata_state );
    1729           5 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1730           0 :           return err;
    1731           0 :         }
    1732           5 :         programdata.acc->pd_write = 1;
    1733             : 
    1734             :         /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L846-L875 */
    1735             :         /* We want to copy over the data and zero out the rest */
    1736           5 :         if( FD_UNLIKELY( programdata_data_offset+buffer_data_len>fd_borrowed_account_get_data_len( &programdata ) ) ) {
    1737           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1738           0 :         }
    1739             : 
    1740           5 :         uchar * programdata_data = NULL;
    1741           5 :         ulong   programdata_dlen = 0UL;
    1742           5 :         err = fd_borrowed_account_get_data_mut( &programdata, &programdata_data, &programdata_dlen );
    1743           5 :         if( FD_UNLIKELY( err ) ) {
    1744           0 :           return err;
    1745           0 :         }
    1746           5 :         uchar * dst_slice     = programdata_data + programdata_data_offset;
    1747           5 :         ulong   dst_slice_len = buffer_data_len;
    1748             : 
    1749             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L863-L864 */
    1750           5 :         fd_guarded_borrowed_account_t buffer = {0};
    1751           5 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 2UL, &buffer );
    1752             : 
    1753           5 :         if( FD_UNLIKELY( buffer_data_offset>fd_borrowed_account_get_data_len( &buffer ) ) ){
    1754           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
    1755           0 :         }
    1756             : 
    1757           5 :         const uchar * src_slice = fd_borrowed_account_get_data( &buffer ) + buffer_data_offset;
    1758           5 :         fd_memcpy( dst_slice, src_slice, dst_slice_len );
    1759           5 :         fd_memset( dst_slice + dst_slice_len, 0, fd_borrowed_account_get_data_len( &programdata ) - programdata_data_offset - dst_slice_len );
    1760             : 
    1761             :         /* implicit drop of buffer */
    1762           5 :       } while (0);
    1763             : 
    1764             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L876-L891 */
    1765             :       /* Fund ProgramData to rent-exemption, spill the rest */
    1766             : 
    1767             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L878-L879 */
    1768           5 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 2UL, &buffer );
    1769             : 
    1770             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L880-L881 */
    1771           5 :       fd_guarded_borrowed_account_t spill = {0};
    1772           5 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 3UL, &spill );
    1773             : 
    1774           5 :       ulong spill_addend = fd_ulong_sat_sub( fd_ulong_sat_add( fd_borrowed_account_get_lamports( &programdata ), buffer_lamports ),
    1775           5 :                                             programdata_balance_required );
    1776           5 :       err = fd_borrowed_account_checked_add_lamports( &spill, spill_addend );
    1777           5 :       if( FD_UNLIKELY( err ) ) {
    1778           0 :         return err;
    1779           0 :       }
    1780           5 :       err = fd_borrowed_account_set_lamports( &buffer, 0UL );
    1781           5 :       if( FD_UNLIKELY( err ) ) {
    1782           0 :         return err;
    1783           0 :       }
    1784           5 :       err = fd_borrowed_account_set_lamports( &programdata, programdata_balance_required );
    1785           5 :       if( FD_UNLIKELY( err ) ) {
    1786           0 :         return err;
    1787           0 :       }
    1788             : 
    1789             :       /* Buffer account set_data_length */
    1790           5 :       err = fd_borrowed_account_set_data_length( &buffer, BUFFER_METADATA_SIZE );
    1791           5 :       if( FD_UNLIKELY( err ) ) {
    1792           0 :         return err;
    1793           0 :       }
    1794             : 
    1795             :       /* buffer is dropped when it goes out of scope */
    1796             :       /* spill is dropped when it goes out of scope */
    1797             :       /* programdata is dropped when it goes out of scope */
    1798             : 
    1799             :       /* Max msg_sz: 19 - 2 + 45 = 62 < 127 => we can use printf */
    1800           5 :       FD_BASE58_ENCODE_32_BYTES( new_program_id.uc, program_id_b58 );
    1801           5 :       fd_log_collector_printf_dangerous_max_127( instr_ctx, "Upgraded program %s", program_id_b58 );
    1802             : 
    1803           5 :       break;
    1804           5 :     }
    1805             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L893-L957 */
    1806         303 :     case FD_BPF_INSTR_SET_AUTHORITY: {
    1807         303 :       int err;
    1808         303 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 2U ) ) ) {
    1809           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1810           0 :       }
    1811             : 
    1812             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L896-L897 */
    1813         303 :       fd_guarded_borrowed_account_t account = {0};
    1814         303 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &account );
    1815             : 
    1816             :       /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L898-L900 */
    1817         303 :       fd_pubkey_t const * present_authority_key = NULL;
    1818         303 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 1UL, &present_authority_key );
    1819         303 :       if( FD_UNLIKELY( err ) ) {
    1820           0 :         return err;
    1821           0 :       }
    1822             : 
    1823             :       /* Don't check the error here because the new_authority key is allowed to be NULL until further checks.
    1824             :          https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L901-L906 */
    1825         303 :       fd_pubkey_t const * new_authority = NULL;
    1826         303 :       fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 2UL, &new_authority );
    1827             : 
    1828         303 :       fd_bpf_state_t account_state[1];
    1829         303 :       err = fd_bpf_loader_program_get_state( account.acc, account_state );
    1830         303 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1831           2 :         return err;
    1832           2 :       }
    1833             : 
    1834         301 :       if( account_state->discriminant==FD_BPF_STATE_BUFFER ) {
    1835         152 :         if( FD_UNLIKELY( !new_authority ) ) {
    1836          13 :           fd_log_collector_msg_literal( instr_ctx, "Buffer authority is not optional" );
    1837          13 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1838          13 :         }
    1839         139 :         if( FD_UNLIKELY( !account_state->inner.buffer.has_authority_address ) ) {
    1840           0 :           fd_log_collector_msg_literal( instr_ctx, "Buffer is immutable" );
    1841           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
    1842           0 :         }
    1843         139 :         if( FD_UNLIKELY( !fd_pubkey_eq( &account_state->inner.buffer.authority_address, present_authority_key ) ) ) {
    1844           1 :           fd_log_collector_msg_literal( instr_ctx, "Incorrect buffer authority provided" );
    1845           1 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1846           1 :         }
    1847         138 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 1UL, &err ) ) ) {
    1848             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1849           3 :           if( FD_UNLIKELY( !!err ) ) return err;
    1850           3 :           fd_log_collector_msg_literal( instr_ctx, "Buffer authority did not sign" );
    1851           3 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1852           3 :         }
    1853             : 
    1854             :         /* copy in the authority public key into the authority address.
    1855             :            https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L926-L928 */
    1856         135 :         account_state->inner.buffer.has_authority_address = !!new_authority;
    1857         135 :         if( new_authority ) {
    1858         135 :           account_state->inner.buffer.authority_address = *new_authority;
    1859         135 :         }
    1860             : 
    1861         135 :         err = fd_bpf_loader_v3_program_set_state( &account, account_state );
    1862         135 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1863           0 :           return err;
    1864           0 :         }
    1865         149 :       } else if( account_state->discriminant==FD_BPF_STATE_PROGRAM_DATA ) {
    1866         149 :         if( FD_UNLIKELY( !account_state->inner.program_data.has_upgrade_authority_address ) ) {
    1867           0 :           fd_log_collector_msg_literal( instr_ctx, "Program not upgradeable" );
    1868           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
    1869           0 :         }
    1870         149 :         if( FD_UNLIKELY( !fd_pubkey_eq( &account_state->inner.program_data.upgrade_authority_address, present_authority_key ) ) ) {
    1871           2 :           fd_log_collector_msg_literal( instr_ctx, "Incorrect upgrade authority provided" );
    1872           2 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1873           2 :         }
    1874         147 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 1UL, &err ) ) ) {
    1875             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1876           8 :           if( FD_UNLIKELY( !!err ) ) return err;
    1877           8 :           fd_log_collector_msg_literal( instr_ctx, "Upgrade authority did not sign" );
    1878           8 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1879           8 :         }
    1880             : 
    1881             :         /* SIMD-0500: forbid finalize (SetAuthority None) on programs
    1882             :            that are not at least SBPF v3. */
    1883         139 :         if( !new_authority ) {
    1884          12 :           int rc = fd_bpf_loader_finalize_v3_check(
    1885          12 :               FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, disable_sbpf_v0_v1_v2_deployment ),
    1886          12 :               fd_borrowed_account_get_data    ( &account ),
    1887          12 :               fd_borrowed_account_get_data_len( &account ) );
    1888          12 :           if( FD_UNLIKELY( rc!=FD_EXECUTOR_INSTR_SUCCESS ) ) return rc;
    1889          12 :         }
    1890             : 
    1891             :         /* copy in the authority public key into the upgrade authority address.
    1892             :            https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L946-L949 */
    1893         139 :         account_state->inner.program_data.has_upgrade_authority_address = !!new_authority;
    1894         139 :         if( new_authority ) {
    1895         127 :           account_state->inner.program_data.upgrade_authority_address = *new_authority;
    1896         127 :         }
    1897             : 
    1898         139 :         err = fd_bpf_loader_v3_program_set_state( &account, account_state );
    1899         139 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1900           0 :           return err;
    1901           0 :         }
    1902         139 :       } else {
    1903           0 :         fd_log_collector_msg_literal( instr_ctx, "Account does not support authorities" );
    1904           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1905           0 :       }
    1906             : 
    1907             :       /* Max msg_sz: 16 - 2 + 45 = 59 < 127 => we can use printf */
    1908         274 :       if( new_authority ) {
    1909         262 :         FD_BASE58_ENCODE_32_BYTES( new_authority->uc, new_authority_b58 );
    1910         262 :         fd_log_collector_printf_dangerous_max_127( instr_ctx, "New authority Some(%s)", new_authority_b58 );
    1911         262 :       } else {
    1912          12 :         fd_log_collector_printf_dangerous_max_127( instr_ctx, "New authority None" );
    1913          12 :       }
    1914             : 
    1915             :       /* implicit drop of account */
    1916             : 
    1917         274 :       break;
    1918         301 :     }
    1919             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L958-L1030 */
    1920         295 :     case FD_BPF_INSTR_SET_AUTHORITY_CHECKED: {
    1921         295 :       int err;
    1922         295 :       if( !FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, enable_bpf_loader_set_authority_checked_ix ) ) {
    1923           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1924           0 :       }
    1925             : 
    1926         295 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 3U ) ) ) {
    1927           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1928           0 :       }
    1929             : 
    1930             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L968-L969 */
    1931         295 :       fd_guarded_borrowed_account_t account = {0};
    1932         295 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &account );
    1933             : 
    1934             :       /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L970-L975 */
    1935         295 :       fd_pubkey_t const * present_authority_key = NULL;
    1936         295 :       fd_pubkey_t const * new_authority_key     = NULL;
    1937             : 
    1938         295 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 1UL, &present_authority_key );
    1939         295 :       if( FD_UNLIKELY( err ) ) return err;
    1940             : 
    1941         295 :       err = fd_exec_instr_ctx_get_key_of_account_at_index( instr_ctx, 2UL, &new_authority_key );
    1942         295 :       if( FD_UNLIKELY( err ) ) return err;
    1943             : 
    1944         295 :       fd_bpf_state_t account_state[1];
    1945         295 :       err = fd_bpf_loader_program_get_state( account.acc, account_state );
    1946         295 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1947           7 :         return err;
    1948           7 :       }
    1949             : 
    1950         288 :       if( account_state->discriminant==FD_BPF_STATE_BUFFER ) {
    1951         135 :         if( FD_UNLIKELY( !account_state->inner.buffer.has_authority_address ) ) {
    1952           0 :           fd_log_collector_msg_literal( instr_ctx, "Buffer is immutable" );
    1953           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
    1954           0 :         }
    1955         135 :         if( FD_UNLIKELY( !fd_pubkey_eq( &account_state->inner.buffer.authority_address, present_authority_key ) ) ) {
    1956           3 :           fd_log_collector_msg_literal( instr_ctx, "Incorrect buffer authority provided" );
    1957           3 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1958           3 :         }
    1959         132 :         int instr_err_code = 0;
    1960         132 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 1UL, &instr_err_code ) ) ) {
    1961             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1962           3 :           if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
    1963           3 :           fd_log_collector_msg_literal( instr_ctx, "Buffer authority did not sign" );
    1964           3 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1965           3 :         }
    1966         129 :         instr_err_code = 0;
    1967         129 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 2UL, &instr_err_code ) ) ) {
    1968             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1969           0 :           if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
    1970           0 :           fd_log_collector_msg_literal( instr_ctx, "New authority did not sign" );
    1971           0 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1972           0 :         }
    1973         129 :         account_state->inner.buffer.has_authority_address = 1;
    1974         129 :         account_state->inner.buffer.authority_address     = *new_authority_key;
    1975         129 :         err = fd_bpf_loader_v3_program_set_state( &account, account_state );
    1976         129 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1977           0 :           return err;
    1978           0 :         }
    1979         153 :       } else if( account_state->discriminant==FD_BPF_STATE_PROGRAM_DATA ) {
    1980         153 :         if( FD_UNLIKELY( !account_state->inner.program_data.has_upgrade_authority_address ) ) {
    1981           0 :           fd_log_collector_msg_literal( instr_ctx, "Program not upgradeable" );
    1982           0 :           return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
    1983           0 :         }
    1984         153 :         if( FD_UNLIKELY( !fd_pubkey_eq( &account_state->inner.program_data.upgrade_authority_address, present_authority_key ) ) ) {
    1985           1 :           fd_log_collector_msg_literal( instr_ctx, "Incorrect upgrade authority provided" );
    1986           1 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
    1987           1 :         }
    1988         152 :         int instr_err_code = 0;
    1989         152 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 1UL, &instr_err_code ) ) ) {
    1990             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1991           3 :           if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
    1992           3 :           fd_log_collector_msg_literal( instr_ctx, "Upgrade authority did not sign" );
    1993           3 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1994           3 :         }
    1995         149 :         instr_err_code = 0;
    1996         149 :         if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( instr_ctx->instr, 2UL, &instr_err_code ) ) ) {
    1997             :           /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1998           1 :           if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
    1999           1 :           fd_log_collector_msg_literal( instr_ctx, "New authority did not sign" );
    2000           1 :           return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2001           1 :         }
    2002         148 :         account_state->inner.program_data.has_upgrade_authority_address = 1;
    2003         148 :         account_state->inner.program_data.upgrade_authority_address     = *new_authority_key;
    2004         148 :         err = fd_bpf_loader_v3_program_set_state( &account, account_state );
    2005         148 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    2006           0 :           return err;
    2007           0 :         }
    2008         148 :       } else {
    2009           0 :         fd_log_collector_msg_literal( instr_ctx, "Account does not support authorities" );
    2010           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2011           0 :       }
    2012             : 
    2013             :       /* Max msg_sz: 16 - 2 + 45 = 59 < 127 => we can use printf */
    2014         277 :       FD_BASE58_ENCODE_32_BYTES( new_authority_key->uc, new_authority_b58 );
    2015         277 :       fd_log_collector_printf_dangerous_max_127( instr_ctx, "New authority %s", new_authority_b58 );
    2016             : 
    2017             :       /* implicit drop of account */
    2018             : 
    2019         277 :       break;
    2020         288 :     }
    2021             :     /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1031-L1134 */
    2022         334 :     case FD_BPF_INSTR_CLOSE: {
    2023         334 :       int err;
    2024             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1032-L1046 */
    2025         334 :       if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 2U ) ) ) {
    2026           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2027           0 :       }
    2028             : 
    2029             :       /* It's safe to directly access the instruction accounts because we already checked for two
    2030             :          instruction accounts previously.
    2031             :          https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L1034-L1035 */
    2032         334 :       if( FD_UNLIKELY( instr_ctx->instr->accounts[ 0UL ].index_in_transaction ==
    2033         334 :                        instr_ctx->instr->accounts[ 1UL ].index_in_transaction ) ) {
    2034           0 :         fd_log_collector_msg_literal( instr_ctx, "Recipient is the same as the account being closed" );
    2035           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2036           0 :       }
    2037             : 
    2038             :       /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1043-L1044 */
    2039         334 :       fd_guarded_borrowed_account_t close_account = {0};
    2040         334 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 0UL, &close_account );
    2041             : 
    2042         334 :       fd_pubkey_t const * close_key = (fd_pubkey_t*)close_account.acc->pubkey;
    2043         334 :       fd_bpf_state_t close_account_state[1];
    2044         334 :       err = fd_bpf_loader_program_get_state( close_account.acc, close_account_state );
    2045         334 :       if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    2046           2 :         return err;
    2047           2 :       }
    2048             : 
    2049             :       /* https://github.com/anza-xyz/agave/blob/v4.4.0-beta.0/programs/bpf_loader/src/lib.rs#L719-L728 */
    2050         332 :       if( close_account_state->discriminant==FD_BPF_STATE_UNINITIALIZED ) {
    2051             : 
    2052             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1050-L1051 */
    2053          86 :         fd_guarded_borrowed_account_t recipient_account = {0};
    2054          86 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( instr_ctx, 1UL, &recipient_account );
    2055             : 
    2056          86 :         err = fd_borrowed_account_checked_add_lamports( &recipient_account, fd_borrowed_account_get_lamports( &close_account ) );
    2057          86 :         if( FD_UNLIKELY( err ) ) {
    2058           1 :           return err;
    2059           1 :         }
    2060          85 :         err = fd_borrowed_account_set_lamports( &close_account, 0UL );
    2061          85 :         if( FD_UNLIKELY( err ) ) {
    2062           1 :           return err;
    2063           1 :         }
    2064          84 :         err = fd_borrowed_account_set_data_length( &close_account, SIZE_OF_UNINITIALIZED );
    2065          84 :         if( FD_UNLIKELY( err ) ) {
    2066           0 :           return err;
    2067           0 :         }
    2068             :         /* Max msg_sz: 23 - 2 + 45 = 66 < 127 => we can use printf */
    2069          84 :         FD_BASE58_ENCODE_32_BYTES( close_key->uc, close_key_b58 );
    2070          84 :         fd_log_collector_printf_dangerous_max_127( instr_ctx, "Closed Uninitialized %s", close_key_b58 );
    2071             : 
    2072             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1057-L1068 */
    2073         246 :       } else if( close_account_state->discriminant==FD_BPF_STATE_BUFFER ) {
    2074             : 
    2075             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1059 */
    2076         158 :         fd_borrowed_account_drop( &close_account );
    2077             : 
    2078         158 :         if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 3U ) ) ) {
    2079           0 :           return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2080           0 :         }
    2081             : 
    2082         158 :         fd_bpf_state_buffer_t * state_buf = &close_account_state->inner.buffer;
    2083         158 :         err = common_close_account(
    2084         158 :             state_buf->has_authority_address ? &state_buf->authority_address : NULL,
    2085         158 :             instr_ctx,
    2086         158 :             close_account_state );
    2087         158 :         if( FD_UNLIKELY( err ) ) return err;
    2088             : 
    2089             :         /* Max msg_sz: 16 - 2 + 45 = 63 < 127 => we can use printf */
    2090         138 :         FD_BASE58_ENCODE_32_BYTES( close_key->uc, close_key_b58 );
    2091         138 :         fd_log_collector_printf_dangerous_max_127( instr_ctx, "Closed Buffer %s", close_key_b58 );
    2092             : 
    2093             :       /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1069-L1129 */
    2094         138 :       } else if( close_account_state->discriminant==FD_BPF_STATE_PROGRAM_DATA ) {
    2095          88 :         int err;
    2096          88 :         if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( instr_ctx, 4U ) ) ) {
    2097           0 :           return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2098           0 :         }
    2099             : 
    2100             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1074 */
    2101          88 :         fd_borrowed_account_drop( &close_account );
    2102             : 
    2103             :         /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1075-L1076 */
    2104          88 :         fd_guarded_borrowed_account_t program_account = {0};
    2105          88 :         FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK(instr_ctx, 3UL, &program_account );
    2106             : 
    2107          88 :         if( FD_UNLIKELY( !fd_borrowed_account_is_writable( &program_account ) ) ) {
    2108           0 :           fd_log_collector_msg_literal( instr_ctx, "Program account is not writable" );
    2109           0 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2110           0 :         }
    2111          88 :         if( FD_UNLIKELY( memcmp( fd_borrowed_account_get_owner( &program_account ), program_id, sizeof(fd_pubkey_t) ) ) ) {
    2112           1 :           fd_log_collector_msg_literal( instr_ctx, "Program account not owned by loader" );
    2113           1 :           return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    2114           1 :         }
    2115          87 :         fd_sol_sysvar_clock_t clock_;
    2116          87 :         fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( instr_ctx->sysvar_cache, &clock_ );
    2117          87 :         if( FD_UNLIKELY( !clock ) ) {
    2118           0 :           return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2119           0 :         }
    2120          87 :         if( FD_UNLIKELY( clock->slot==close_account_state->inner.program_data.slot ) ) {
    2121          75 :           fd_log_collector_msg_literal( instr_ctx,"Program was deployed in this block already" );
    2122          75 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2123          75 :         }
    2124             : 
    2125          12 :         fd_bpf_state_t program_state[1];
    2126          12 :         err = fd_bpf_loader_program_get_state( program_account.acc, program_state );
    2127          12 :         if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    2128           0 :           return err;
    2129           0 :         }
    2130             : 
    2131          12 :         if( program_state->discriminant==FD_BPF_STATE_PROGRAM ) {
    2132          12 :           if( FD_UNLIKELY( memcmp( &program_state->inner.program.programdata_address, close_key, sizeof(fd_pubkey_t) ) ) ) {
    2133           9 :             fd_log_collector_msg_literal( instr_ctx,"ProgramData account does not match ProgramData account" );
    2134           9 :             return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2135           9 :           }
    2136             : 
    2137             :           /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/bpf_loader/src/lib.rs#L1105 */
    2138           3 :           fd_borrowed_account_drop( &program_account );
    2139             : 
    2140           3 :           fd_bpf_state_program_data_t * pd = &close_account_state->inner.program_data;
    2141           3 :           err = common_close_account(
    2142           3 :               pd->has_upgrade_authority_address ? &pd->upgrade_authority_address : NULL,
    2143           3 :               instr_ctx,
    2144           3 :               close_account_state );
    2145           3 :           if( FD_UNLIKELY( err ) ) return err;
    2146             : 
    2147             :           /* Mark the closed programdata pd_write via the txn account (no
    2148             :              borrow is live here, and buffer/uninitialized closes going
    2149             :              through common_close_account must not set the bit). */
    2150           3 :           ushort pd_idx_in_txn;
    2151           3 :           err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( instr_ctx, 0U, &pd_idx_in_txn );
    2152           3 :           if( FD_UNLIKELY( err ) ) return err; /* unreachable */
    2153           3 :           instr_ctx->txn_out->accounts.account[ pd_idx_in_txn ]->pd_write = 1;
    2154             : 
    2155             :           /* Execution validates ProgramData and rejects a parent copy
    2156             :              if pd_write_this_slot is set, before consulting the program
    2157             :              cache. */
    2158             : 
    2159           3 :         } else {
    2160           0 :           fd_log_collector_msg_literal( instr_ctx, "Invalid Program account" );
    2161           0 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2162           0 :         }
    2163             : 
    2164             :         /* Max msg_sz: 17 - 2 + 45 = 60 < 127 => we can use printf */
    2165           3 :         FD_BASE58_ENCODE_32_BYTES( program_account.acc->pubkey, program_account_b58 );
    2166           3 :         fd_log_collector_printf_dangerous_max_127( instr_ctx, "Closed Program %s", program_account_b58 );
    2167             : 
    2168             :         /* program account is dropped when it goes out of scope */
    2169           3 :       } else {
    2170           0 :         fd_log_collector_msg_literal( instr_ctx, "Account does not support closing" );
    2171           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2172           0 :       }
    2173             : 
    2174             :       /* implicit drop of close account */
    2175         225 :       break;
    2176         332 :     }
    2177             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1158-L1170 */
    2178         381 :     case FD_BPF_INSTR_EXTEND_PROGRAM: {
    2179         381 :       err = common_extend_program( instr_ctx, instruction->inner.extend_program.additional_bytes, 0 );
    2180         381 :       if( FD_UNLIKELY( err ) ) {
    2181         381 :         return err;
    2182         381 :       }
    2183             : 
    2184           0 :       break;
    2185         381 :     }
    2186             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L1171-L1179 */
    2187         299 :     case FD_BPF_INSTR_EXTEND_PROGRAM_CHECKED: {
    2188         299 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2189         381 :     }
    2190             :     /* https://github.com/anza-xyz/agave/blob/v2.2.6/programs/bpf_loader/src/lib.rs#L1338-L1508 */
    2191         613 :     case FD_BPF_INSTR_MIGRATE: {
    2192             :       /* https://github.com/anza-xyz/agave/blob/v2.2.6/programs/bpf_loader/src/lib.rs#L1339-L1344 */
    2193         613 :       if( FD_UNLIKELY( !FD_FEATURE_ACTIVE_BANK( instr_ctx->bank, enable_loader_v4 ) ) ) {
    2194         613 :         return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2195         613 :       }
    2196             : 
    2197             :       /* TODO: Implement me */
    2198           0 :       FD_LOG_WARNING(( "migrate instruction is not implemented" ));
    2199           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2200         613 :     }
    2201           0 :     default: {
    2202           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    2203         613 :     }
    2204        3653 :   }
    2205        1225 :   return FD_EXECUTOR_INSTR_SUCCESS;
    2206        3653 : }
    2207             : 
    2208             : /* process_instruction_inner() */
    2209             : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L394-L564 */
    2210             : int
    2211        9973 : fd_bpf_loader_program_execute( fd_exec_instr_ctx_t * ctx ) {
    2212             :   /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L491-L529 */
    2213             : 
    2214             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L403-L404 */
    2215        9973 :   fd_guarded_borrowed_account_t program_account = {0};
    2216        9973 :   int err = fd_exec_instr_ctx_try_borrow_last_program_account( ctx, &program_account );
    2217        9973 :   if( FD_UNLIKELY( err ) ) {
    2218           0 :     return err;
    2219           0 :   }
    2220             : 
    2221             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/bpf_loader/src/lib.rs#L409 */
    2222        9973 :   fd_pubkey_t const * program_id = NULL;
    2223        9973 :   err = fd_exec_instr_ctx_get_last_program_key( ctx, &program_id );
    2224        9973 :   if( FD_UNLIKELY( err ) ) {
    2225           0 :     return err;
    2226           0 :   }
    2227             : 
    2228             :   /* Program management instruction */
    2229        9973 :   if( FD_UNLIKELY( !memcmp( &fd_solana_native_loader_id, fd_borrowed_account_get_owner( &program_account ), sizeof(fd_pubkey_t) ) ) ) {
    2230             :     /* https://github.com/anza-xyz/agave/blob/v2.2.3/programs/bpf_loader/src/lib.rs#L416 */
    2231        3735 :     fd_borrowed_account_drop( &program_account );
    2232             : 
    2233        3735 :     if( FD_UNLIKELY( !memcmp( &fd_solana_bpf_loader_upgradeable_program_id, program_id, sizeof(fd_pubkey_t) ) ) ) {
    2234        3710 :       FD_EXEC_CU_UPDATE( ctx, UPGRADEABLE_LOADER_COMPUTE_UNITS );
    2235        3704 :       return process_loader_upgradeable_instruction( ctx );
    2236        3710 :     } else if( FD_UNLIKELY( !memcmp( &fd_solana_bpf_loader_program_id, program_id, sizeof(fd_pubkey_t) ) ) ) {
    2237          26 :       FD_EXEC_CU_UPDATE( ctx, DEFAULT_LOADER_COMPUTE_UNITS );
    2238          26 :       fd_log_collector_msg_literal( ctx, "BPF loader management instructions are no longer supported" );
    2239          26 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2240 >1844*10^16 :     } else if( FD_UNLIKELY( !memcmp( &fd_solana_bpf_loader_deprecated_program_id, program_id, sizeof(fd_pubkey_t) ) ) ) {
    2241           2 :       FD_EXEC_CU_UPDATE( ctx, DEPRECATED_LOADER_COMPUTE_UNITS );
    2242           2 :       fd_log_collector_msg_literal( ctx, "Deprecated loader is no longer supported" );
    2243           2 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2244 >1844*10^16 :     } else {
    2245 >1844*10^16 :       fd_log_collector_msg_literal( ctx, "Invalid BPF loader id" );
    2246 >1844*10^16 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2247 >1844*10^16 :     }
    2248        3735 :   }
    2249             : 
    2250             :   /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L551-L563 */
    2251             :   /* The Agave client stores a loaded program type state in its implementation
    2252             :      of the loaded program cache. It checks to see if an account is able to be
    2253             :      executed. It is possible for a program to be in the DelayVisibility state or
    2254             :      Closed state but it won't be reflected in the Firedancer cache. Program
    2255             :      accounts that are in this state should exit with an unsupported program
    2256             :      id error. For programs that are recently deployed or upgraded, they should not
    2257             :      be allowed to be executed for the remainder of the slot. For closed
    2258             :      accounts, they're uninitialized and shouldn't be executed as well.
    2259             : 
    2260             :      For the former case the slot that the
    2261             :      program was last updated in is in the program data account.
    2262             :      This means that if the slot in the program data account is greater than or
    2263             :      equal to the current execution slot, then the account is in a
    2264             :      'LoadedProgramType::DelayVisiblity' state.
    2265             : 
    2266             :      The latter case as described above is a tombstone account which is in a Closed
    2267             :      state. This occurs when a program data account is closed. However, our cache
    2268             :      does not track this. Instead, this can be checked for by seeing if the program
    2269             :      account's respective program data account is uninitialized. This should only
    2270             :      happen when the account is closed.
    2271             : 
    2272             :      The programdata account here is fetched via fd_runtime_get_executable_account,
    2273             :      which may return a copy read from the parent fork.  A parent copy's
    2274             :      program_data.slot cannot reflect a current-slot deploy/upgrade/extend/close,
    2275             :      so the DelayVisibility gate below is provenance-aware: current-fork copies keep
    2276             :      the slot comparison, parent-fork copies gate on the accdb pd_write probe
    2277             :      result instead. */
    2278             : 
    2279        6238 :   uchar is_deprecated = !memcmp( program_account.acc->owner, &fd_solana_bpf_loader_deprecated_program_id, sizeof(fd_pubkey_t) );
    2280             : 
    2281        6238 :   fd_acc_t const * progdata_ro = program_account.acc;
    2282        6238 :   if( !memcmp( program_account.acc->owner, &fd_solana_bpf_loader_upgradeable_program_id, sizeof(fd_pubkey_t) ) ) {
    2283        2400 :     fd_bpf_state_t program_account_state[1];
    2284        2400 :     err = fd_bpf_loader_program_get_state( program_account.acc, program_account_state );
    2285        2400 :     if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    2286           1 :       fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2287           1 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2288           1 :     }
    2289             : 
    2290             :     /* https://github.com/anza-xyz/agave/blob/v2.0.9/svm/src/program_loader.rs#L96-L98
    2291             :        Program account and program data account discriminants get checked when loading in program accounts
    2292             :        into the program cache. If the discriminants are incorrect, the program is marked as closed. */
    2293        2399 :     if( FD_UNLIKELY( program_account_state->discriminant!=FD_BPF_STATE_PROGRAM ) ) {
    2294             :       /* https://github.com/anza-xyz/agave/tree/v3.0.5/programs/bpf_loader/src/lib.rs#L424-L433
    2295             :          Agave's program cache will add any non-migrating built-ins as built-in
    2296             :          accounts, even though they might be owned by the BPF loader. In these
    2297             :          cases, Agave does not log this message. Meanwhile, non-migrating
    2298             :          built-in programs do not use the BPF loader, by definition. */
    2299         204 :       if( !fd_is_non_migrating_builtin_program( program_id ) ) {
    2300         203 :         fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2301         203 :       }
    2302         204 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2303         204 :     }
    2304             : 
    2305        2195 :     fd_pubkey_t * programdata_pubkey = &program_account_state->inner.program.programdata_address;
    2306        2195 :     int from_parent_copy   = 0;
    2307        2195 :     int pd_write_this_slot = 0;
    2308        2195 :     progdata_ro = fd_runtime_get_executable_account( ctx->txn_out, programdata_pubkey, &from_parent_copy, &pd_write_this_slot );
    2309        2195 :     if( FD_UNLIKELY( !progdata_ro ) ) {
    2310        1201 :       fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2311        1201 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2312        1201 :     }
    2313             : 
    2314         994 :     if( FD_UNLIKELY( progdata_ro->data_len<PROGRAMDATA_METADATA_SIZE ) ) {
    2315          19 :       fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2316          19 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2317          19 :     }
    2318             : 
    2319         975 :     fd_bpf_state_t program_data_account_state[1];
    2320         975 :     err = fd_bpf_loader_program_get_state( progdata_ro, program_data_account_state );
    2321         975 :     if( FD_UNLIKELY( err!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
    2322           6 :       fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2323           6 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2324           6 :     }
    2325             : 
    2326             :     /* https://github.com/anza-xyz/agave/blob/v2.0.9/svm/src/program_loader.rs#L100-L104
    2327             :        Same as above comment. Program data discriminant must be set correctly. */
    2328         969 :     if( FD_UNLIKELY( program_data_account_state->discriminant!=FD_BPF_STATE_PROGRAM_DATA ) ) {
    2329             :       /* The account is closed. */
    2330           0 :       fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2331           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2332           0 :     }
    2333             : 
    2334         969 :     ulong program_data_slot = program_data_account_state->inner.program_data.slot;
    2335         969 :     if( FD_LIKELY( !from_parent_copy ) ) {
    2336         969 :       if( FD_UNLIKELY( program_data_slot>=ctx->bank->f.slot ) ) {
    2337             :         /* The account was likely just deployed or upgraded. Corresponds to
    2338             :            'LoadedProgramType::DelayVisibility' */
    2339           1 :         fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2340           1 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2341           1 :       }
    2342         969 :     } else {
    2343           0 :       if( FD_UNLIKELY( pd_write_this_slot ) ) {
    2344           0 :         fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2345           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2346           0 :       }
    2347           0 :     }
    2348         969 :   }
    2349             : 
    2350        4806 :   fd_prog_load_env_t load_env[1]; fd_prog_load_env_from_bank( load_env, ctx->bank );
    2351        4806 :   fd_progcache_t * progcache = ctx->runtime->progcache;
    2352        4806 :   fd_progcache_rec_t * cache_entry =
    2353        4806 :       fd_progcache_pull( progcache, ctx->bank->progcache_fork_id, program_id, load_env, progdata_ro );
    2354        4806 :   if( FD_UNLIKELY( !cache_entry ) ) {
    2355           1 :     fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2356           1 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2357           1 :   }
    2358             : 
    2359             :   /* The program may be in the cache but could have failed verification in the current epoch. */
    2360        4805 :   if( FD_UNLIKELY( !cache_entry->data_gaddr ) ) {
    2361         576 :     fd_progcache_rec_close( progcache, cache_entry );
    2362         576 :     fd_log_collector_msg_literal( ctx, "Program is not deployed" );
    2363         576 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    2364         576 :   }
    2365             : 
    2366             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/bpf_loader/src/lib.rs#L446 */
    2367        4229 :   fd_borrowed_account_drop( &program_account );
    2368             : 
    2369        4229 :   int exec_err = fd_bpf_execute( ctx, cache_entry, is_deprecated );
    2370        4229 :   fd_progcache_rec_close( progcache, cache_entry );
    2371        4229 :   return exec_err;
    2372        4805 : }

Generated by: LCOV version 1.14