LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_runtime.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 353 382 92.4 %
Date: 2026-10-22 18:10:43 Functions: 11 11 100.0 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : #include "../../runtime/context/fd_exec_instr_ctx.h"
       3             : #include "../../runtime/fd_system_ids.h"
       4             : #include "fd_vm_syscall_macros.h"
       5             : 
       6             : /* The VM structs for sysvars that are exposed by the VM are represented
       7             :    differently from the representations of the accounts in the accounts
       8             :    database. These structs usually have padding which must be zeroed
       9             :    out. */
      10             : struct fd_vm_epoch_schedule {
      11             :   ulong slots_per_epoch;
      12             :   ulong leader_schedule_slot_offset;
      13             :   uchar warmup; /* 0 or 1 */
      14             :   uchar padding_[7];
      15             :   ulong first_normal_epoch;
      16             :   ulong first_normal_slot;
      17             : };
      18             : typedef struct fd_vm_epoch_schedule fd_vm_epoch_schedule_t;
      19             : FD_STATIC_ASSERT( sizeof(fd_vm_epoch_schedule_t) == 40UL, "vm epoch schedule size mismatch" );
      20             : FD_STATIC_ASSERT( alignof(fd_vm_epoch_schedule_t) == FD_VM_ALIGN_RUST_SYSVAR_EPOCH_SCHEDULE, "vm epoch schedule alignment mismatch" );
      21             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, slots_per_epoch            ) == 0UL,      "vm epoch schedule layout mismatch"    );
      22             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, leader_schedule_slot_offset) == 8UL,      "vm epoch schedule layout mismatch"    );
      23             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, warmup                     ) == 16UL,     "vm epoch schedule layout mismatch"    );
      24             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, first_normal_epoch         ) == 24UL,     "vm epoch schedule layout mismatch"    );
      25             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_schedule_t, first_normal_slot          ) == 32UL,     "vm epoch schedule layout mismatch"    );
      26             : 
      27             : struct fd_vm_rent {
      28             :   ulong  lamports_per_uint8_year;
      29             :   double exemption_threshold;
      30             :   uchar  burn_percent;
      31             :   uchar  padding_[7];
      32             : };
      33             : typedef struct fd_vm_rent fd_vm_rent_t;
      34             : FD_STATIC_ASSERT( sizeof(fd_vm_rent_t) == 24UL, "vm rent size mismatch" );
      35             : FD_STATIC_ASSERT( alignof(fd_vm_rent_t) == FD_VM_ALIGN_RUST_SYSVAR_RENT,   "vm rent alignment mismatch" );
      36             : FD_STATIC_ASSERT( offsetof(fd_vm_rent_t, lamports_per_uint8_year) == 0UL,  "vm rent layout mismatch"    );
      37             : FD_STATIC_ASSERT( offsetof(fd_vm_rent_t, exemption_threshold    ) == 8UL,  "vm rent layout mismatch"    );
      38             : FD_STATIC_ASSERT( offsetof(fd_vm_rent_t, burn_percent           ) == 16UL, "vm rent layout mismatch"    );
      39             : 
      40             : typedef fd_sol_sysvar_clock_t fd_vm_clock_t;
      41             : FD_STATIC_ASSERT( sizeof(fd_vm_clock_t) == 40UL, "vm clock size mismatch" );
      42             : FD_STATIC_ASSERT( alignof(fd_vm_clock_t) == FD_VM_ALIGN_RUST_SYSVAR_CLOCK, "vm clock alignment mismatch" );
      43             : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, slot                 ) == 0UL,   "vm clock layout mismatch"    );
      44             : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, epoch_start_timestamp) == 8UL,   "vm clock layout mismatch"    );
      45             : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, epoch                ) == 16UL,  "vm clock layout mismatch"    );
      46             : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, leader_schedule_epoch) == 24UL,  "vm clock layout mismatch"    );
      47             : FD_STATIC_ASSERT( offsetof(fd_vm_clock_t, unix_timestamp       ) == 32UL,  "vm clock layout mismatch"    );
      48             : 
      49             : struct __attribute__((aligned(16))) fd_vm_epoch_rewards {
      50             :   ulong       distribution_starting_block_height;
      51             :   ulong       num_partitions;
      52             :   fd_hash_t   parent_blockhash;
      53             :   fd_w_u128_t total_points;
      54             :   ulong       total_rewards;
      55             :   ulong       distributed_rewards;
      56             :   uchar       active; /* 0 or 1 */
      57             :   uchar       padding_[15];
      58             : };
      59             : typedef struct fd_vm_epoch_rewards fd_vm_epoch_rewards_t;
      60             : FD_STATIC_ASSERT( sizeof(fd_vm_epoch_rewards_t) == 96UL, "vm epoch rewards size mismatch" );
      61             : FD_STATIC_ASSERT( alignof(fd_vm_epoch_rewards_t) == FD_VM_ALIGN_RUST_SYSVAR_EPOCH_REWARDS,     "vm epoch rewards alignment mismatch" );
      62             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, distribution_starting_block_height) == 0UL,  "vm epoch rewards layout mismatch"    );
      63             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, num_partitions                    ) == 8UL,  "vm epoch rewards layout mismatch"    );
      64             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, parent_blockhash                  ) == 16UL, "vm epoch rewards layout mismatch"    );
      65             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, total_points                      ) == 48UL, "vm epoch rewards layout mismatch"    );
      66             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, total_rewards                     ) == 64UL, "vm epoch rewards layout mismatch"    );
      67             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, distributed_rewards               ) == 72UL, "vm epoch rewards layout mismatch"    );
      68             : FD_STATIC_ASSERT( offsetof(fd_vm_epoch_rewards_t, active                            ) == 80UL, "vm epoch rewards layout mismatch"    );
      69             : 
      70             : /* FIXME: In the original version of this code, there was an FD_TEST
      71             :    to check if the VM was attached to an instruction context (that
      72             :    would have crashed anyway because of pointer chasing).  If the VM
      73             :    is being run outside the Solana runtime, it should never invoke
      74             :    this syscall in the first place.  So we treat this as a SIGCALL in
      75             :    a non-crashing way for the time being. */
      76             : 
      77             : int
      78             : fd_vm_syscall_sol_get_clock_sysvar( /**/            void *  _vm,
      79             :                                     /**/            ulong   out_vaddr,
      80             :                                     FD_PARAM_UNUSED ulong   r2,
      81             :                                     FD_PARAM_UNUSED ulong   r3,
      82             :                                     FD_PARAM_UNUSED ulong   r4,
      83         174 :                                     FD_PARAM_UNUSED ulong   r5 ) {
      84         174 :   fd_vm_t * vm = _vm;
      85         174 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
      86         174 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
      87             : 
      88         348 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_clock_t) ) );
      89             : 
      90             :   /* See https://github.com/anza-xyz/agave/pull/12130 */
      91         174 :   if( FD_UNLIKELY( vm->is_deprecated ) ) {
      92          30 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
      93          30 :     return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
      94          30 :   }
      95             : 
      96         144 :   if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
      97           1 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
      98           1 :     return FD_VM_ERR_INVAL;
      99           1 :   }
     100             : 
     101         143 :   fd_vm_haddr_query_t var_query = {
     102         143 :     .vaddr    = out_vaddr,
     103         143 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_CLOCK,
     104         143 :     .sz       = sizeof(fd_vm_clock_t),
     105         143 :     .is_slice = 0,
     106         143 :   };
     107             : 
     108         143 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     109         143 :   FD_VM_TRANSLATE_MUT( vm, queries );
     110             : 
     111         143 :   fd_vm_clock_t clock = fd_sysvar_cache_clock_read_nofail( instr_ctx->sysvar_cache );
     112           0 :   memcpy( var_query.haddr, &clock, sizeof(fd_vm_clock_t) );
     113             : 
     114         143 :   vm->reg[0] = 0UL;
     115         143 :   return FD_VM_SUCCESS;
     116         143 : }
     117             : 
     118             : int
     119             : fd_vm_syscall_sol_get_epoch_schedule_sysvar( /**/            void *  _vm,
     120             :                                              /**/            ulong   out_vaddr,
     121             :                                              FD_PARAM_UNUSED ulong   r2,
     122             :                                              FD_PARAM_UNUSED ulong   r3,
     123             :                                              FD_PARAM_UNUSED ulong   r4,
     124         120 :                                              FD_PARAM_UNUSED ulong   r5 ) {
     125         120 :   fd_vm_t * vm = _vm;
     126         120 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     127         120 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     128             : 
     129         240 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_epoch_schedule_t) ) );
     130             : 
     131             :   /* See https://github.com/anza-xyz/agave/pull/12130 */
     132         120 :   if( FD_UNLIKELY( vm->is_deprecated ) ) {
     133          44 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
     134          44 :     return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
     135          44 :   }
     136             : 
     137          76 :   if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     138           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     139           3 :     return FD_VM_ERR_INVAL;
     140           3 :   }
     141             : 
     142          73 :   fd_vm_haddr_query_t var_query = {
     143          73 :     .vaddr    = out_vaddr,
     144          73 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_EPOCH_SCHEDULE,
     145          73 :     .sz       = sizeof(fd_vm_epoch_schedule_t),
     146          73 :     .is_slice = 0,
     147          73 :   };
     148             : 
     149          73 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     150          73 :   FD_VM_TRANSLATE_MUT( vm, queries );
     151             : 
     152          73 :   fd_epoch_schedule_t schedule;
     153          73 :   if( FD_UNLIKELY( !fd_sysvar_cache_epoch_schedule_read( instr_ctx->sysvar_cache, &schedule ) ) ) {
     154           0 :     FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_out, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_out->err.exec_err_idx );
     155           0 :     return FD_VM_ERR_INVAL;
     156           0 :   }
     157             : 
     158             :   /* Returned value has padding which must be zeroed out. */
     159          73 :   uchar * dst = var_query.haddr;
     160          73 :   fd_vm_epoch_schedule_t * vm_schedule = (fd_vm_epoch_schedule_t *)dst;
     161          73 :   *vm_schedule = (fd_vm_epoch_schedule_t){
     162          73 :     .slots_per_epoch             = schedule.slots_per_epoch,
     163          73 :     .leader_schedule_slot_offset = schedule.leader_schedule_slot_offset,
     164          73 :     .warmup                      = schedule.warmup,
     165          73 :     .first_normal_epoch          = schedule.first_normal_epoch,
     166          73 :     .first_normal_slot           = schedule.first_normal_slot,
     167          73 :   };
     168             : 
     169          73 :   vm->reg[0] = 0UL;
     170          73 :   return FD_VM_SUCCESS;
     171          73 : }
     172             : 
     173             : int
     174             : fd_vm_syscall_sol_get_rent_sysvar( /**/            void *  _vm,
     175             :                                    /**/            ulong   out_vaddr,
     176             :                                    FD_PARAM_UNUSED ulong   r2,
     177             :                                    FD_PARAM_UNUSED ulong   r3,
     178             :                                    FD_PARAM_UNUSED ulong   r4,
     179         178 :                                    FD_PARAM_UNUSED ulong   r5 ) {
     180         178 :   fd_vm_t * vm = _vm;
     181             : 
     182             :   /* Unreachable in a real SVM, used for testing */
     183             : 
     184         178 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     185         178 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     186             : 
     187         356 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_rent_t) ) );
     188             : 
     189             :   /* See https://github.com/anza-xyz/agave/pull/12130 */
     190         178 :   if( FD_UNLIKELY( vm->is_deprecated ) ) {
     191          29 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
     192          29 :     return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
     193          29 :   }
     194             : 
     195         149 :   if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     196           2 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     197           2 :     return FD_VM_ERR_INVAL;
     198           2 :   }
     199             : 
     200         147 :   fd_vm_haddr_query_t var_query = {
     201         147 :     .vaddr    = out_vaddr,
     202         147 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_RENT,
     203         147 :     .sz       = sizeof(fd_vm_rent_t),
     204         147 :     .is_slice = 0,
     205         147 :   };
     206             : 
     207         147 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     208         147 :   FD_VM_TRANSLATE_MUT( vm, queries );
     209             : 
     210         147 :   fd_rent_t rent = fd_sysvar_cache_rent_read_nofail( instr_ctx->sysvar_cache );
     211             : 
     212             :   /* The returned value has padding which must be zeroed out. */
     213           0 :   uchar * dst = var_query.haddr;
     214         147 :   fd_vm_rent_t * vm_rent = (fd_vm_rent_t *)dst;
     215         147 :   *vm_rent = (fd_vm_rent_t){
     216         147 :     .lamports_per_uint8_year = rent.lamports_per_uint8_year,
     217         147 :     .exemption_threshold     = rent.exemption_threshold,
     218         147 :     .burn_percent            = rent.burn_percent,
     219         147 :   };
     220             : 
     221         147 :   vm->reg[0] = 0UL;
     222         147 :   return FD_VM_SUCCESS;
     223         147 : }
     224             : 
     225             : /* https://github.com/anza-xyz/agave/blob/v2.3.2/programs/bpf_loader/src/syscalls/sysvar.rs#L149 */
     226             : int
     227             : fd_vm_syscall_sol_get_last_restart_slot_sysvar( /**/            void *  _vm,
     228             :                                                 /**/            ulong   out_vaddr,
     229             :                                                 FD_PARAM_UNUSED ulong   r2,
     230             :                                                 FD_PARAM_UNUSED ulong   r3,
     231             :                                                 FD_PARAM_UNUSED ulong   r4,
     232         130 :                                                 FD_PARAM_UNUSED ulong   r5 ) {
     233         130 :   fd_vm_t * vm = _vm;
     234         130 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     235         130 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     236             : 
     237         260 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, 8UL ) );
     238             : 
     239             :   /* See https://github.com/anza-xyz/agave/pull/12130 */
     240         130 :   if( FD_UNLIKELY( vm->is_deprecated ) ) {
     241          35 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
     242          35 :     return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
     243          35 :   }
     244             : 
     245          95 :   if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     246           5 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     247           5 :     return FD_VM_ERR_INVAL;
     248           5 :   }
     249             : 
     250          90 :   fd_vm_haddr_query_t var_query = {
     251          90 :     .vaddr    = out_vaddr,
     252          90 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_LAST_RESTART_SLOT,
     253          90 :     .sz       = sizeof(ulong),
     254          90 :     .is_slice = 0,
     255          90 :   };
     256             : 
     257          90 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     258          90 :   FD_VM_TRANSLATE_MUT( vm, queries );
     259             : 
     260          90 :   ulong const * last_restart_slot = fd_sysvar_cache_last_restart_slot_read( vm->instr_ctx->sysvar_cache );
     261          90 :   if( FD_UNLIKELY( last_restart_slot==NULL ) ) {
     262          21 :     FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_out, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_out->err.exec_err_idx );
     263          21 :     return FD_VM_ERR_INVAL;
     264          21 :   }
     265             : 
     266          69 :   memcpy( var_query.haddr, last_restart_slot, sizeof(ulong) );
     267             : 
     268          69 :   vm->reg[0] = 0UL;
     269          69 :   return FD_VM_SUCCESS;
     270          90 : }
     271             : 
     272             : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L167-L232 */
     273             : int
     274             : fd_vm_syscall_sol_get_sysvar( /**/            void *  _vm,
     275             :                               /**/            ulong   sysvar_id_vaddr,
     276             :                               /**/            ulong   out_vaddr,
     277             :                               /**/            ulong   offset,
     278             :                               /**/            ulong   sz,
     279         365 :                               FD_PARAM_UNUSED ulong   r5 ) {
     280         365 :   fd_vm_t * vm = _vm;
     281         365 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     282         365 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     283             : 
     284             :   /* sysvar_id_cost seems to just always be 32 / 250 = 0...
     285             :      https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L190-L197 */
     286         365 :   ulong sysvar_buf_cost = sz / FD_VM_CPI_BYTES_PER_UNIT;
     287         365 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, fd_ulong_max( sysvar_buf_cost, FD_VM_MEM_OP_BASE_COST ) ) );
     288             : 
     289             :   /* See https://github.com/anza-xyz/agave/pull/12130 */
     290         338 :   if( FD_UNLIKELY( vm->is_deprecated ) ) {
     291         117 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
     292         117 :     return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
     293         117 :   }
     294             : 
     295         221 :   if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     296          33 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     297          33 :     return FD_VM_ERR_INVAL;
     298          33 :   }
     299             : 
     300             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/sysvar.rs#L207-L211 */
     301         188 :   fd_vm_haddr_query_t var_query = {
     302         188 :     .vaddr    = out_vaddr,
     303         188 :     .align    = FD_VM_ALIGN_RUST_U8,
     304         188 :     .sz       = sz,
     305         188 :     .is_slice = 1,
     306         188 :   };
     307             : 
     308         188 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     309         188 :   FD_VM_TRANSLATE_MUT( vm, queries );
     310             : 
     311             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L199-L200 */
     312         480 :   const fd_pubkey_t * sysvar_id = FD_VM_MEM_HADDR_LD( vm, sysvar_id_vaddr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
     313             : 
     314             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L205-L208 */
     315           0 :   ulong offset_length;
     316         480 :   int err = fd_int_if( __builtin_uaddl_overflow( offset, sz, &offset_length ), FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW, FD_EXECUTOR_INSTR_SUCCESS );
     317         480 :   if( FD_UNLIKELY( err ) ) {
     318           0 :     FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     319           0 :     return FD_VM_SYSCALL_ERR_ABORT;
     320           0 :   }
     321             : 
     322             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L210-L213
     323             :      We don't need this, we already checked we can store in out_vaddr with requested sz. */
     324             : 
     325             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L215-L221 */
     326         160 :   if( FD_UNLIKELY( memcmp( sysvar_id->uc, fd_sysvar_clock_id.uc,             FD_PUBKEY_FOOTPRINT ) &&
     327         160 :                    memcmp( sysvar_id->uc, fd_sysvar_epoch_schedule_id.uc,    FD_PUBKEY_FOOTPRINT ) &&
     328         160 :                    memcmp( sysvar_id->uc, fd_sysvar_epoch_rewards_id.uc,     FD_PUBKEY_FOOTPRINT ) &&
     329         160 :                    memcmp( sysvar_id->uc, fd_sysvar_rent_id.uc,              FD_PUBKEY_FOOTPRINT ) &&
     330         160 :                    memcmp( sysvar_id->uc, fd_sysvar_slot_hashes_id.uc,       FD_PUBKEY_FOOTPRINT ) &&
     331         160 :                    memcmp( sysvar_id->uc, fd_sysvar_stake_history_id.uc,     FD_PUBKEY_FOOTPRINT ) &&
     332         160 :                    memcmp( sysvar_id->uc, fd_sysvar_last_restart_slot_id.uc, FD_PUBKEY_FOOTPRINT ) ) ) {
     333          84 :     vm->reg[0] = 2UL;
     334          84 :     return FD_VM_SUCCESS;
     335          84 :   }
     336             : 
     337          76 :   ulong         sysvar_buf_len;
     338          76 :   uchar const * sysvar_buf =
     339          76 :     fd_sysvar_cache_data_query( vm->instr_ctx->sysvar_cache, sysvar_id, &sysvar_buf_len );
     340          76 :   if( FD_UNLIKELY( !sysvar_buf ) ) {
     341           3 :     vm->reg[0] = 2UL;
     342           3 :     return FD_VM_SUCCESS;
     343           3 :   }
     344             : 
     345             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L223-L228
     346             :      Note the length check is at the very end to fail after performing sufficient checks. */
     347             : 
     348          73 :   if( FD_UNLIKELY( offset_length>sysvar_buf_len ) ) {
     349          12 :     vm->reg[0] = 1UL;
     350          12 :     return FD_VM_SUCCESS;
     351          12 :   }
     352             : 
     353          61 :   if( FD_UNLIKELY( sz==0UL ) ) {
     354           4 :     vm->reg[0] = 0UL;
     355           4 :     return FD_VM_SUCCESS;
     356           4 :   }
     357             : 
     358          57 :   fd_memcpy( var_query.haddr, sysvar_buf + offset, sz );
     359          57 :   vm->reg[0] = 0UL;
     360          57 :   return FD_VM_SUCCESS;
     361          61 : }
     362             : 
     363             : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2043-L2118 */
     364             : int
     365             : fd_vm_syscall_sol_get_epoch_stake( /**/            void *  _vm,
     366             :                                    /**/            ulong   var_addr,
     367             :                                    FD_PARAM_UNUSED ulong   r2,
     368             :                                    FD_PARAM_UNUSED ulong   r3,
     369             :                                    FD_PARAM_UNUSED ulong   r4,
     370          94 :                                    FD_PARAM_UNUSED ulong   r5 ) {
     371          94 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     372             : 
     373             :   /* Var addr of 0 returns the total active stake on the cluster.
     374             : 
     375             :      https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2057-L2075 */
     376          94 :   if( FD_UNLIKELY( var_addr==0UL ) ) {
     377             :     /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2065-L2066 */
     378          46 :     FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     379             : 
     380             :     /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2074 */
     381           0 :     vm->reg[0] = vm->instr_ctx->bank->f.total_epoch_stake;
     382          46 :     return FD_VM_SUCCESS;
     383          46 :   }
     384             : 
     385             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2083-L2091
     386             :      FD_PUBKEY_FOOTPRINT/FD_VM_CPI_BYTES_PER_UNIT is always 32/250 = 0,
     387             :      so we can omit it */
     388             : 
     389          96 :   FD_VM_CU_UPDATE( vm, FD_VM_MEM_OP_BASE_COST + FD_VM_SYSCALL_BASE_COST );
     390             : 
     391             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2103-L2104 */
     392          48 :   fd_pubkey_t const * vote_address = FD_VM_MEM_HADDR_LD( vm, var_addr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
     393             : 
     394             :   /* https://github.com/anza-xyz/agave/blob/v2.2.14/runtime/src/bank.rs#L6954 */
     395             : 
     396           0 :   ulong stake = 0UL;
     397             :   /* It's okay to ignore if an account is invalid since these stakes
     398             :      are calculated from an older snapshot of vote account stakes. */
     399          48 :   fd_bank_t *          bank = vm->instr_ctx->bank;
     400          48 :   fd_vote_stakes_ele_t ele[1];
     401          48 :   if( fd_vote_stakes_query_t_1( fd_bank_vote_stakes( bank ), bank->vote_stakes_fork_id, vote_address, ele ) ) stake = ele->stake;
     402             : 
     403          48 :   vm->reg[0] = stake;
     404             : 
     405          48 :   return FD_VM_SUCCESS;
     406          96 : }
     407             : 
     408             : int
     409             : fd_vm_syscall_sol_get_stack_height( /**/            void *  _vm,
     410             :                                     FD_PARAM_UNUSED ulong   r1,
     411             :                                     FD_PARAM_UNUSED ulong   r2,
     412             :                                     FD_PARAM_UNUSED ulong   r3,
     413             :                                     FD_PARAM_UNUSED ulong   r4,
     414         472 :                                     FD_PARAM_UNUSED ulong   r5 ) {
     415             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1547 */
     416         472 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     417             : 
     418         472 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     419             : 
     420           0 :   vm->reg[0] = vm->instr_ctx->runtime->instr.stack_sz;
     421         472 :   return FD_VM_SUCCESS;
     422         472 : }
     423             : 
     424             : int
     425             : fd_vm_syscall_sol_get_return_data( /**/            void *  _vm,
     426             :                                    /**/            ulong   return_data_vaddr,
     427             :                                    /**/            ulong   sz,
     428             :                                    /**/            ulong   program_id_vaddr,
     429             :                                    FD_PARAM_UNUSED ulong   r4,
     430         129 :                                    FD_PARAM_UNUSED ulong   r5 ) {
     431         129 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     432             : 
     433             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1465 */
     434         129 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     435             : 
     436             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1467 */
     437           0 :   fd_txn_return_data_t const * return_data = &vm->instr_ctx->txn_out->details.return_data;
     438             : 
     439             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1468 */
     440         129 :   ulong length = fd_ulong_min( return_data->len, sz );
     441             : 
     442             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1469-L1492 */
     443         129 :   if( FD_LIKELY( length ) ) {
     444             : 
     445             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1470-L1474 */
     446          34 :     FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( length, sizeof(fd_pubkey_t) ) / FD_VM_CPI_BYTES_PER_UNIT );
     447             : 
     448             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1476-L1481 */
     449           0 :     fd_vm_haddr_query_t return_data_query = {
     450          34 :       .vaddr    = return_data_vaddr,
     451          34 :       .align    = FD_VM_ALIGN_RUST_U8,
     452          34 :       .sz       = length,
     453          34 :       .is_slice = 1
     454          34 :     };
     455             : 
     456          34 :     fd_vm_haddr_query_t program_id_query = {
     457          34 :       .vaddr    = program_id_vaddr,
     458          34 :       .align    = FD_VM_ALIGN_RUST_PUBKEY,
     459          34 :       .sz       = sizeof(fd_pubkey_t),
     460          34 :       .is_slice = 0
     461          34 :     };
     462             : 
     463          34 :     fd_vm_haddr_query_t * queries[] = { &return_data_query, &program_id_query };
     464          34 :     FD_VM_TRANSLATE_MUT( vm, queries );
     465             : 
     466             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1490-L1491 */
     467          29 :     memcpy( return_data_query.haddr, return_data->data, length );
     468          29 :     memcpy( program_id_query.haddr, &return_data->program_id, sizeof(fd_pubkey_t) );
     469          29 :   }
     470             : 
     471             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1495 */
     472         124 :   vm->reg[0] = return_data->len;
     473         124 :   return FD_VM_SUCCESS;
     474         129 : }
     475             : 
     476             : int
     477             : fd_vm_syscall_sol_set_return_data( /**/            void *  _vm,
     478             :                                    /**/            ulong   src_vaddr,
     479             :                                    /**/            ulong   src_sz,
     480             :                                    FD_PARAM_UNUSED ulong   r3,
     481             :                                    FD_PARAM_UNUSED ulong   r4,
     482         165 :                                    FD_PARAM_UNUSED ulong   r5 ) {
     483             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1297 */
     484         165 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     485             : 
     486             :   /* In the original version of this code, there was an FD_TEST
     487             :      to check if the VM was attached to an instruction context (that
     488             :      would have crashed anyway because of pointer chasing).  If the VM
     489             :      is being run outside the Solana runtime, it should never invoke
     490             :      this syscall in the first place.  So we treat this as a SIGCALL in
     491             :      a non-crashing way for the time being. */
     492         165 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     493         165 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     494             : 
     495         330 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSCALL_BASE_COST, src_sz / FD_VM_CPI_BYTES_PER_UNIT ) );
     496             : 
     497             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1316 */
     498         165 :   if( FD_UNLIKELY( src_sz>FD_VM_RETURN_DATA_MAX ) ) {
     499             :     /* TODO: this is a bit annoying, we may want to unify return codes...
     500             :        - FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE is Agave's return code,
     501             :           also used for logging */
     502           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE );
     503           0 :     return FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE;
     504           0 :   }
     505             : 
     506             :   /* src_sz == 0 is ok */
     507         330 :   void const * src = FD_VM_MEM_SLICE_HADDR_LD( vm, src_vaddr, FD_VM_ALIGN_RUST_U8, src_sz );
     508             : 
     509             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/bpf_loader/src/syscalls/mod.rs#L1480-L1484 */
     510           0 :   fd_pubkey_t const * program_id = NULL;
     511         330 :   int err = fd_exec_instr_ctx_get_last_program_key( vm->instr_ctx, &program_id );
     512         330 :   if( FD_UNLIKELY( err ) ) {
     513           0 :     FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     514           0 :     return err;
     515           0 :   }
     516             : 
     517         165 :   fd_txn_return_data_t * return_data = &instr_ctx->txn_out->details.return_data;
     518             : 
     519         165 :   return_data->len = src_sz;
     520         165 :   if( FD_LIKELY( src_sz!=0UL ) ) {
     521         165 :     fd_memcpy( return_data->data, src, src_sz );
     522         165 :   }
     523         165 :   return_data->program_id = *program_id;
     524             : 
     525         165 :   vm->reg[0] = 0UL;
     526         165 :   return FD_VM_SUCCESS;
     527         330 : }
     528             : 
     529             : /* Used to query and convey information about the sibling instruction
     530             :    https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/sdk/program/src/instruction.rs#L676
     531             : 
     532             :     */
     533             : struct fd_vm_syscall_processed_sibling_instruction {
     534             :   /* Length of the instruction data */
     535             :   ulong data_len;
     536             :   /* Number of accounts */
     537             :   ulong accounts_len;
     538             : };
     539             : typedef struct fd_vm_syscall_processed_sibling_instruction fd_vm_syscall_processed_sibling_instruction_t;
     540             : 
     541           5 : #define FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_SIZE  (16UL)
     542           5 : #define FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_ALIGN (8UL )
     543             : 
     544             : /* https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/programs/bpf_loader/src/syscalls/mod.rs#L1402 */
     545             : int
     546             : fd_vm_syscall_sol_get_processed_sibling_instruction(
     547             :     void * _vm,
     548             :     ulong index,
     549             :     ulong result_meta_vaddr,
     550             :     ulong result_program_id_vaddr,
     551             :     ulong result_data_vaddr,
     552             :     ulong result_accounts_vaddr
     553         150 : ) {
     554         150 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     555             : 
     556             :   /* Consume base compute cost
     557             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1513 */
     558         150 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     559             : 
     560             :   /* Get the current instruction stack height.  This value is 1-indexed
     561             :      (top level instruction has a stack height of 1).
     562             :     https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1517 */
     563           0 :   ulong stack_height = vm->instr_ctx->runtime->instr.stack_sz;
     564             : 
     565             :   /* Reverse iterate through the instruction trace, ignoring anything except instructions on the same level.
     566             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1518-L1522 */
     567         150 :   ulong instruction_trace_length = vm->instr_ctx->runtime->instr.trace_length;
     568         150 :   ulong reverse_index_at_stack_height = 0UL;
     569         150 :   fd_instr_info_t * found_instruction_context = NULL;
     570         314 :   for( ulong index_in_trace=instruction_trace_length; index_in_trace>0UL; index_in_trace-- ) {
     571             : 
     572             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1524-L1526
     573             :        This error can never happen */
     574             : 
     575             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1527-L1529 */
     576         192 :     fd_instr_info_t * instruction_context = &vm->instr_ctx->runtime->instr.trace[ index_in_trace-1UL ];
     577         192 :     if( FD_LIKELY( instruction_context->stack_height<stack_height ) ) {
     578          23 :       break;
     579          23 :     }
     580             : 
     581             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1530-L1536 */
     582         169 :     if( FD_UNLIKELY( instruction_context->stack_height==stack_height ) ) {
     583         160 :       if( FD_UNLIKELY( fd_ulong_sat_add( index, 1UL )==reverse_index_at_stack_height ) ) {
     584           5 :         found_instruction_context = instruction_context;
     585           5 :         break;
     586           5 :       }
     587         155 :       reverse_index_at_stack_height = fd_ulong_sat_add( reverse_index_at_stack_height, 1UL );
     588         155 :     }
     589         169 :   }
     590             : 
     591             :   /* If we have found an entry, then copy the instruction into the
     592             :      result addresses.
     593             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1539-L1588
     594             :    */
     595         150 :   if( FD_LIKELY( found_instruction_context != NULL ) ) {
     596           5 :     fd_vm_haddr_query_t result_header_query = {
     597           5 :       .vaddr    = result_meta_vaddr,
     598           5 :       .align    = FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_ALIGN,
     599           5 :       .sz       = FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_SIZE,
     600           5 :       .is_slice = 0,
     601           5 :     };
     602             : 
     603           5 :     fd_vm_haddr_query_t * queries[] = { &result_header_query };
     604           5 :     FD_VM_TRANSLATE_MUT( vm, queries );
     605             : 
     606           5 :     fd_vm_syscall_processed_sibling_instruction_t * result_header = result_header_query.haddr;
     607             : 
     608             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1546-L1583 */
     609           5 :     if( result_header->data_len==found_instruction_context->data_sz && result_header->accounts_len==found_instruction_context->acct_cnt ) {
     610           2 :       fd_vm_haddr_query_t program_id_query = {
     611           2 :         .vaddr    = result_program_id_vaddr,
     612           2 :         .align    = FD_VM_ALIGN_RUST_PUBKEY,
     613           2 :         .sz       = sizeof(fd_pubkey_t),
     614           2 :         .is_slice = 0,
     615           2 :       };
     616             : 
     617           2 :       fd_vm_haddr_query_t data_query = {
     618           2 :         .vaddr    = result_data_vaddr,
     619           2 :         .align    = FD_VM_ALIGN_RUST_U8,
     620           2 :         .sz       = result_header->data_len,
     621           2 :         .is_slice = 1,
     622           2 :       };
     623             : 
     624           2 :       fd_vm_haddr_query_t accounts_query = {
     625           2 :         .vaddr    = result_accounts_vaddr,
     626           2 :         .align    = FD_VM_RUST_ACCOUNT_META_ALIGN,
     627           2 :         .sz       = fd_ulong_sat_mul( result_header->accounts_len, FD_VM_RUST_ACCOUNT_META_SIZE ),
     628           2 :         .is_slice = 1,
     629           2 :       };
     630             : 
     631           2 :       fd_vm_haddr_query_t * queries[] = { &program_id_query, &data_query, &accounts_query, &result_header_query };
     632           2 :       FD_VM_TRANSLATE_MUT( vm, queries );
     633             : 
     634           1 :       fd_pubkey_t *               program_id = program_id_query.haddr;
     635           1 :       uchar *                     data       = data_query.haddr;
     636           1 :       fd_vm_rust_account_meta_t * accounts   = accounts_query.haddr;
     637             : 
     638             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1561-L1562 */
     639           1 :       fd_pubkey_t const * instr_ctx_program_id = NULL;
     640           1 :       int err = fd_runtime_get_key_of_account_at_index(
     641           1 :           vm->instr_ctx->txn_out,
     642           1 :           found_instruction_context->program_id,
     643           1 :           &instr_ctx_program_id
     644           1 :       );
     645           1 :       if( FD_UNLIKELY( err ) ) {
     646           0 :         FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     647           0 :         return err;
     648           0 :       }
     649           1 :       fd_memcpy( program_id, instr_ctx_program_id, sizeof(fd_pubkey_t) );
     650             : 
     651             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1563 */
     652           1 :       if( FD_LIKELY( found_instruction_context->data_sz ) ) {
     653           1 :         fd_memcpy( data, found_instruction_context->data, found_instruction_context->data_sz );
     654           1 :       }
     655             : 
     656             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1564-L1581 */
     657         256 :       for( ushort i=0; i<found_instruction_context->acct_cnt; i++ ) {
     658         255 :         fd_pubkey_t const * account_key;
     659         255 :         ushort txn_idx = found_instruction_context->accounts[ i ].index_in_transaction;
     660         255 :         err            = fd_runtime_get_key_of_account_at_index( vm->instr_ctx->txn_out, txn_idx, &account_key );
     661         255 :         if( FD_UNLIKELY( err ) ) {
     662           0 :           FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     663           0 :           return err;
     664           0 :         }
     665             : 
     666         255 :         fd_memcpy( accounts[ i ].pubkey, account_key, sizeof(fd_pubkey_t) );
     667         255 :         accounts[ i ].is_signer   = !!(found_instruction_context->accounts[ i ].is_signer );
     668         255 :         accounts[ i ].is_writable = !!(found_instruction_context->accounts[ i ].is_writable );
     669         255 :       }
     670           3 :     } else {
     671             :       /* Copy the actual metadata into the result meta struct
     672             :          https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1584-L1586 */
     673           3 :       result_header->data_len     = found_instruction_context->data_sz;
     674           3 :       result_header->accounts_len = found_instruction_context->acct_cnt;
     675           3 :     }
     676             : 
     677             :     /* Return true as we found a sibling instruction
     678             :        https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1588 */
     679           4 :     vm->reg[0] = 1UL;
     680           4 :     return FD_VM_SUCCESS;
     681           5 :   }
     682             : 
     683             :   /* Return false if we didn't find a sibling instruction
     684             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1590 */
     685         145 :   vm->reg[0] = 0UL;
     686         145 :   return FD_VM_SUCCESS;
     687         150 : }
     688             : 
     689             : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/sysvar.rs#L80 */
     690             : int
     691             : fd_vm_syscall_sol_get_epoch_rewards_sysvar( /**/            void *  _vm,
     692             :                                             /**/            ulong   out_vaddr,
     693             :                                             FD_PARAM_UNUSED ulong   r2,
     694             :                                             FD_PARAM_UNUSED ulong   r3,
     695             :                                             FD_PARAM_UNUSED ulong   r4,
     696         108 :                                             FD_PARAM_UNUSED ulong   r5 ) {
     697         108 :   fd_vm_t * vm = _vm;
     698         108 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     699         108 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     700             : 
     701         216 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_vm_epoch_rewards_t) ) );
     702             : 
     703             :   /* See https://github.com/anza-xyz/agave/pull/12130 */
     704         108 :   if( FD_UNLIKELY( vm->is_deprecated ) ) {
     705          31 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_UNALIGNED_POINTER );
     706          31 :     return FD_VM_SYSCALL_ERR_UNALIGNED_POINTER;
     707          31 :   }
     708             : 
     709          77 :   if( FD_UNLIKELY( vm->syscall_parameter_address_restrictions && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     710           4 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     711           4 :     return FD_VM_ERR_INVAL;
     712           4 :   }
     713             : 
     714          73 :   uchar * out = FD_VM_MEM_HADDR_ST( vm, out_vaddr, FD_VM_ALIGN_RUST_SYSVAR_EPOCH_REWARDS, sizeof(fd_vm_epoch_rewards_t) );
     715             : 
     716           0 :   fd_sysvar_epoch_rewards_t epoch_rewards;
     717          63 :   if( FD_UNLIKELY( !fd_sysvar_cache_epoch_rewards_read( instr_ctx->sysvar_cache, &epoch_rewards ) ) ) {
     718           8 :     FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_out, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_out->err.exec_err_idx );
     719           8 :     return FD_VM_ERR_INVAL;
     720           8 :   }
     721             : 
     722          55 :   fd_vm_epoch_rewards_t * vm_epoch_rewards = (fd_vm_epoch_rewards_t *)out;
     723          55 :   *vm_epoch_rewards = (fd_vm_epoch_rewards_t){
     724          55 :     .distribution_starting_block_height = epoch_rewards.distribution_starting_block_height,
     725          55 :     .num_partitions                     = epoch_rewards.num_partitions,
     726          55 :     .parent_blockhash                   = epoch_rewards.parent_blockhash,
     727          55 :     .total_points                       = epoch_rewards.total_points,
     728          55 :     .total_rewards                      = epoch_rewards.total_rewards,
     729          55 :     .distributed_rewards                = epoch_rewards.distributed_rewards,
     730          55 :     .active                             = epoch_rewards.active,
     731          55 :   };
     732             : 
     733          55 :   vm->reg[0] = 0UL;
     734          55 :   return FD_VM_SUCCESS;
     735          63 : }

Generated by: LCOV version 1.14