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

Generated by: LCOV version 1.14