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 500 0.0 %
Date: 2026-07-11 05:27:41 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 "../../ballet/sha256/fd_sha256.h"
      10             : #include "../../ballet/sbpf/fd_sbpf_loader.h"
      11             : #include "../progcache/fd_prog_load.h"
      12             : #include "../vm/fd_vm.h"
      13             : 
      14             : static fd_pubkey_t
      15           0 : get_program_data_address( fd_pubkey_t const * program_addr ) {
      16           0 :   uchar const * seed    = program_addr->uc;
      17           0 :   ulong         seed_sz = 32UL;
      18           0 :   fd_pubkey_t   out;
      19           0 :   uint          custom_err;
      20           0 :   uchar         out_bump_seed;
      21           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 );
      22           0 :   if( FD_UNLIKELY( err ) ) {
      23             :     /* https://github.com/anza-xyz/solana-sdk/blob/address%40v2.1.0/address/src/syscalls.rs#L277-L279 */
      24           0 :     FD_LOG_ERR(( "Unable to find a viable program address bump seed" ));
      25           0 :   }
      26           0 :   return out;
      27           0 : }
      28             : 
      29             : fd_tmp_account_t *
      30             : tmp_account_new( fd_tmp_account_t * acc,
      31           0 :                  ulong              acc_sz ) {
      32           0 :   acc->data_sz = acc_sz;
      33           0 :   fd_memset( acc->data,  0, acc_sz );
      34           0 :   acc->lamports = 0UL;
      35           0 :   acc->executable = 0;
      36           0 :   fd_memset( acc->owner.uc, 0, 32UL );
      37           0 :   fd_memset( acc->pubkey.uc, 0, 32UL );
      38           0 :   return acc;
      39           0 : }
      40             : 
      41             : fd_tmp_account_t *
      42             : tmp_account_read( fd_tmp_account_t *        acc,
      43             :                   fd_accdb_t *              accdb,
      44             :                   fd_accdb_fork_id_t        fork_id,
      45           0 :                   fd_pubkey_t const *       addr ) {
      46           0 :   fd_acc_t db_acc = fd_accdb_read_one( accdb, fork_id, addr->uc );
      47           0 :   if( FD_UNLIKELY( !db_acc.lamports ) ) {
      48           0 :     fd_accdb_unread_one( accdb, &db_acc );
      49           0 :     return NULL;
      50           0 :   }
      51             : 
      52           0 :   acc->lamports = db_acc.lamports;
      53           0 :   fd_memcpy( acc->owner.uc, db_acc.owner, 32UL );
      54           0 :   acc->executable = db_acc.executable;
      55           0 :   fd_memcpy( acc->data, db_acc.data, db_acc.data_len );
      56           0 :   acc->data_sz = db_acc.data_len;
      57           0 :   acc->pubkey = *addr;
      58             : 
      59           0 :   fd_accdb_unread_one( accdb, &db_acc );
      60           0 :   return acc;
      61           0 : }
      62             : 
      63             : void
      64             : tmp_account_store( fd_bank_t *        bank,
      65             :                    fd_accdb_t *       accdb,
      66             :                    fd_tmp_account_t * acc,
      67           0 :                    fd_capture_ctx_t * capture_ctx ) {
      68           0 :   if( FD_UNLIKELY( fd_pubkey_eq( &acc->pubkey, &fd_solana_system_program_id ) ) ) FD_LOG_ERR(( "attempted to write to the system program account" ));
      69             : 
      70           0 :   fd_accdb_svm_update_t update[1];
      71           0 :   fd_acc_t db_acc = fd_accdb_svm_open_rw( bank, accdb, update, &acc->pubkey, 1 );
      72             : 
      73           0 :   db_acc.executable = acc->executable;
      74           0 :   fd_memcpy( db_acc.owner, acc->owner.uc, 32UL );
      75           0 :   db_acc.lamports = acc->lamports;
      76           0 :   fd_memcpy( db_acc.data, acc->data, acc->data_sz );
      77           0 :   db_acc.data_len = acc->data_sz;
      78             : 
      79           0 :   fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &db_acc, update );
      80           0 : }
      81             : 
      82             : /* https://github.com/anza-xyz/agave/blob/v3.0.2/runtime/src/bank/builtins/core_bpf_migration/target_core_bpf.rs#L12 */
      83             : 
      84             : struct target_core_bpf {
      85             :   fd_pubkey_t        program_address;
      86             :   fd_tmp_account_t * program_data_account;
      87             :   fd_pubkey_t        upgrade_authority_address;
      88             :   uint               has_upgrade_authority_address : 1;
      89             : };
      90             : 
      91             : typedef struct target_core_bpf target_core_bpf_t;
      92             : 
      93             : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L19 */
      94             : 
      95             : struct target_builtin {
      96             :   fd_tmp_account_t * program_account;
      97             :   fd_pubkey_t        program_data_address;
      98             :   ulong              program_data_account_lamports;
      99             : };
     100             : 
     101             : typedef struct target_builtin target_builtin_t;
     102             : 
     103             : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L25-L91 */
     104             : 
     105             : target_builtin_t *
     106             : target_builtin_new_checked( target_builtin_t *        target_builtin,
     107             :                             fd_pubkey_t const *       program_address,
     108             :                             int                       migration_target,
     109             :                             int                       relax_programdata_account_check_migration,
     110             :                             fd_accdb_t *              accdb,
     111             :                             fd_accdb_fork_id_t        fork_id,
     112           0 :                             fd_runtime_stack_t *      runtime_stack ) {
     113             : 
     114             :   /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/bank/builtins/core_bpf_migration/target_builtin.rs#L31-L53 */
     115             : 
     116           0 :   fd_tmp_account_t * program_account = &runtime_stack->bpf_migration.program_account;
     117           0 :   switch( migration_target ) {
     118           0 :   case FD_CORE_BPF_MIGRATION_TARGET_BUILTIN:
     119           0 :     if( FD_UNLIKELY( !tmp_account_read( program_account, accdb, fork_id, program_address ) ) ) {
     120             :       /* CoreBpfMigrationError::AccountNotFound(*program_address) */
     121           0 :       return NULL;
     122           0 :     }
     123           0 :     if( FD_UNLIKELY( 0!=memcmp( program_account->owner.uc, &fd_solana_native_loader_id, 32 ) ) ) {
     124             :       /* CoreBpfMigrationError::IncorrectOwner(*program_address) */
     125           0 :       return NULL;
     126           0 :     }
     127           0 :     break;
     128           0 :   case FD_CORE_BPF_MIGRATION_TARGET_STATELESS: {
     129             :     /* CoreBpfMigrationError::AccountAlreadyExists(*program_address) */
     130           0 :     if( FD_UNLIKELY( fd_accdb_exists( accdb, fork_id, program_address->uc ) ) ) return NULL;
     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_acc_t progdata = fd_accdb_read_one( accdb, fork_id, program_data_address.uc );
     147           0 :     int progdata_exists = !!progdata.lamports;
     148           0 :     if( FD_UNLIKELY( !progdata_exists ) ) fd_accdb_unread_one( accdb, &progdata );
     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_pubkey_t*)progdata.owner, &fd_solana_system_program_id ) ) ) {
     157             :           /* CoreBpfMigrationError::ProgramHasDataAccount(*program_address) */
     158           0 :           fd_accdb_unread_one( accdb, &progdata );
     159           0 :           return NULL;
     160           0 :         } else {
     161           0 :           program_data_account_lamports = progdata.lamports;
     162           0 :           fd_accdb_unread_one( accdb, &progdata );
     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_unread_one( accdb, &progdata );
     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_t *         accdb,
     191             :                              fd_accdb_fork_id_t   fork_id,
     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, fork_id, 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->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->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_state2( program_account->data, program_account->data_sz, 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, fork_id, &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->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_state2( program_data_account->data, program_data_account->data_sz, 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_t *              accdb,
     269             :                            fd_accdb_fork_id_t        fork_id,
     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, fork_id, 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->owner, &fd_solana_bpf_loader_program_id, sizeof(fd_pubkey_t) ) ) ) {
     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->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_acc_t acc = fd_accdb_read_one( accdb, fork_id, program_data_address.uc );
     298           0 :     int progdata_exists = !!acc.lamports;
     299           0 :     if( FD_UNLIKELY( !progdata_exists ) ) fd_accdb_unread_one( accdb, &acc );
     300             : 
     301             :     /* 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 */
     302           0 :     if( FD_LIKELY( allow_prefunded ) ) {
     303             :       /* The program data account should not exist, but a system
     304             :          account with funded lamports is acceptable.
     305             : 
     306             :          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 */
     307           0 :       if( FD_UNLIKELY( progdata_exists ) ) {
     308           0 :         if( FD_UNLIKELY( !fd_pubkey_eq( (fd_pubkey_t*)acc.owner, &fd_solana_system_program_id ) ) ) {
     309             :           /* CoreBpfMigrationError::ProgramHasDataAccount(*program_address) */
     310           0 :           fd_accdb_unread_one( accdb, &acc );
     311           0 :           return NULL;
     312           0 :         } else {
     313           0 :           program_data_account_lamports = acc.lamports;
     314           0 :           fd_accdb_unread_one( accdb, &acc );
     315           0 :         }
     316           0 :       }
     317           0 :     } else {
     318             :       /* 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 */
     319           0 :       if( FD_UNLIKELY( progdata_exists ) ) {
     320             :         /* CoreBpfMigrationError::ProgramHasDataAccount(*program_address) */
     321           0 :         fd_accdb_unread_one( accdb, &acc );
     322           0 :         return NULL;
     323           0 :       }
     324           0 :     }
     325           0 :   } while(0);
     326             : 
     327           0 :   *target_bpf_v2 = (target_builtin_t) {
     328           0 :     .program_account               = program_account,
     329           0 :     .program_data_address          = program_data_address,
     330           0 :     .program_data_account_lamports = program_data_account_lamports
     331           0 :   };
     332           0 :   return target_bpf_v2;
     333           0 : }
     334             : 
     335             : /* This function contains the deployment checks that are equivalent to
     336             :    Agave's directly_invoke_loader_v3_deploy.
     337             : 
     338             :    There is no direct equivalent in Agave to this function, because
     339             :    we are not updating the program cache here. However, we do the same
     340             :    checks that our program cache does upon deployment.
     341             : 
     342             :    This is safe because the bpf migration code runs at the epoch
     343             :    boundary, before any transaction execution. The program cache
     344             :    automatically invalidates all programs at the start of an epoch
     345             :    boundary, so we do not need to explicitly update the cache during the
     346             :    migration.
     347             : 
     348             :    https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L120-L218 */
     349             : static int
     350             : fd_directly_invoke_loader_v3_deploy_checks( fd_bank_t const *    bank,
     351             :                                             fd_runtime_stack_t * runtime_stack,
     352             :                                             uchar const *        elf,
     353           0 :                                             ulong                elf_sz ) {
     354           0 :   fd_features_t const * features = &bank->f.features;
     355           0 :   ulong                 slot     = bank->f.slot;
     356             : 
     357             :   /* ELF verification with deploy checks enabled */
     358           0 :   fd_prog_versions_t versions = fd_prog_versions( features, slot );
     359           0 :   fd_sbpf_loader_config_t loader_config = {
     360           0 :     .elf_deploy_checks = 1,
     361           0 :     .sbpf_min_version  = versions.min_sbpf_version,
     362           0 :     .sbpf_max_version  = versions.max_sbpf_version,
     363           0 :   };
     364           0 :   fd_sbpf_elf_info_t elf_info[1];
     365           0 :   if( FD_UNLIKELY( fd_sbpf_elf_peek( elf_info, elf, elf_sz, &loader_config )!=FD_SBPF_ELF_SUCCESS ) ) return 1;
     366             : 
     367             :   /* Setup program (includes calldests) */
     368           0 :   fd_sbpf_program_t * prog = fd_sbpf_program_new(
     369           0 :     runtime_stack->bpf_migration.progcache_validate.sbpf_footprint,
     370           0 :     elf_info,
     371           0 :     runtime_stack->bpf_migration.progcache_validate.rodata );
     372           0 :   if( FD_UNLIKELY( !prog ) ) return 1;
     373             : 
     374           0 :   fd_sbpf_syscalls_t _syscalls[ FD_SBPF_SYSCALLS_SLOT_CNT ];
     375           0 :   fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_join( fd_sbpf_syscalls_new( _syscalls ) );
     376           0 :   if( FD_UNLIKELY( !syscalls ) ) return 1;
     377           0 :   if( FD_UNLIKELY( fd_vm_syscall_register_slot( syscalls, slot, features, /* is_deploy */ 1 )!=FD_VM_SUCCESS ) ) return 1;
     378             : 
     379             :   /* fd_sbpf_program_load checks */
     380           0 :   if( FD_UNLIKELY( fd_sbpf_program_load(
     381           0 :     prog,
     382           0 :     elf,
     383           0 :     elf_sz,
     384           0 :     syscalls,
     385           0 :     &loader_config,
     386           0 :     runtime_stack->bpf_migration.progcache_validate.programdata,
     387           0 :     sizeof(runtime_stack->bpf_migration.progcache_validate.programdata) ) ) ) return 1;
     388             : 
     389             :   /* fd_vm_validate checks */
     390           0 :   fd_vm_t _vm[1];
     391           0 :   fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
     392           0 :   if( FD_UNLIKELY( !vm ) ) return 1;
     393           0 :   vm = fd_vm_init( vm,
     394           0 :                    NULL,
     395           0 :                    0UL,
     396           0 :                    0UL,
     397           0 :                    prog->rodata,
     398           0 :                    prog->rodata_sz,
     399           0 :                    prog->text,
     400           0 :                    prog->info.text_cnt,
     401           0 :                    prog->info.text_off,
     402           0 :                    prog->info.text_sz,
     403           0 :                    prog->entry_pc,
     404           0 :                    prog->calldests,
     405           0 :                    elf_info->sbpf_version,
     406           0 :                    syscalls,
     407           0 :                    NULL,
     408           0 :                    NULL,
     409           0 :                    NULL,
     410           0 :                    0U,
     411           0 :                    NULL,
     412           0 :                    0,
     413           0 :                    FD_FEATURE_ACTIVE( slot, features, account_data_direct_mapping ),
     414           0 :                    FD_FEATURE_ACTIVE( slot, features, syscall_parameter_address_restrictions ),
     415           0 :                    FD_FEATURE_ACTIVE( slot, features, virtual_address_space_adjustments ),
     416           0 :                    0,
     417           0 :                    0UL );
     418           0 :   if( FD_UNLIKELY( !vm ) ) return 1;
     419           0 :   if( FD_UNLIKELY( fd_vm_validate( vm )!=FD_VM_SUCCESS ) ) return 1;
     420             : 
     421           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     422           0 : }
     423             : 
     424             : /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L51-L75 */
     425             : 
     426             : static fd_tmp_account_t *
     427             : source_buffer_new_checked( fd_tmp_account_t *  acc,
     428             :                            fd_accdb_t *        accdb,
     429             :                            fd_accdb_fork_id_t  fork_id,
     430             :                            fd_pubkey_t const * pubkey,
     431           0 :                            fd_hash_t const *   verified_build_hash ) {
     432             : 
     433           0 :   if( FD_UNLIKELY( !tmp_account_read( acc, accdb, fork_id, pubkey ) ) ) {
     434             :     /* CoreBpfMigrationError::AccountNotFound(*buffer_address) */
     435           0 :     return NULL;
     436           0 :   }
     437             : 
     438           0 :   if( FD_UNLIKELY( 0!=memcmp( acc->owner.uc, &fd_solana_bpf_loader_upgradeable_program_id, 32 ) ) ) {
     439             :     /* CoreBpfMigrationError::IncorrectOwner(*buffer_address) */
     440           0 :     return NULL;
     441           0 :   }
     442             : 
     443           0 :   if( acc->data_sz < BUFFER_METADATA_SIZE ) {
     444             :     /* CoreBpfMigrationError::InvalidBufferAccount(*buffer_address) */
     445           0 :     return NULL;
     446           0 :   }
     447             : 
     448           0 :   fd_bpf_state_t state[1];
     449           0 :   if( FD_UNLIKELY( fd_bpf_state_decode( state, acc->data, BUFFER_METADATA_SIZE ) ) ) {
     450           0 :     return NULL;
     451           0 :   }
     452             : 
     453           0 :   if( FD_UNLIKELY( state->discriminant!=FD_BPF_STATE_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_state_t state = {
     488           0 :     .discriminant = FD_BPF_STATE_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_state_size( &state );
     497           0 :   tmp_account_new( acc, state_sz );
     498           0 :   acc->lamports   = fd_rent_exempt_minimum_balance( rent, SIZE_OF_PROGRAM );
     499           0 :   acc->executable = 1;
     500           0 :   memcpy( acc->owner.uc, fd_solana_bpf_loader_upgradeable_program_id.uc, sizeof(fd_pubkey_t) );
     501             : 
     502           0 :   ulong out_sz = 0UL;
     503           0 :   if( FD_UNLIKELY( fd_bpf_state_encode( &state, acc->data, state_sz, &out_sz ) ) ) {
     504           0 :     FD_LOG_ERR(( "fd_bpf_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_state_t state;
     523           0 :   if( FD_UNLIKELY( fd_bpf_state_decode( &state, source->data, buffer_metadata_sz ) ) ) {
     524           0 :     return NULL;
     525           0 :   }
     526             : 
     527           0 :   if( FD_UNLIKELY( state.discriminant!=FD_BPF_STATE_BUFFER ) )
     528           0 :     return NULL; /* CoreBpfMigrationError::InvalidBufferAccount */
     529             : 
     530             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L118-L125 */
     531           0 :   if( upgrade_authority_address ) {
     532           0 :     if( FD_UNLIKELY( !state.inner.buffer.has_authority_address ||
     533           0 :                      !fd_pubkey_eq( upgrade_authority_address, &state.inner.buffer.authority_address ) ) ) {
     534           0 :       return NULL; /* CoreBpfMigrationError::UpgradeAuthorityMismatch */
     535           0 :     }
     536           0 :   }
     537             : 
     538           0 :   void const * elf      = (uchar const *)source->data    + buffer_metadata_sz;
     539           0 :   ulong        elf_sz   = /*           */source->data_sz - buffer_metadata_sz;
     540             : 
     541           0 :   ulong        space    = PROGRAMDATA_METADATA_SIZE + elf_sz;
     542           0 :   ulong        lamports = fd_rent_exempt_minimum_balance( rent, space );
     543           0 :   fd_pubkey_t  owner    = fd_solana_bpf_loader_upgradeable_program_id;
     544             : 
     545           0 :   fd_bpf_state_t programdata_meta = {
     546           0 :     .discriminant = FD_BPF_STATE_PROGRAM_DATA,
     547           0 :     .inner = {
     548           0 :       .program_data = {
     549           0 :         .slot = slot,
     550           0 :         .has_upgrade_authority_address = !!upgrade_authority_address,
     551           0 :         .upgrade_authority_address     = upgrade_authority_address ? *upgrade_authority_address : (fd_pubkey_t){{0}}
     552           0 :       }
     553           0 :     }
     554           0 :   };
     555             : 
     556           0 :   tmp_account_new( acc, space );
     557           0 :   acc->lamports = lamports;
     558           0 :   memcpy( acc->owner.uc, owner.uc, sizeof(fd_pubkey_t) );
     559           0 :   ulong out_sz = 0UL;
     560           0 :   if( FD_UNLIKELY( fd_bpf_state_encode( &programdata_meta, acc->data, PROGRAMDATA_METADATA_SIZE, &out_sz ) ) ) {
     561           0 :     FD_LOG_ERR(( "fd_bpf_state_encode failed" ));
     562           0 :   }
     563           0 :   fd_memcpy( (uchar *)acc->data+PROGRAMDATA_METADATA_SIZE, elf, elf_sz );
     564             : 
     565           0 :   return acc;
     566           0 : }
     567             : 
     568             : void
     569             : migrate_builtin_to_core_bpf1( fd_core_bpf_migration_config_t const * config,
     570             :                               fd_accdb_t *                           accdb,
     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 :       bank->accdb_fork_id,
     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 :       bank->accdb_fork_id,
     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->pubkey = *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->pubkey = 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 :   FD_DCHECK_CRIT( new_target_program_data->data_sz>=PROGRAMDATA_METADATA_SIZE, "undersize account" );
     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->lamports, source->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->lamports, new_target_program_data->lamports, &lamports_to_fund ) ) ) return;
     634             : 
     635             :   /* Write back accounts */
     636           0 :   tmp_account_store( bank, accdb, new_target_program,      capture_ctx );
     637           0 :   tmp_account_store( bank, accdb, new_target_program_data, capture_ctx );
     638           0 :   fd_tmp_account_t * empty = &runtime_stack->bpf_migration.empty;
     639           0 :   tmp_account_new( empty, 0UL );
     640           0 :   empty->pubkey = source->pubkey;
     641           0 :   tmp_account_store( bank, accdb, empty, 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_t *                           accdb,
     652             :                                 fd_runtime_stack_t *                   runtime_stack,
     653             :                                 fd_core_bpf_migration_config_t const * config,
     654           0 :                                 fd_capture_ctx_t *                     capture_ctx ) {
     655           0 :   migrate_builtin_to_core_bpf1( config, accdb, bank, runtime_stack, config->builtin_program_id, capture_ctx );
     656           0 : }
     657             : 
     658             : /* Mimics upgrade_core_bpf_program().
     659             :    https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L319-L377 */
     660             : void
     661             : fd_upgrade_core_bpf_program( fd_bank_t *                            bank,
     662             :                              fd_accdb_t *                           accdb,
     663             :                              fd_runtime_stack_t *                   runtime_stack,
     664             :                              fd_pubkey_t const *                    builtin_program_id,
     665             :                              fd_pubkey_t const *                    source_buffer_address,
     666           0 :                              fd_capture_ctx_t *                     capture_ctx ) {
     667           0 :   fd_memset( &runtime_stack->bpf_migration, 0, sizeof(runtime_stack->bpf_migration) );
     668             : 
     669             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L327 */
     670           0 :   target_core_bpf_t target[1];
     671           0 :   if( FD_UNLIKELY( !target_core_bpf_new_checked( target, builtin_program_id, accdb, bank->accdb_fork_id, runtime_stack ) ) ) {
     672           0 :     return;
     673           0 :   }
     674             : 
     675             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L328 */
     676           0 :   fd_tmp_account_t * source = &runtime_stack->bpf_migration.source;
     677           0 :   if( FD_UNLIKELY( !source_buffer_new_checked( source, accdb, bank->accdb_fork_id, source_buffer_address, NULL ) ) ) {
     678           0 :     return;
     679           0 :   }
     680             : 
     681             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L331-L332  */
     682           0 :   fd_tmp_account_t * new_target_program_data = &runtime_stack->bpf_migration.new_target_program_data;
     683           0 :   fd_pubkey_t program_data_address = get_program_data_address( builtin_program_id );
     684             : 
     685           0 :   ulong program_data_len = source->data_sz - BUFFER_METADATA_SIZE;
     686           0 :   ulong new_account_size = PROGRAMDATA_METADATA_SIZE + program_data_len;
     687             : 
     688           0 :   tmp_account_new( new_target_program_data, new_account_size );
     689           0 :   new_target_program_data->pubkey = program_data_address;
     690             : 
     691           0 :   fd_rent_t const * rent = &bank->f.rent;
     692           0 :   new_target_program_data->lamports   = fd_rent_exempt_minimum_balance( rent, new_account_size );
     693           0 :   new_target_program_data->executable = 0;
     694           0 :   fd_memcpy( new_target_program_data->owner.uc, &fd_solana_bpf_loader_upgradeable_program_id, sizeof(fd_pubkey_t) );
     695             : 
     696           0 :   fd_bpf_state_t programdata_state[1] = {{
     697           0 :     .discriminant = FD_BPF_STATE_PROGRAM_DATA,
     698           0 :     .inner = { .program_data = {
     699           0 :       .slot = bank->f.slot,
     700           0 :       .upgrade_authority_address = target->upgrade_authority_address,
     701           0 :       .has_upgrade_authority_address = target->has_upgrade_authority_address
     702           0 :     }}
     703           0 :   }};
     704             : 
     705           0 :   ulong out_sz = 0UL;
     706           0 :   if( FD_UNLIKELY( fd_bpf_state_encode( programdata_state, new_target_program_data->data, PROGRAMDATA_METADATA_SIZE, &out_sz ) ) ) {
     707           0 :     return;
     708           0 :   }
     709             : 
     710           0 :   fd_memcpy( new_target_program_data->data + PROGRAMDATA_METADATA_SIZE,
     711           0 :              source->data + BUFFER_METADATA_SIZE,
     712           0 :              program_data_len );
     713             : 
     714             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.4/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L339-L346 */
     715           0 :   ulong old_data_sz;
     716           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_data_account->data_sz, source->data_sz, &old_data_sz ) ) ) return;
     717           0 :   ulong new_data_sz = new_target_program_data->data_sz;
     718             : 
     719             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.4/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L349-L355 */
     720           0 :   uchar const * elf    = new_target_program_data->data + PROGRAMDATA_METADATA_SIZE;
     721           0 :   ulong         elf_sz = program_data_len;
     722           0 :   if( FD_UNLIKELY( fd_directly_invoke_loader_v3_deploy_checks( bank, runtime_stack, elf, elf_sz ) ) ) return;
     723             : 
     724             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L359-L364 */
     725           0 :   ulong lamports_to_burn;
     726           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_data_account->lamports, source->lamports, &lamports_to_burn ) ) ) return;
     727             : 
     728             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L366-L371 */
     729           0 :   fd_pubkey_t source_addr = source->pubkey;
     730           0 :   tmp_account_store( bank, accdb, new_target_program_data, capture_ctx );
     731             : 
     732           0 :   fd_tmp_account_t * empty = &runtime_stack->bpf_migration.empty;
     733           0 :   tmp_account_new( empty, 0UL );
     734           0 :   empty->pubkey = source_addr;
     735           0 :   tmp_account_store( bank, accdb, empty, capture_ctx );
     736             : 
     737             :   /* https://github.com/anza-xyz/agave/blob/v3.1.7/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L374 */
     738             :   /* FIXME "update account data size delta" */
     739           0 :   (void)old_data_sz;
     740           0 :   (void)new_data_sz;
     741             : 
     742           0 :   fd_memset( &runtime_stack->bpf_migration, 0, sizeof(runtime_stack->bpf_migration) );
     743           0 : }
     744             : 
     745             : /* Mimics upgrade_loader_v2_program_with_loader_v3_program().
     746             :    https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L402-L474 */
     747             : void
     748             : fd_upgrade_loader_v2_program_with_loader_v3_program( fd_bank_t *               bank,
     749             :                                                      fd_accdb_t *              accdb,
     750             :                                                      fd_runtime_stack_t *      runtime_stack,
     751             :                                                      fd_pubkey_t const *       loader_v2_program_address,
     752             :                                                      fd_pubkey_t const *       source_buffer_address,
     753             :                                                      int                       allow_prefunded,
     754           0 :                                                      fd_capture_ctx_t *        capture_ctx ) {
     755           0 :   fd_memset( &runtime_stack->bpf_migration, 0, sizeof(runtime_stack->bpf_migration) );
     756             : 
     757             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L411-L412 */
     758           0 :   target_builtin_t target[1];
     759           0 :   if( FD_UNLIKELY( !target_bpf_v2_new_checked(
     760           0 :       target,
     761           0 :       loader_v2_program_address,
     762           0 :       allow_prefunded,
     763           0 :       accdb,
     764           0 :       bank->accdb_fork_id,
     765           0 :       runtime_stack ) ) )
     766           0 :     return;
     767             : 
     768             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L413 */
     769           0 :   fd_tmp_account_t * source = &runtime_stack->bpf_migration.source;
     770           0 :   if( FD_UNLIKELY( !source_buffer_new_checked( source, accdb, bank->accdb_fork_id, source_buffer_address, NULL ) ) )
     771           0 :     return;
     772             : 
     773           0 :   fd_rent_t const * rent = &bank->f.rent;
     774           0 :   ulong             slot = bank->f.slot;
     775             : 
     776             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L416-L417 */
     777           0 :   fd_tmp_account_t * new_target_program = &runtime_stack->bpf_migration.new_target_program;
     778           0 :   if( FD_UNLIKELY( !new_target_program_account( new_target_program, target, rent ) ) )
     779           0 :     return;
     780           0 :   new_target_program->pubkey = *loader_v2_program_address;
     781             : 
     782             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L419-L421 */
     783           0 :   fd_tmp_account_t * new_target_program_data = &runtime_stack->bpf_migration.new_target_program_data;
     784           0 :   if( FD_UNLIKELY( !new_target_program_data_account( new_target_program_data, source, NULL, rent, slot ) ) ) {
     785           0 :     return;
     786           0 :   }
     787           0 :   new_target_program_data->pubkey = target->program_data_address;
     788             : 
     789             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L427-L435 */
     790           0 :   ulong old_data_sz;
     791           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_account->data_sz, source->data_sz, &old_data_sz ) ) ) return;
     792             : 
     793             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L432-L435 */
     794           0 :   ulong new_data_sz;
     795           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( new_target_program->data_sz, new_target_program_data->data_sz, &new_data_sz ) ) ) return;
     796             : 
     797           0 :   if( FD_UNLIKELY( new_target_program_data->data_sz<PROGRAMDATA_METADATA_SIZE ) ) {
     798           0 :     FD_LOG_CRIT(( "invariant violation: new target programdata too small" ));
     799           0 :   }
     800             : 
     801             :   /* Agave calls directly_invoke_loader_v3_deploy to deploy the new
     802             :      program to the program cache. We don't do that, but instead we
     803             :      perform the same checks as directly_invoke_loader_v3_deploy
     804             :      without modifying the program cache. We need to do the checks
     805             :      at this point so that we can fail the upgrade if the ELF is
     806             :      invalid.
     807             : 
     808             :      This is safe because the bpf migration code runs at the epoch
     809             :      boundary, before any transaction execution. The program cache
     810             :      automatically invalidates all programs at the start of an epoch
     811             :      boundary, so we do not need to explicitly update the cache during the
     812             :      migration.
     813             : 
     814             :      https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L437-L443*/
     815           0 :   uchar const * elf    = (uchar const *)new_target_program_data->data + PROGRAMDATA_METADATA_SIZE;
     816           0 :   ulong         elf_sz = new_target_program_data->data_sz - PROGRAMDATA_METADATA_SIZE;
     817           0 :   if( FD_UNLIKELY( fd_directly_invoke_loader_v3_deploy_checks( bank, runtime_stack, elf, elf_sz ) ) ) return;
     818             : 
     819             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L451-L459 */
     820           0 :   ulong lamports_to_burn;
     821           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( target->program_account->lamports, source->lamports, &lamports_to_burn ) ) ) return;
     822           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( lamports_to_burn, target->program_data_account_lamports, &lamports_to_burn ) ) )       return;
     823             : 
     824           0 :   ulong lamports_to_fund;
     825           0 :   if( FD_UNLIKELY( fd_ulong_checked_add( new_target_program->lamports, new_target_program_data->lamports, &lamports_to_fund ) ) ) return;
     826             : 
     827             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L462-L468 */
     828           0 :   tmp_account_store( bank, accdb, new_target_program,      capture_ctx );
     829           0 :   tmp_account_store( bank, accdb, new_target_program_data, capture_ctx );
     830             : 
     831           0 :   fd_tmp_account_t * empty = &runtime_stack->bpf_migration.empty;
     832           0 :   tmp_account_new( empty, 0UL );
     833           0 :   empty->pubkey = source->pubkey;
     834           0 :   tmp_account_store( bank, accdb, empty, capture_ctx );
     835             : 
     836             :   /* NB: Agave updates "delta_off_chain", using these two fields,
     837             :      which is not consensus-critical (only used for Agave stats)
     838             :      so we don't update this in our migration code or store this in
     839             :      our bank. */
     840           0 :   (void)old_data_sz;
     841           0 :   (void)new_data_sz;
     842             : 
     843           0 :   fd_memset( &runtime_stack->bpf_migration, 0, sizeof(runtime_stack->bpf_migration) );
     844           0 : }

Generated by: LCOV version 1.14