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: 705 1562 45.1 %
Date: 2026-08-19 04:32:02 Functions: 12 13 92.3 %

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

Generated by: LCOV version 1.14