LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_core_bpf_migration.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 501 0.0 %
Date: 2026-04-10 06:33:15 Functions: 0 15 0.0 %

          Line data    Source code
       1             : #include "fd_accdb_svm.h"
       2             : #include "sysvar/fd_sysvar_rent.h"
       3             : #include "program/fd_bpf_loader_program.h"
       4             : #include "program/fd_builtin_programs.h"
       5             : #include "program/fd_program_util.h"
       6             : #include "fd_runtime_stack.h"
       7             : #include "fd_pubkey_utils.h"
       8             : #include "fd_system_ids.h"
       9             : #include "../accdb/fd_accdb_sync.h"
      10             : #include "../../ballet/sha256/fd_sha256.h"
      11             : #include "../../ballet/sbpf/fd_sbpf_loader.h"
      12             : #include "../progcache/fd_prog_load.h"
      13             : #include "../vm/fd_vm.h"
      14             : #include <assert.h>
      15             : 
      16             : static fd_pubkey_t
      17           0 : get_program_data_address( fd_pubkey_t const * program_addr ) {
      18           0 :   uchar const * seed    = program_addr->uc;
      19           0 :   ulong         seed_sz = 32UL;
      20           0 :   fd_pubkey_t   out;
      21           0 :   uint          custom_err;
      22           0 :   uchar         out_bump_seed;
      23           0 :   int err = fd_pubkey_find_program_address( &fd_solana_bpf_loader_upgradeable_program_id, 1UL, &seed, &seed_sz, &out, &out_bump_seed, &custom_err );
      24           0 :   if( FD_UNLIKELY( err ) ) {
      25             :     /* https://github.com/anza-xyz/solana-sdk/blob/address%40v2.1.0/address/src/syscalls.rs#L277-L279 */
      26           0 :     FD_LOG_ERR(( "Unable to find a viable program address bump seed" ));
      27           0 :   }
      28           0 :   return out;
      29           0 : }
      30             : 
      31             : fd_tmp_account_t *
      32             : tmp_account_new( fd_tmp_account_t * acc,
      33           0 :                  ulong              acc_sz ) {
      34           0 :   acc->data_sz = acc_sz;
      35           0 :   fd_memset( acc->data, 0, acc_sz );
      36           0 :   return acc;
      37           0 : }
      38             : 
      39             : fd_tmp_account_t *
      40             : tmp_account_read( fd_tmp_account_t *        acc,
      41             :                   fd_accdb_user_t *         accdb,
      42             :                   fd_funk_txn_xid_t const * xid,
      43           0 :                   fd_pubkey_t const *       addr ) {
      44           0 :   fd_accdb_ro_t ro[1];
      45           0 :   if( FD_LIKELY( !fd_accdb_open_ro( accdb, ro, xid, addr ) ) ) return NULL;
      46           0 :   tmp_account_new( acc, fd_accdb_ref_data_sz( ro ) );
      47           0 :   acc->meta = *ro->meta;
      48           0 :   acc->addr = *addr;
      49           0 :   fd_memcpy( acc->data, fd_accdb_ref_data_const( ro ), fd_accdb_ref_data_sz( ro ) );
      50           0 :   acc->data_sz = fd_accdb_ref_data_sz( ro );
      51           0 :   fd_accdb_close_ro( accdb, ro );
      52           0 :   return acc;
      53           0 : }
      54             : 
      55             : void
      56             : tmp_account_store( fd_tmp_account_t *        acc,
      57             :                    fd_accdb_user_t *         accdb,
      58             :                    fd_funk_txn_xid_t const * xid,
      59             :                    fd_bank_t *               bank,
      60           0 :                    fd_capture_ctx_t *        capture_ctx ) {
      61           0 :   if( FD_UNLIKELY( fd_pubkey_eq( &acc->addr, &fd_solana_system_program_id ) ) ) {
      62           0 :     FD_LOG_ERR(( "Attempted to write to the system program account" ));
      63           0 :   }
      64             : 
      65           0 :   fd_accdb_rw_t rw[1]; fd_accdb_svm_update_t update[1];
      66           0 :   FD_TEST( fd_accdb_svm_open_rw( accdb, bank, xid, rw, update, &acc->addr, acc->data_sz, FD_ACCDB_FLAG_CREATE ) );
      67             : 
      68           0 :   fd_accdb_ref_exec_bit_set( rw, acc->meta.executable );
      69           0 :   fd_accdb_ref_owner_set   ( rw, acc->meta.owner      );
      70           0 :   fd_accdb_ref_lamports_set( rw, acc->meta.lamports   );
      71           0 :   fd_accdb_ref_data_set    ( accdb, rw, acc->data, acc->data_sz );
      72             : 
      73           0 :   fd_accdb_svm_close_rw( accdb, bank, capture_ctx, rw, update );
      74           0 : }
      75             : 
      76             : /* https://github.com/anza-xyz/agave/blob/v3.0.2/runtime/src/bank/builtins/core_bpf_migration/target_core_bpf.rs#L12 */
      77             : 
      78             : struct target_core_bpf {
      79             :   fd_pubkey_t        program_address;
      80             :   fd_tmp_account_t * program_data_account;
      81             :   fd_pubkey_t        upgrade_authority_address;
      82             :   uint               has_upgrade_authority_address : 1;
      83             : };
      84             : 
      85             : typedef struct target_core_bpf target_core_bpf_t;
      86             : 
      87             : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L19 */
      88             : 
      89             : struct target_builtin {
      90             :   fd_tmp_account_t * program_account;
      91             :   fd_pubkey_t        program_data_address;
      92             :   ulong              program_data_account_lamports;
      93             : };
      94             : 
      95             : typedef struct target_builtin target_builtin_t;
      96             : 
      97             : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L25-L91 */
      98             : 
      99             : target_builtin_t *
     100             : target_builtin_new_checked( target_builtin_t *        target_builtin,
     101             :                             fd_pubkey_t const *       program_address,
     102             :                             int                       migration_target,
     103             :                             int                       relax_programdata_account_check_migration,
     104             :                             fd_accdb_user_t *         accdb,
     105             :                             fd_funk_txn_xid_t const * xid,
     106           0 :                             fd_runtime_stack_t *      runtime_stack ) {
     107             : 
     108             :   /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L31-L53 */
     109             : 
     110           0 :   fd_tmp_account_t * program_account = &runtime_stack->bpf_migration.program_account;
     111           0 :   switch( migration_target ) {
     112           0 :   case FD_CORE_BPF_MIGRATION_TARGET_BUILTIN:
     113           0 :     if( FD_UNLIKELY( !tmp_account_read( program_account, accdb, xid, program_address ) ) ) {
     114             :       /* CoreBpfMigrationError::AccountNotFound(*program_address) */
     115           0 :       return NULL;
     116           0 :     }
     117           0 :     if( FD_UNLIKELY( 0!=memcmp( program_account->meta.owner, &fd_solana_native_loader_id, 32 ) ) ) {
     118             :       /* CoreBpfMigrationError::IncorrectOwner(*program_address) */
     119           0 :       return NULL;
     120           0 :     }
     121           0 :     break;
     122           0 :   case FD_CORE_BPF_MIGRATION_TARGET_STATELESS: {
     123             :     /* Program account should not exist */
     124           0 :     fd_accdb_ro_t ro[1];
     125           0 :     int progdata_exists = !!fd_accdb_open_ro( accdb, ro, xid, program_address );
     126           0 :     if( progdata_exists ) {
     127             :       /* CoreBpfMigrationError::AccountAlreadyExists(*program_address) */
     128           0 :       fd_accdb_close_ro( accdb, ro );
     129           0 :       return NULL;
     130           0 :     }
     131           0 :     break;
     132           0 :   }
     133           0 :   default:
     134           0 :     FD_LOG_ERR(( "invalid migration_target %d", migration_target ));
     135           0 :   }
     136             : 
     137             :   /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L55 */
     138             : 
     139           0 :   fd_pubkey_t program_data_address = get_program_data_address( program_address );
     140             : 
     141             :   /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L57-L82 */
     142             : 
     143           0 :   ulong program_data_account_lamports = 0UL;
     144           0 :   do {
     145             :     /* Program data account should not exist */
     146           0 :     fd_accdb_ro_t ro[1];
     147           0 :     int progdata_exists = !!fd_accdb_open_ro( accdb, ro, xid, &program_data_address );
     148             : 
     149             :     /* SIMD-0444: relax_programdata_account_check_migration
     150             :        https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L57-L70 */
     151           0 :     if( relax_programdata_account_check_migration ) {
     152             :       /* The program data account should not exist, but a system
     153             :          account with funded lamports is acceptable. */
     154           0 :       if( FD_UNLIKELY( progdata_exists ) ) {
     155           0 :         if( FD_UNLIKELY( !fd_pubkey_eq( fd_accdb_ref_owner( ro ), &fd_solana_system_program_id ) ) ) {
     156             :           /* CoreBpfMigrationError::ProgramHasDataAccount(*program_address) */
     157           0 :           fd_accdb_close_ro( accdb, ro );
     158           0 :           return NULL;
     159           0 :         } else {
     160           0 :           program_data_account_lamports = fd_accdb_ref_lamports( ro );
     161           0 :           fd_accdb_close_ro( accdb, ro );
     162           0 :         }
     163           0 :       }
     164           0 :     } else {
     165             :       /* If relax_programdata_account_check_migration is not enabled,
     166             :          we do not allow the program data account to exist at all. */
     167           0 :       if( FD_UNLIKELY( progdata_exists ) ) {
     168             :         /* CoreBpfMigrationError::AccountAlreadyExists(*program_address) */
     169           0 :         fd_accdb_close_ro( accdb, ro );
     170           0 :         return NULL;
     171           0 :       }
     172           0 :     }
     173           0 :   } while(0);
     174             : 
     175             :   /* https://github.com/anza-xyz/agave/blob/v3.0.2/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L63-L67 */
     176             : 
     177           0 :   *target_builtin = (target_builtin_t) {
     178           0 :     .program_account               = program_account,
     179           0 :     .program_data_address          = program_data_address,
     180           0 :     .program_data_account_lamports = program_data_account_lamports
     181           0 :   };
     182           0 :   return target_builtin;
     183           0 : }
     184             : 
     185             : /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/target_core_bpf.rs#L26-L93 */
     186             : static target_core_bpf_t *
     187             : target_core_bpf_new_checked( target_core_bpf_t *       target_core_bpf,
     188             :                              fd_pubkey_t const *       program_address,
     189             :                              fd_accdb_user_t *         accdb,
     190             :                              fd_funk_txn_xid_t const * xid,
     191           0 :                              fd_runtime_stack_t *      runtime_stack ) {
     192           0 :   fd_pubkey_t program_data_address = get_program_data_address( program_address );
     193             : 
     194             :   /* The program account should exist */
     195           0 :   fd_tmp_account_t * program_account = &runtime_stack->bpf_migration.program_account;
     196           0 :   if( FD_UNLIKELY( !tmp_account_read( program_account, accdb, xid, program_address ) ) ) {
     197           0 :     return NULL;
     198           0 :   }
     199             : 
     200             :   /* The program account should be owned by the upgradeable loader */
     201           0 :   if( FD_UNLIKELY( 0!=memcmp( program_account->meta.owner, &fd_solana_bpf_loader_upgradeable_program_id, sizeof(fd_pubkey_t) ) ) ) {
     202           0 :     return NULL;
     203           0 :   }
     204             : 
     205             :   /* The program account should be executable */
     206           0 :   if( FD_UNLIKELY( !program_account->meta.executable ) ) {
     207           0 :     return NULL;
     208           0 :   }
     209             : 
     210             :   /* Decode and validate program account state */
     211           0 :   fd_bpf_upgradeable_loader_state_t program_state[1];
     212           0 :   if( FD_UNLIKELY( FD_EXECUTOR_INSTR_SUCCESS!=fd_bpf_loader_program_get_state( &program_account->meta, program_state ) ) ) {
     213           0 :     return NULL;
     214           0 :   }
     215           0 :   if( FD_UNLIKELY( !fd_bpf_upgradeable_loader_state_is_program( program_state ) ) ) {
     216           0 :     return NULL;
     217           0 :   }
     218           0 :   if( FD_UNLIKELY( 0!=memcmp( &program_state->inner.program.programdata_address, &program_data_address, sizeof(fd_pubkey_t) ) ) ) {
     219           0 :     return NULL;
     220           0 :   }
     221             : 
     222             :   /* The program data account should exist */
     223           0 :   fd_tmp_account_t * program_data_account = &runtime_stack->bpf_migration.new_target_program;
     224           0 :   if( FD_UNLIKELY( !tmp_account_read( program_data_account, accdb, xid, &program_data_address ) ) ) {
     225           0 :     return NULL;
     226           0 :   }
     227             : 
     228             :   /* The program data account should be owned by the upgradeable loader */
     229           0 :   if( FD_UNLIKELY( 0!=memcmp( program_data_account->meta.owner, &fd_solana_bpf_loader_upgradeable_program_id, sizeof(fd_pubkey_t) ) ) ) {
     230           0 :     return NULL;
     231           0 :   }
     232             : 
     233             :   /* Decode and validate program data account state */
     234           0 :   fd_bpf_upgradeable_loader_state_t programdata_state[1];
     235           0 :   if( FD_UNLIKELY( FD_EXECUTOR_INSTR_SUCCESS!=fd_bpf_loader_program_get_state( &program_data_account->meta, programdata_state ) ) ) {
     236           0 :     return NULL;
     237           0 :   }
     238           0 :   if( FD_UNLIKELY( !fd_bpf_upgradeable_loader_state_is_program_data( programdata_state ) ) ) {
     239           0 :     return NULL;
     240           0 :   }
     241             : 
     242             :   /* Extract upgrade authority from program data state */
     243           0 :   fd_pubkey_t upgrade_authority_address;
     244           0 :   if( programdata_state->inner.program_data.has_upgrade_authority_address ) {
     245           0 :     upgrade_authority_address = programdata_state->inner.program_data.upgrade_authority_address;
     246           0 :   } else {
     247           0 :     fd_memset( &upgrade_authority_address, 0, sizeof(fd_pubkey_t) );
     248           0 :   }
     249             : 
     250           0 :   *target_core_bpf = (target_core_bpf_t) {
     251           0 :     .program_address                = *program_address,
     252           0 :     .program_data_account           = program_data_account,
     253           0 :     .upgrade_authority_address      = upgrade_authority_address,
     254           0 :     .has_upgrade_authority_address  = (uint)!!programdata_state->inner.program_data.has_upgrade_authority_address
     255           0 :   };
     256           0 :   return target_core_bpf;
     257           0 : }
     258             : 
     259             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L25-L82
     260             : 
     261             :    Agave uses a separate TargetBpfV2 struct, but it has the
     262             :    same layout as target_builtin_t so we reuse that. */
     263             : static target_builtin_t *
     264             : target_bpf_v2_new_checked( target_builtin_t *        target_bpf_v2,
     265             :                            fd_pubkey_t const *       program_address,
     266             :                            int                       allow_prefunded,
     267             :                            fd_accdb_user_t *         accdb,
     268             :                            fd_funk_txn_xid_t const * xid,
     269           0 :                            fd_runtime_stack_t *      runtime_stack ) {
     270             : 
     271             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L30-L33 */
     272           0 :   fd_tmp_account_t * program_account = &runtime_stack->bpf_migration.program_account;
     273           0 :   if( FD_UNLIKELY( !tmp_account_read( program_account, accdb, xid, program_address ) ) ) {
     274             :     /* CoreBpfMigrationError::AccountNotFound(*program_address) */
     275           0 :     return NULL;
     276           0 :   }
     277             : 
     278             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L35-L38 */
     279           0 :   if( FD_UNLIKELY( 0!=memcmp( program_account->meta.owner, &fd_solana_bpf_loader_program_id, FD_PUBKEY_FOOTPRINT ) ) ) {
     280             :     /* CoreBpfMigrationError::IncorrectOwner(*program_address) */
     281           0 :     return NULL;
     282           0 :   }
     283             : 
     284             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L40-L45 */
     285           0 :   if( FD_UNLIKELY( !program_account->meta.executable ) ) {
     286             :     /* CoreBpfMigrationError::ProgramAccountNotExecutable(*program_address) */
     287           0 :     return NULL;
     288           0 :   }
     289             : 
     290             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L47 */
     291           0 :   fd_pubkey_t program_data_address = get_program_data_address( program_address );
     292             : 
     293             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L49-L74 */
     294           0 :   ulong program_data_account_lamports = 0UL;
     295           0 :   do {
     296           0 :     fd_accdb_ro_t ro[1];
     297           0 :     int progdata_exists = !!fd_accdb_open_ro( accdb, ro, xid, &program_data_address );
     298             : 
     299             :     /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L49-L74 */
     300           0 :     if( FD_LIKELY( allow_prefunded ) ) {
     301             :       /* The program data account should not exist, but a system
     302             :          account with funded lamports is acceptable.
     303             : 
     304             :          https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L50-L61 */
     305           0 :       if( FD_UNLIKELY( progdata_exists ) ) {
     306           0 :         if( FD_UNLIKELY( !fd_pubkey_eq( fd_accdb_ref_owner( ro ), &fd_solana_system_program_id ) ) ) {
     307             :           /* CoreBpfMigrationError::ProgramHasDataAccount(*program_address) */
     308           0 :           fd_accdb_close_ro( accdb, ro );
     309           0 :           return NULL;
     310           0 :         } else {
     311           0 :           program_data_account_lamports = fd_accdb_ref_lamports( ro );
     312           0 :           fd_accdb_close_ro( accdb, ro );
     313           0 :         }
     314           0 :       }
     315           0 :     } else {
     316             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/target_bpf_v2.rs#L62-L74 */
     317           0 :       if( FD_UNLIKELY( progdata_exists ) ) {
     318             :         /* CoreBpfMigrationError::ProgramHasDataAccount(*program_address) */
     319           0 :         fd_accdb_close_ro( accdb, ro );
     320           0 :         return NULL;
     321           0 :       }
     322           0 :     }
     323           0 :   } while(0);
     324             : 
     325           0 :   *target_bpf_v2 = (target_builtin_t) {
     326           0 :     .program_account               = program_account,
     327           0 :     .program_data_address          = program_data_address,
     328           0 :     .program_data_account_lamports = program_data_account_lamports
     329           0 :   };
     330           0 :   return target_bpf_v2;
     331           0 : }
     332             : 
     333             : /* This function contains the deployment checks that are equivalent to
     334             :    Agave's directly_invoke_loader_v3_deploy.
     335             : 
     336             :    There is no direct equivalent in Agave to this function, because
     337             :    we are not updating the program cache here. However, we do the same
     338             :    checks that our program cache does upon deployment.
     339             : 
     340             :    This is safe because the bpf migration code runs at the epoch
     341             :    boundary, before any transaction execution. The program cache
     342             :    automatically invalidates all programs at the start of an epoch
     343             :    boundary, so we do not need to explicitly update the cache during the
     344             :    migration.
     345             : 
     346             :    https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L120-L218 */
     347             : static int
     348             : fd_directly_invoke_loader_v3_deploy_checks( fd_bank_t const *    bank,
     349             :                                             fd_runtime_stack_t * runtime_stack,
     350             :                                             uchar const *        elf,
     351           0 :                                             ulong                elf_sz ) {
     352           0 :   fd_features_t const * features = &bank->f.features;
     353           0 :   ulong                 slot     = bank->f.slot;
     354             : 
     355             :   /* ELF verification with deploy checks enabled */
     356           0 :   fd_prog_versions_t versions = fd_prog_versions( features, slot );
     357           0 :   fd_sbpf_loader_config_t loader_config = {
     358           0 :     .elf_deploy_checks = 1,
     359           0 :     .sbpf_min_version  = versions.min_sbpf_version,
     360           0 :     .sbpf_max_version  = versions.max_sbpf_version,
     361           0 :   };
     362           0 :   fd_sbpf_elf_info_t elf_info[1];
     363           0 :   if( FD_UNLIKELY( fd_sbpf_elf_peek( elf_info, elf, elf_sz, &loader_config )!=FD_SBPF_ELF_SUCCESS ) ) return 1;
     364             : 
     365             :   /* Setup program (includes calldests) */
     366           0 :   fd_sbpf_program_t * prog = fd_sbpf_program_new(
     367           0 :     runtime_stack->bpf_migration.progcache_validate.sbpf_footprint,
     368           0 :     elf_info,
     369           0 :     runtime_stack->bpf_migration.progcache_validate.rodata );
     370           0 :   if( FD_UNLIKELY( !prog ) ) return 1;
     371             : 
     372           0 :   fd_sbpf_syscalls_t _syscalls[ FD_SBPF_SYSCALLS_SLOT_CNT ];
     373           0 :   fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_join( fd_sbpf_syscalls_new( _syscalls ) );
     374           0 :   if( FD_UNLIKELY( !syscalls ) ) return 1;
     375           0 :   if( FD_UNLIKELY( fd_vm_syscall_register_slot( syscalls, slot, features, /* is_deploy */ 1 )!=FD_VM_SUCCESS ) ) return 1;
     376             : 
     377             :   /* fd_sbpf_program_load checks */
     378           0 :   if( FD_UNLIKELY( fd_sbpf_program_load(
     379           0 :     prog,
     380           0 :     elf,
     381           0 :     elf_sz,
     382           0 :     syscalls,
     383           0 :     &loader_config,
     384           0 :     runtime_stack->bpf_migration.progcache_validate.programdata,
     385           0 :     sizeof(runtime_stack->bpf_migration.progcache_validate.programdata) ) ) ) return 1;
     386             : 
     387             :   /* fd_vm_validate checks */
     388           0 :   fd_vm_t _vm[1];
     389           0 :   fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
     390           0 :   if( FD_UNLIKELY( !vm ) ) return 1;
     391           0 :   vm = fd_vm_init( vm,
     392           0 :                    NULL,
     393           0 :                    0UL,
     394           0 :                    0UL,
     395           0 :                    prog->rodata,
     396           0 :                    prog->rodata_sz,
     397           0 :                    prog->text,
     398           0 :                    prog->info.text_cnt,
     399           0 :                    prog->info.text_off,
     400           0 :                    prog->info.text_sz,
     401           0 :                    prog->entry_pc,
     402           0 :                    prog->calldests,
     403           0 :                    elf_info->sbpf_version,
     404           0 :                    syscalls,
     405           0 :                    NULL,
     406           0 :                    NULL,
     407           0 :                    NULL,
     408           0 :                    0U,
     409           0 :                    NULL,
     410           0 :                    0,
     411           0 :                    FD_FEATURE_ACTIVE( slot, features, account_data_direct_mapping ),
     412           0 :                    FD_FEATURE_ACTIVE( slot, features, syscall_parameter_address_restrictions ),
     413           0 :                    FD_FEATURE_ACTIVE( slot, features, virtual_address_space_adjustments ),
     414           0 :                    0,
     415           0 :                    0UL );
     416           0 :   if( FD_UNLIKELY( !vm ) ) return 1;
     417           0 :   if( FD_UNLIKELY( fd_vm_validate( vm )!=FD_VM_SUCCESS ) ) return 1;
     418             : 
     419           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     420           0 : }
     421             : 
     422             : /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L51-L75 */
     423             : 
     424             : static fd_tmp_account_t *
     425             : source_buffer_new_checked( fd_tmp_account_t *        acc,
     426             :                            fd_accdb_user_t *         accdb,
     427             :                            fd_funk_txn_xid_t const * xid,
     428             :                            fd_pubkey_t const *       pubkey,
     429           0 :                            fd_hash_t const *         verified_build_hash ) {
     430             : 
     431           0 :   if( FD_UNLIKELY( !tmp_account_read( acc, accdb, xid, pubkey ) ) ) {
     432             :     /* CoreBpfMigrationError::AccountNotFound(*buffer_address) */
     433           0 :     return NULL;
     434           0 :   }
     435             : 
     436           0 :   if( FD_UNLIKELY( 0!=memcmp( acc->meta.owner, &fd_solana_bpf_loader_upgradeable_program_id, 32 ) ) ) {
     437             :     /* CoreBpfMigrationError::IncorrectOwner(*buffer_address) */
     438           0 :     return NULL;
     439           0 :   }
     440             : 
     441           0 :   if( acc->data_sz < BUFFER_METADATA_SIZE ) {
     442             :     /* CoreBpfMigrationError::InvalidBufferAccount(*buffer_address) */
     443           0 :     return NULL;
     444           0 :   }
     445             : 
     446           0 :   fd_bpf_upgradeable_loader_state_t state[1];
     447           0 :   if( FD_UNLIKELY( !fd_bincode_decode_static(
     448           0 :       bpf_upgradeable_loader_state, state,
     449           0 :       acc->data, BUFFER_METADATA_SIZE ) ) ) {
     450           0 :     return NULL;
     451           0 :   }
     452             : 
     453           0 :   if( FD_UNLIKELY( state->discriminant!=fd_bpf_upgradeable_loader_state_enum_buffer ) ) {
     454             :     /* CoreBpfMigrationError::InvalidBufferAccount(*buffer_address) */
     455           0 :     return NULL;
     456           0 :   }
     457             : 
     458             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L61-L71 */
     459           0 :   if( verified_build_hash ) {
     460             :     /* Strip trailing zero-padding before hashing
     461             :        https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L61-L63 */
     462           0 :     uchar const * data       = (uchar const *)acc->data;
     463           0 :     ulong         offset     = BUFFER_METADATA_SIZE;
     464           0 :     ulong         end_offset = acc->data_sz;
     465           0 :     while( end_offset>offset && data[end_offset-1]==0 ) end_offset--;
     466           0 :     uchar const * buffer_program_data    = data + offset;
     467           0 :     ulong         buffer_program_data_sz = end_offset - offset;
     468             : 
     469           0 :     fd_hash_t hash;
     470           0 :     fd_sha256_hash( buffer_program_data, buffer_program_data_sz, hash.uc );
     471           0 :     if( FD_UNLIKELY( 0!=memcmp( hash.uc, verified_build_hash->uc, FD_HASH_FOOTPRINT ) ) ) {
     472             :       /* CoreBpfMigrationError::BuildHashMismatch */
     473           0 :       return NULL;
     474           0 :     }
     475           0 :   }
     476             : 
     477           0 :   return acc;
     478           0 : }
     479             : 
     480             : /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L82-L95 */
     481             : 
     482             : static fd_tmp_account_t *
     483             : new_target_program_account( fd_tmp_account_t *        acc,
     484             :                             target_builtin_t const *  target,
     485           0 :                             fd_rent_t const *         rent ) {
     486             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L86-L88 */
     487           0 :   fd_bpf_upgradeable_loader_state_t state = {
     488           0 :     .discriminant = fd_bpf_upgradeable_loader_state_enum_program,
     489           0 :     .inner = {
     490           0 :       .program = {
     491           0 :         .programdata_address = target->program_data_address,
     492           0 :       }
     493           0 :     }
     494           0 :   };
     495             : 
     496           0 :   ulong state_sz = fd_bpf_upgradeable_loader_state_size( &state );
     497           0 :   tmp_account_new( acc, state_sz );
     498           0 :   acc->meta.lamports   = fd_rent_exempt_minimum_balance( rent, SIZE_OF_PROGRAM );
     499           0 :   acc->meta.executable = 1;
     500           0 :   memcpy( acc->meta.owner, fd_solana_bpf_loader_upgradeable_program_id.uc, sizeof(fd_pubkey_t) );
     501             : 
     502           0 :   fd_bincode_encode_ctx_t ctx = { .data=acc->data, .dataend=(uchar *)acc->data+state_sz };
     503           0 :   if( FD_UNLIKELY( fd_bpf_upgradeable_loader_state_encode( &state, &ctx )!=FD_BINCODE_SUCCESS ) ) {
     504           0 :     FD_LOG_ERR(( "fd_bpf_upgradeable_loader_state_encode failed" ));
     505           0 :   }
     506             : 
     507           0 :   return acc;
     508           0 : }
     509             : 
     510             : /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L108-L153 */
     511             : static fd_tmp_account_t *
     512             : new_target_program_data_account( fd_tmp_account_t *       acc,
     513             :                                  fd_tmp_account_t const * source,
     514             :                                  fd_pubkey_t const *      upgrade_authority_address,
     515             :                                  fd_rent_t const *        rent,
     516           0 :                                  ulong                    slot ) {
     517           0 :   ulong const buffer_metadata_sz = BUFFER_METADATA_SIZE;
     518             : 
     519           0 :   if( FD_UNLIKELY( source->data_sz < buffer_metadata_sz ) )
     520           0 :     return NULL; /* CoreBpfMigrationError::InvalidBufferAccount */
     521             : 
     522           0 :   fd_bpf_upgradeable_loader_state_t state;
     523           0 :   if( !fd_bincode_decode_static(
     524           0 :       bpf_upgradeable_loader_state,
     525           0 :       &state,
     526           0 :       source->data,
     527           0 :       buffer_metadata_sz ) )
     528           0 :     return NULL;
     529             : 
     530           0 :   if( FD_UNLIKELY( state.discriminant!=fd_bpf_upgradeable_loader_state_enum_buffer ) )
     531           0 :     return NULL; /* CoreBpfMigrationError::InvalidBufferAccount */
     532             : 
     533             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L118-L125 */
     534           0 :   if( upgrade_authority_address ) {
     535           0 :     if( FD_UNLIKELY( !state.inner.buffer.has_authority_address ||
     536           0 :                      !fd_pubkey_eq( upgrade_authority_address, &state.inner.buffer.authority_address ) ) ) {
     537           0 :       return NULL; /* CoreBpfMigrationError::UpgradeAuthorityMismatch */
     538           0 :     }
     539           0 :   }
     540             : 
     541           0 :   void const * elf      = (uchar const *)source->data    + buffer_metadata_sz;
     542           0 :   ulong        elf_sz   = /*           */source->data_sz - buffer_metadata_sz;
     543             : 
     544           0 :   ulong        space    = PROGRAMDATA_METADATA_SIZE + elf_sz;
     545           0 :   ulong        lamports = fd_rent_exempt_minimum_balance( rent, space );
     546           0 :   fd_pubkey_t  owner    = fd_solana_bpf_loader_upgradeable_program_id;
     547             : 
     548           0 :   fd_bpf_upgradeable_loader_state_t programdata_meta = {
     549           0 :     .discriminant = fd_bpf_upgradeable_loader_state_enum_program_data,
     550           0 :     .inner = {
     551           0 :       .program_data = {
     552           0 :         .slot = slot,
     553           0 :         .has_upgrade_authority_address = !!upgrade_authority_address,
     554           0 :         .upgrade_authority_address     = upgrade_authority_address ? *upgrade_authority_address : (fd_pubkey_t){{0}}
     555           0 :       }
     556           0 :     }
     557           0 :   };
     558             : 
     559           0 :   tmp_account_new( acc, space );
     560           0 :   acc->meta.lamports = lamports;
     561           0 :   memcpy( acc->meta.owner, owner.uc, sizeof(fd_pubkey_t) );
     562           0 :   fd_bincode_encode_ctx_t ctx = { .data=acc->data, .dataend=(uchar *)acc->data+PROGRAMDATA_METADATA_SIZE };
     563           0 :   if( FD_UNLIKELY( fd_bpf_upgradeable_loader_state_encode( &programdata_meta, &ctx )!=FD_BINCODE_SUCCESS ) ) {
     564           0 :     FD_LOG_ERR(( "fd_bpf_upgradeable_loader_state_encode failed" ));
     565           0 :   }
     566           0 :   fd_memcpy( (uchar *)acc->data+PROGRAMDATA_METADATA_SIZE, elf, elf_sz );
     567             : 
     568           0 :   return acc;
     569           0 : }
     570             : 
     571             : void
     572             : migrate_builtin_to_core_bpf1( fd_core_bpf_migration_config_t const * config,
     573             :                               fd_accdb_user_t *                      accdb,
     574             :                               fd_funk_txn_xid_t const *              xid,
     575             :                               fd_bank_t *                            bank,
     576             :                               fd_runtime_stack_t *                   runtime_stack,
     577             :                               fd_pubkey_t const *                    builtin_program_id,
     578           0 :                               fd_capture_ctx_t *                     capture_ctx ) {
     579           0 :   target_builtin_t target[1];
     580           0 :   if( FD_UNLIKELY( !target_builtin_new_checked(
     581           0 :       target,
     582           0 :       builtin_program_id,
     583           0 :       config->migration_target,
     584           0 :       FD_FEATURE_ACTIVE_BANK( bank, relax_programdata_account_check_migration ),
     585           0 :       accdb,
     586           0 :       xid,
     587           0 :       runtime_stack ) ) )
     588           0 :     return;
     589             : 
     590           0 :   fd_tmp_account_t * source = &runtime_stack->bpf_migration.source;
     591           0 :   if( FD_UNLIKELY( !source_buffer_new_checked(
     592           0 :       source,
     593           0 :       accdb,
     594           0 :       xid,
     595           0 :       config->source_buffer_address,
     596           0 :       config->verified_build_hash ) ) )
     597           0 :     return;
     598             : 
     599           0 :   fd_rent_t const * rent = &bank->f.rent;
     600           0 :   ulong const       slot = bank->f.slot;
     601             : 
     602           0 :   fd_tmp_account_t * new_target_program = &runtime_stack->bpf_migration.new_target_program;
     603           0 :   if( FD_UNLIKELY( !new_target_program_account(
     604           0 :       new_target_program,
     605           0 :       target,
     606           0 :       rent ) ) )
     607           0 :     return;
     608           0 :   new_target_program->addr = *builtin_program_id;
     609             : 
     610           0 :   fd_tmp_account_t * new_target_program_data = &runtime_stack->bpf_migration.new_target_program_data;
     611           0 :   if( FD_UNLIKELY( !new_target_program_data_account(
     612           0 :       new_target_program_data,
     613           0 :       source,
     614           0 :       config->upgrade_authority_address,
     615           0 :       rent,
     616           0 :       slot ) ) )
     617           0 :     return;
     618           0 :   new_target_program_data->addr = target->program_data_address;
     619             : 
     620           0 :   ulong old_data_sz;
     621           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_account->data_sz, source->data_sz, &old_data_sz ) ) ) return;
     622             : 
     623           0 :   ulong new_data_sz;
     624           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( new_target_program->data_sz, new_target_program_data->data_sz, &new_data_sz ) ) ) return;
     625             : 
     626           0 :   assert( new_target_program_data->data_sz>=PROGRAMDATA_METADATA_SIZE );
     627             :   /* FIXME call fd_directly_invoke_loader_v3_deploy */
     628             : 
     629             :   /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L267-L281 */
     630           0 :   ulong lamports_to_burn;
     631           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_account->meta.lamports, source->meta.lamports, &lamports_to_burn ) ) ) return;
     632           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( lamports_to_burn, target->program_data_account_lamports, &lamports_to_burn ) ) )       return;
     633             : 
     634           0 :   ulong lamports_to_fund;
     635           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( new_target_program->meta.lamports, new_target_program_data->meta.lamports, &lamports_to_fund ) ) ) return;
     636             : 
     637             :   /* Write back accounts */
     638           0 :   tmp_account_store( new_target_program,      accdb, xid, bank, capture_ctx );
     639           0 :   tmp_account_store( new_target_program_data, accdb, xid, bank, capture_ctx );
     640           0 :   fd_tmp_account_t * empty = &runtime_stack->bpf_migration.empty;
     641           0 :   tmp_account_new( empty, 0UL );
     642           0 :   empty->addr = source->addr;
     643           0 :   tmp_account_store( empty, accdb, xid, bank, capture_ctx );
     644             : 
     645             :   /* FIXME "remove the built-in program from the bank's list of builtins" */
     646             :   /* FIXME "update account data size delta" */
     647           0 : }
     648             : 
     649             : /* Mimics migrate_builtin_to_core_bpf().
     650             :    https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#215-303 */
     651             : void
     652             : fd_migrate_builtin_to_core_bpf( fd_bank_t *                            bank,
     653             :                                 fd_accdb_user_t *                      accdb,
     654             :                                 fd_funk_txn_xid_t const *              xid,
     655             :                                 fd_runtime_stack_t *                   runtime_stack,
     656             :                                 fd_core_bpf_migration_config_t const * config,
     657           0 :                                 fd_capture_ctx_t *                     capture_ctx ) {
     658           0 :   migrate_builtin_to_core_bpf1( config, accdb, xid, bank, runtime_stack, config->builtin_program_id, capture_ctx );
     659           0 : }
     660             : 
     661             : /* Mimics upgrade_core_bpf_program().
     662             :    https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L319-L377 */
     663             : void
     664             : fd_upgrade_core_bpf_program( fd_bank_t *                            bank,
     665             :                              fd_accdb_user_t *                      accdb,
     666             :                              fd_funk_txn_xid_t const *              xid,
     667             :                              fd_runtime_stack_t *                   runtime_stack,
     668             :                              fd_pubkey_t const *                    builtin_program_id,
     669             :                              fd_pubkey_t const *                    source_buffer_address,
     670           0 :                              fd_capture_ctx_t *                     capture_ctx ) {
     671             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L327 */
     672           0 :   target_core_bpf_t target[1];
     673           0 :   if( FD_UNLIKELY( !target_core_bpf_new_checked( target, builtin_program_id, accdb, xid, runtime_stack ) ) ) {
     674           0 :     return;
     675           0 :   }
     676             : 
     677             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L328 */
     678           0 :   fd_tmp_account_t * source = &runtime_stack->bpf_migration.source;
     679           0 :   if( FD_UNLIKELY( !source_buffer_new_checked( source, accdb, xid, source_buffer_address, NULL ) ) ) {
     680           0 :     return;
     681           0 :   }
     682             : 
     683             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L331-L332  */
     684           0 :   fd_tmp_account_t * new_target_program_data = &runtime_stack->bpf_migration.new_target_program_data;
     685           0 :   fd_pubkey_t program_data_address = get_program_data_address( builtin_program_id );
     686             : 
     687           0 :   ulong program_data_len = source->data_sz - BUFFER_METADATA_SIZE;
     688           0 :   ulong new_account_size = PROGRAMDATA_METADATA_SIZE + program_data_len;
     689             : 
     690           0 :   tmp_account_new( new_target_program_data, new_account_size );
     691           0 :   new_target_program_data->addr = program_data_address;
     692             : 
     693           0 :   fd_rent_t const * rent = &bank->f.rent;
     694           0 :   new_target_program_data->meta.lamports   = fd_rent_exempt_minimum_balance( rent, new_account_size );
     695           0 :   new_target_program_data->meta.executable = 0;
     696           0 :   fd_memcpy( new_target_program_data->meta.owner, &fd_solana_bpf_loader_upgradeable_program_id, sizeof(fd_pubkey_t) );
     697             : 
     698           0 :   fd_bpf_upgradeable_loader_state_t programdata_state[1] = {{
     699           0 :     .discriminant = fd_bpf_upgradeable_loader_state_enum_program_data,
     700           0 :     .inner = { .program_data = {
     701           0 :       .slot = bank->f.slot,
     702           0 :       .upgrade_authority_address = target->upgrade_authority_address,
     703           0 :       .has_upgrade_authority_address = target->has_upgrade_authority_address
     704           0 :     }}
     705           0 :   }};
     706             : 
     707           0 :   fd_bincode_encode_ctx_t encode_ctx = {
     708           0 :     .data    = new_target_program_data->data,
     709           0 :     .dataend = new_target_program_data->data + PROGRAMDATA_METADATA_SIZE
     710           0 :   };
     711           0 :   if( FD_UNLIKELY( FD_BINCODE_SUCCESS!=fd_bpf_upgradeable_loader_state_encode( programdata_state, &encode_ctx ) ) ) {
     712           0 :     return;
     713           0 :   }
     714             : 
     715           0 :   fd_memcpy( new_target_program_data->data + PROGRAMDATA_METADATA_SIZE,
     716           0 :              source->data + BUFFER_METADATA_SIZE,
     717           0 :              program_data_len );
     718             : 
     719             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.4/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L339-L346 */
     720           0 :   ulong old_data_sz;
     721           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_data_account->data_sz, source->data_sz, &old_data_sz ) ) ) return;
     722           0 :   ulong new_data_sz = new_target_program_data->data_sz;
     723             : 
     724             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.4/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L349-L355 */
     725           0 :   uchar const * elf    = new_target_program_data->data + PROGRAMDATA_METADATA_SIZE;
     726           0 :   ulong         elf_sz = program_data_len;
     727           0 :   if( FD_UNLIKELY( fd_directly_invoke_loader_v3_deploy_checks( bank, runtime_stack, elf, elf_sz ) ) ) return;
     728             : 
     729             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L359-L364 */
     730           0 :   ulong lamports_to_burn;
     731           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_data_account->meta.lamports, source->meta.lamports, &lamports_to_burn ) ) ) return;
     732             : 
     733             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L366-L371 */
     734           0 :   fd_pubkey_t source_addr = source->addr;
     735           0 :   tmp_account_store( new_target_program_data, accdb, xid, bank, capture_ctx );
     736             : 
     737           0 :   fd_tmp_account_t * empty = &runtime_stack->bpf_migration.empty;
     738           0 :   tmp_account_new( empty, 0UL );
     739           0 :   empty->addr = source_addr;
     740           0 :   tmp_account_store( empty, accdb, xid, bank, capture_ctx );
     741             : 
     742             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L374 */
     743             :   /* FIXME "update account data size delta" */
     744           0 :   (void)old_data_sz;
     745           0 :   (void)new_data_sz;
     746             : 
     747           0 :   fd_memset( &runtime_stack->bpf_migration, 0, sizeof(runtime_stack->bpf_migration) );
     748           0 : }
     749             : 
     750             : /* Mimics upgrade_loader_v2_program_with_loader_v3_program().
     751             :    https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L402-L474 */
     752             : void
     753             : fd_upgrade_loader_v2_program_with_loader_v3_program( fd_bank_t *               bank,
     754             :                                                      fd_accdb_user_t *         accdb,
     755             :                                                      fd_funk_txn_xid_t const * xid,
     756             :                                                      fd_runtime_stack_t *      runtime_stack,
     757             :                                                      fd_pubkey_t const *       loader_v2_program_address,
     758             :                                                      fd_pubkey_t const *       source_buffer_address,
     759             :                                                      int                       allow_prefunded,
     760           0 :                                                      fd_capture_ctx_t *        capture_ctx ) {
     761             : 
     762             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L411-L412 */
     763           0 :   target_builtin_t target[1];
     764           0 :   if( FD_UNLIKELY( !target_bpf_v2_new_checked(
     765           0 :       target,
     766           0 :       loader_v2_program_address,
     767           0 :       allow_prefunded,
     768           0 :       accdb,
     769           0 :       xid,
     770           0 :       runtime_stack ) ) )
     771           0 :     return;
     772             : 
     773             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L413 */
     774           0 :   fd_tmp_account_t * source = &runtime_stack->bpf_migration.source;
     775           0 :   if( FD_UNLIKELY( !source_buffer_new_checked( source, accdb, xid, source_buffer_address, NULL ) ) )
     776           0 :     return;
     777             : 
     778           0 :   fd_rent_t const * rent = &bank->f.rent;
     779           0 :   ulong             slot = bank->f.slot;
     780             : 
     781             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L416-L417 */
     782           0 :   fd_tmp_account_t * new_target_program = &runtime_stack->bpf_migration.new_target_program;
     783           0 :   if( FD_UNLIKELY( !new_target_program_account( new_target_program, target, rent ) ) )
     784           0 :     return;
     785           0 :   new_target_program->addr = *loader_v2_program_address;
     786             : 
     787             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L419-L421 */
     788           0 :   fd_tmp_account_t * new_target_program_data = &runtime_stack->bpf_migration.new_target_program_data;
     789           0 :   if( FD_UNLIKELY( !new_target_program_data_account( new_target_program_data, source, NULL, rent, slot ) ) ) {
     790           0 :     return;
     791           0 :   }
     792           0 :   new_target_program_data->addr = target->program_data_address;
     793             : 
     794             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L427-L435 */
     795           0 :   ulong old_data_sz;
     796           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_account->data_sz, source->data_sz, &old_data_sz ) ) ) return;
     797             : 
     798             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L432-L435 */
     799           0 :   ulong new_data_sz;
     800           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( new_target_program->data_sz, new_target_program_data->data_sz, &new_data_sz ) ) ) return;
     801             : 
     802           0 :   if( FD_UNLIKELY( new_target_program_data->data_sz<PROGRAMDATA_METADATA_SIZE ) ) {
     803           0 :     FD_LOG_CRIT(( "invariant violation: new target programdata too small" ));
     804           0 :   }
     805             : 
     806             :   /* Agave calls directly_invoke_loader_v3_deploy to deploy the new
     807             :      program to the program cache. We don't do that, but instead we
     808             :      perform the same checks as directly_invoke_loader_v3_deploy
     809             :      without modifying the program cache. We need to do the checks
     810             :      at this point so that we can fail the upgrade if the ELF is
     811             :      invalid.
     812             : 
     813             :      This is safe because the bpf migration code runs at the epoch
     814             :      boundary, before any transaction execution. The program cache
     815             :      automatically invalidates all programs at the start of an epoch
     816             :      boundary, so we do not need to explicitly update the cache during the
     817             :      migration.
     818             : 
     819             :      https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L437-L443*/
     820           0 :   uchar const * elf    = (uchar const *)new_target_program_data->data + PROGRAMDATA_METADATA_SIZE;
     821           0 :   ulong         elf_sz = new_target_program_data->data_sz - PROGRAMDATA_METADATA_SIZE;
     822           0 :   if( FD_UNLIKELY( fd_directly_invoke_loader_v3_deploy_checks( bank, runtime_stack, elf, elf_sz ) ) ) return;
     823             : 
     824             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L451-L459 */
     825           0 :   ulong lamports_to_burn;
     826           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_account->meta.lamports, source->meta.lamports, &lamports_to_burn ) ) ) return;
     827           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( lamports_to_burn, target->program_data_account_lamports, &lamports_to_burn ) ) )       return;
     828             : 
     829           0 :   ulong lamports_to_fund;
     830           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( new_target_program->meta.lamports, new_target_program_data->meta.lamports, &lamports_to_fund ) ) ) return;
     831             : 
     832             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L462-L468 */
     833           0 :   tmp_account_store( new_target_program,      accdb, xid, bank, capture_ctx );
     834           0 :   tmp_account_store( new_target_program_data, accdb, xid, bank, capture_ctx );
     835             : 
     836           0 :   fd_tmp_account_t * empty = &runtime_stack->bpf_migration.empty;
     837           0 :   tmp_account_new( empty, 0UL );
     838           0 :   empty->addr = source->addr;
     839           0 :   tmp_account_store( empty, accdb, xid, bank, capture_ctx );
     840             : 
     841             :   /* NB: Agave updates "delta_off_chain", using these two fields,
     842             :      which is not consensus-critical (only used for Agave stats)
     843             :      so we don't update this in our migration code or store this in
     844             :      our bank. */
     845           0 :   (void)old_data_sz;
     846           0 :   (void)new_data_sz;
     847             : 
     848           0 :   fd_memset( &runtime_stack->bpf_migration, 0, sizeof(runtime_stack->bpf_migration) );
     849           0 : }

Generated by: LCOV version 1.14