LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_cpi.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 261 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 12 0.0 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : #include "../../../ballet/ed25519/fd_curve25519.h"
       3             : #include "../../../util/bits/fd_uwide.h"
       4             : #include "../../runtime/fd_borrowed_account.h"
       5             : #include "../../runtime/fd_executor.h"
       6             : #include <stdio.h>
       7             : 
       8             : /* FIXME: ALGO EFFICIENCY */
       9             : static inline int
      10             : fd_vm_syscall_cpi_is_signer( fd_pubkey_t const * account,
      11             :            fd_pubkey_t const * signers,
      12           0 :            ulong               signers_cnt ) {
      13           0 :   for( ulong i=0UL; i<signers_cnt; i++ ) if( !memcmp( account->uc, signers[i].uc, sizeof(fd_pubkey_t) ) ) return 1;
      14           0 :   return 0;
      15           0 : }
      16             : 
      17             : /*
      18             : fd_vm_prepare_instruction populates instruction_accounts and instruction_accounts_cnt
      19             : with the instruction accounts ready for execution.
      20             : 
      21             : The majority of this logic is taken from
      22             : https://github.com/solana-labs/solana/blob/v1.17.22/program-runtime/src/invoke_context.rs#L535,
      23             : and is not vm-specific, but a part of the runtime.
      24             : TODO: should we move this out of the CPI section?
      25             : 
      26             : The bulk of the logic is concerned with unifying the privileges for each duplicated account,
      27             : ensuring that each duplicate account referenced has the same privileges. It also performs some
      28             : priviledge checks, for example ensuring the necessary signatures are present.
      29             : 
      30             : TODO: instruction calling convention: const parameters after non-const.
      31             : 
      32             : Assumptions:
      33             : - We do not have more than 256 unique accounts in the callee_instr.
      34             :   This limit comes from the fact that a Solana transaction cannot
      35             :   refefence more than 256 unique accounts, due to the transaction
      36             :   serialization format.
      37             : - callee_instr is not null.
      38             : - callee_instr->acct_pubkeys is at least as long as callee_instr->acct_cnt
      39             : - instr_ctx->txn_ctx->accounts_cnt is less than UCHAR_MAX.
      40             :   This is likely because the transaction is limited to 256 accounts.
      41             : - callee_instr->program_id is set to UCHAR_MAX if account is not in instr_ctx->txn_ctx.
      42             : - instruction_accounts is a 256-length empty array.
      43             : 
      44             : Parameters:
      45             : - caller_instr
      46             : - callee_instr
      47             : - instr_ctx
      48             : - instruction_accounts
      49             : - instruction_accounts_cnt
      50             : - signers
      51             : - signers_cnt
      52             : 
      53             : Returns:
      54             : - instruction_accounts
      55             : - instruction_accounts_cnt
      56             : Populated with the instruction accounts with normalized permissions.
      57             : 
      58             : TODO: is it possible to pass the transaction indexes of the accounts in?
      59             : This would allow us to make some of these algorithms more efficient.
      60             : */
      61             : int
      62             : fd_vm_prepare_instruction( fd_instr_info_t const *  caller_instr,
      63             :                            fd_instr_info_t *        callee_instr,
      64             :                            fd_exec_instr_ctx_t *    instr_ctx,
      65             :                            fd_instruction_account_t instruction_accounts[256],
      66             :                            ulong *                  instruction_accounts_cnt,
      67             :                            fd_pubkey_t const *      signers,
      68           0 :                            ulong                    signers_cnt ) {
      69             : 
      70             :   /* De-duplicate the instruction accounts, using the same logic as Solana */
      71           0 :   ulong deduplicated_instruction_accounts_cnt = 0;
      72           0 :   fd_instruction_account_t deduplicated_instruction_accounts[256] = {0};
      73           0 :   ulong duplicate_indicies_cnt = 0;
      74           0 :   ulong duplicate_indices[256] = {0};
      75             : 
      76             :   /* Normalize the privileges of each instruction account in the callee, after de-duping
      77             :      the account references.
      78             :     https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/program-runtime/src/invoke_context.rs#L540-L595 */
      79           0 :   for( ulong i=0UL; i<callee_instr->acct_cnt; i++ ) {
      80           0 :     fd_pubkey_t const * callee_pubkey = &callee_instr->acct_pubkeys[i];
      81             : 
      82             :     /* Find the corresponding transaction account index for this callee instruction account */
      83             :     /* TODO: passing in the transaction indicies would mean we didn't have to do this */
      84           0 :     ushort index_in_transaction = USHORT_MAX;
      85           0 :     for( ulong j=0UL; j<instr_ctx->txn_ctx->accounts_cnt; j++ ) {
      86           0 :       if( !memcmp( instr_ctx->txn_ctx->account_keys[j].uc, callee_pubkey->uc, sizeof(fd_pubkey_t) ) ) {
      87           0 :         index_in_transaction = (ushort)j;
      88           0 :         break;
      89           0 :       }
      90           0 :     }
      91           0 :     if( index_in_transaction==USHORT_MAX) {
      92             :       /* In this case the callee instruction is referencing an unknown account not listed in the
      93             :          transactions accounts. */
      94           0 :       FD_BASE58_ENCODE_32_BYTES( callee_pubkey->uc, id_b58 );
      95           0 :       fd_log_collector_msg_many( instr_ctx, 2, "Instruction references an unknown account ", 42UL, id_b58, id_b58_len );
      96           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx );
      97           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
      98           0 :     }
      99             : 
     100             :     /* If there was an instruction account before this one which referenced the same
     101             :        transaction account index, find it's index in the deduplicated_instruction_accounts
     102             :        array. */
     103           0 :     ulong duplicate_index = ULONG_MAX;
     104           0 :     for( ulong j=0UL; j<deduplicated_instruction_accounts_cnt; j++ ) {
     105           0 :       if( deduplicated_instruction_accounts[j].index_in_transaction==index_in_transaction ) {
     106           0 :         duplicate_index = j;
     107           0 :         break;
     108           0 :       }
     109           0 :     }
     110             : 
     111             :     /* If this was account referenced in a previous iteration, update the flags to include those set
     112             :        in this iteration. This ensures that after all the iterations, the de-duplicated account flags
     113             :        for each account are the union of all the flags in all the references to that account in this instruction. */
     114             : 
     115             :     /* TODO: FD_UNLIKELY? Need to check which branch is more common by running against a larger mainnet ledger */
     116             :     /* TODO: this code would maybe be easier to read if we inverted the branches */
     117           0 :     if( duplicate_index!=ULONG_MAX ) {
     118           0 :       if ( FD_UNLIKELY( duplicate_index >= deduplicated_instruction_accounts_cnt ) ) {
     119           0 :         FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS, instr_ctx->txn_ctx->instr_err_idx );
     120           0 :         return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     121           0 :       }
     122             : 
     123           0 :       duplicate_indices[duplicate_indicies_cnt++] = duplicate_index;
     124           0 :       fd_instruction_account_t * instruction_account = &deduplicated_instruction_accounts[duplicate_index];
     125           0 :       instruction_account->is_signer   |= !!(callee_instr->acct_flags[i] & FD_INSTR_ACCT_FLAGS_IS_SIGNER);
     126           0 :       instruction_account->is_writable |= !!(callee_instr->acct_flags[i] & FD_INSTR_ACCT_FLAGS_IS_WRITABLE);
     127           0 :     } else {
     128             :       /* In the case where the callee instruction is NOT a duplicate, we need to
     129             :          create the deduplicated_instruction_accounts fd_instruction_account_t object. */
     130             : 
     131             :       /* Find the index of the instruction account in the caller instruction */
     132           0 :       ushort index_in_caller = USHORT_MAX;
     133           0 :       for( ulong j=0UL; j<caller_instr->acct_cnt; j++ ) {
     134             :         /* TODO: passing transaction indicies in would also allow us to remove these memcmp's */
     135           0 :         if( !memcmp( caller_instr->acct_pubkeys[j].uc, callee_instr->acct_pubkeys[i].uc, sizeof(fd_pubkey_t) ) ) {
     136           0 :           index_in_caller = (ushort)j;
     137           0 :           break;
     138           0 :         }
     139           0 :       }
     140           0 :       if( index_in_caller==USHORT_MAX ) {
     141           0 :         FD_BASE58_ENCODE_32_BYTES( callee_pubkey->uc, id_b58 );
     142           0 :         fd_log_collector_msg_many( instr_ctx, 2, "Instruction references an unknown account ", 42UL, id_b58, id_b58_len );
     143           0 :         FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx );
     144           0 :         return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     145           0 :       }
     146             : 
     147             :       /* Add the instruction account to the duplicate indicies array */
     148           0 :       duplicate_indices[duplicate_indicies_cnt++] = deduplicated_instruction_accounts_cnt;
     149             : 
     150             :       /* Initialize the instruction account in the deduplicated_instruction_accounts array */
     151           0 :       fd_instruction_account_t * instruction_account = &deduplicated_instruction_accounts[deduplicated_instruction_accounts_cnt++];
     152           0 :       instruction_account->index_in_callee      = (ushort)i;
     153           0 :       instruction_account->index_in_caller      = index_in_caller;
     154           0 :       instruction_account->index_in_transaction = index_in_transaction;
     155           0 :       instruction_account->is_signer            = !!(callee_instr->acct_flags[i] & FD_INSTR_ACCT_FLAGS_IS_SIGNER);
     156           0 :       instruction_account->is_writable          = !!(callee_instr->acct_flags[i] & FD_INSTR_ACCT_FLAGS_IS_WRITABLE);
     157           0 :     }
     158           0 :   }
     159             : 
     160             :   /* Check the normalized account permissions for privilege escalation.
     161             :      https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/program-runtime/src/invoke_context.rs#L596-L624 */
     162           0 :   for( ulong i = 0; i < deduplicated_instruction_accounts_cnt; i++ ) {
     163           0 :     fd_instruction_account_t * instruction_account = &deduplicated_instruction_accounts[i];
     164           0 :     fd_pubkey_t const * pubkey = &caller_instr->acct_pubkeys[instruction_account->index_in_caller];
     165             : 
     166             :     /* Check that the account is not read-only in the caller but writable in the callee */
     167           0 :     if( FD_UNLIKELY( instruction_account->is_writable && !fd_instr_acc_is_writable( instr_ctx->instr, pubkey ) ) ) {
     168           0 :       FD_BASE58_ENCODE_32_BYTES( pubkey->uc, id_b58 );
     169           0 :       fd_log_collector_msg_many( instr_ctx, 2, id_b58, id_b58_len, "'s writable privilege escalated", 31UL );
     170           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION, instr_ctx->txn_ctx->instr_err_idx );
     171           0 :       return FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION;
     172           0 :     }
     173             : 
     174             :     /* If the account is signed in the callee, it must be signed by the caller or the program */
     175           0 :     if ( FD_UNLIKELY( instruction_account->is_signer && !( fd_instr_acc_is_signer( instr_ctx->instr, pubkey ) || fd_vm_syscall_cpi_is_signer( pubkey, signers, signers_cnt) ) ) ) {
     176           0 :       FD_BASE58_ENCODE_32_BYTES( pubkey->uc, id_b58 );
     177           0 :       fd_log_collector_msg_many( instr_ctx, 2, id_b58, id_b58_len, "'s signer privilege escalated", 29UL );
     178           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION, instr_ctx->txn_ctx->instr_err_idx );
     179           0 :       return FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION;
     180           0 :     }
     181           0 :   }
     182             : 
     183             :   /* Copy the accounts with their normalized permissions over to the final instruction_accounts array,
     184             :      and set the callee_instr acct_flags. */
     185           0 :   for (ulong i = 0; i < duplicate_indicies_cnt; i++) {
     186           0 :     ulong duplicate_index = duplicate_indices[i];
     187             : 
     188             :     /* Failing this condition is technically impossible, but it is probably safest to keep this in
     189             :        so that we throw InstructionError::NotEnoughAccountKeys at the same point at Solana does,
     190             :        in the event any surrounding code is changed.
     191             :        https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/program-runtime/src/invoke_context.rs#L625-L633 */
     192           0 :     if ( FD_LIKELY( duplicate_index < deduplicated_instruction_accounts_cnt ) ) {
     193           0 :       instruction_accounts[i] = deduplicated_instruction_accounts[duplicate_index];
     194           0 :       callee_instr->acct_flags[i] = (uchar)
     195           0 :         ( ( callee_instr->acct_flags[i] ) |
     196           0 :           ( !!(instruction_accounts[i].is_writable) * FD_INSTR_ACCT_FLAGS_IS_WRITABLE ) |
     197           0 :           ( !!(instruction_accounts[i].is_signer  ) * FD_INSTR_ACCT_FLAGS_IS_SIGNER   ) );
     198           0 :     } else {
     199           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS, instr_ctx->txn_ctx->instr_err_idx );
     200           0 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     201           0 :     }
     202           0 :   }
     203             : 
     204           0 :   if( FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, instr_ctx->txn_ctx->features, lift_cpi_caller_restriction ) ) {
     205           0 :     if( FD_UNLIKELY( -1==fd_exec_txn_ctx_find_idx_of_program_account( instr_ctx->txn_ctx, &callee_instr->program_id_pubkey ) ) ) {
     206           0 :       FD_BASE58_ENCODE_32_BYTES( callee_instr->program_id_pubkey.uc, id_b58 );
     207           0 :       fd_log_collector_msg_many( instr_ctx, 2, "Unknown program ", 16UL, id_b58, id_b58_len );
     208           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx );
     209           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     210           0 :     }
     211           0 :   } else {
     212             :     /* Obtain the program account index and return a MissingAccount error if not found.
     213             :        https://github.com/anza-xyz/agave/blob/v2.1.14/program-runtime/src/invoke_context.rs#L430-L435 */
     214           0 :     int program_idx = fd_exec_instr_ctx_find_idx_of_instr_account( instr_ctx, &callee_instr->program_id_pubkey );
     215           0 :     if( FD_UNLIKELY( program_idx == -1 ) ) {
     216           0 :       FD_BASE58_ENCODE_32_BYTES( callee_instr->program_id_pubkey.uc, id_b58 );
     217           0 :       fd_log_collector_msg_many( instr_ctx, 2, "Unknown program ", 16UL, id_b58, id_b58_len );
     218           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx );
     219           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     220           0 :     }
     221             : 
     222             :     /* Caller is in charge of setting an appropriate sentinel value (i.e., UCHAR_MAX) for callee_instr->program_id if not found.
     223             :        Borrow the program account here.
     224             :        https://github.com/anza-xyz/agave/blob/v2.1.14/program-runtime/src/invoke_context.rs#L436-L437 */
     225           0 :     fd_guarded_borrowed_account_t borrowed_program_account;
     226           0 :     int err = fd_exec_instr_ctx_try_borrow_account( instr_ctx, (ulong)program_idx, &borrowed_program_account );
     227           0 :     if( FD_UNLIKELY( err ) ) {
     228           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, err, instr_ctx->txn_ctx->instr_err_idx );
     229           0 :       return err;
     230           0 :     }
     231             : 
     232           0 :     if( FD_UNLIKELY( err ) ) {
     233             :       /* https://github.com/anza-xyz/agave/blob/a9ac3f55fcb2bc735db0d251eda89897a5dbaaaa/program-runtime/src/invoke_context.rs#L434 */
     234           0 :       FD_BASE58_ENCODE_32_BYTES( callee_instr->program_id_pubkey.uc, id_b58 );
     235           0 :       fd_log_collector_msg_many( instr_ctx, 2, "Unknown program ", 16UL, id_b58, id_b58_len );
     236           0 :       FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx );
     237           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     238           0 :     }
     239             :     /* Check that the program account is executable. We need to ensure that the
     240             :        program account is a valid instruction account.
     241             :        https://github.com/anza-xyz/agave/blob/v2.1.14/program-runtime/src/invoke_context.rs#L438 */
     242           0 :     if( !FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, instr_ctx->txn_ctx->features, remove_accounts_executable_flag_checks ) ) {
     243           0 :       if( FD_UNLIKELY( !fd_borrowed_account_is_executable( &borrowed_program_account ) ) ) {
     244           0 :         FD_BASE58_ENCODE_32_BYTES( callee_instr->program_id_pubkey.uc, id_b58 );
     245           0 :         fd_log_collector_msg_many( instr_ctx, 3, "Account ", 8UL, id_b58, id_b58_len, " is not executable", 18UL );
     246           0 :         FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE, instr_ctx->txn_ctx->instr_err_idx );
     247           0 :         return FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE;
     248           0 :       }
     249           0 :     }
     250           0 :   }
     251             : 
     252           0 :   *instruction_accounts_cnt = duplicate_indicies_cnt;
     253             : 
     254           0 :   return 0;
     255           0 : }
     256             : 
     257             : /**********************************************************************
     258             :    CROSS PROGRAM INVOCATION (Generic logic)
     259             :  **********************************************************************/
     260             : 
     261             : /* FD_CPI_MAX_SIGNER_CNT is the max amount of PDA signer addresses that
     262             :    a cross-program invocation can include in an instruction.
     263             : 
     264             :    https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/programs/bpf_loader/src/syscalls/mod.rs#L80 */
     265             : 
     266             : #define FD_CPI_MAX_SIGNER_CNT              (16UL)
     267             : 
     268             : /* "Maximum number of account info structs that can be used in a single CPI
     269             :    invocation. A limit on account info structs is effectively the same as
     270             :    limiting the number of unique accounts. 128 was chosen to match the max
     271             :    number of locked accounts per transaction (MAX_TX_ACCOUNT_LOCKS)."
     272             : 
     273             :    https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/sdk/program/src/syscalls/mod.rs#L25
     274             :    https://github.com/anza-xyz/agave/blob/838c1952595809a31520ff1603a13f2c9123aa51/programs/bpf_loader/src/syscalls/cpi.rs#L1011 */
     275             : 
     276           0 : #define FD_CPI_MAX_ACCOUNT_INFOS           (128UL)
     277             : /* This is just encoding what Agave says in their code comments into a
     278             :    compile-time check, so if anyone ever inadvertently changes one of
     279             :    the limits, they will have to take a look. */
     280             : FD_STATIC_ASSERT( FD_CPI_MAX_ACCOUNT_INFOS==MAX_TX_ACCOUNT_LOCKS, cpi_max_account_info );
     281             : static inline ulong
     282           0 : get_cpi_max_account_infos( fd_exec_txn_ctx_t const * txn_ctx ) {
     283           0 :   return fd_ulong_if( FD_FEATURE_ACTIVE( txn_ctx->slot, txn_ctx->features, increase_tx_account_lock_limit ), FD_CPI_MAX_ACCOUNT_INFOS, 64UL );
     284           0 : }
     285             : 
     286             : /* Maximum CPI instruction data size. 10 KiB was chosen to ensure that CPI
     287             :    instructions are not more limited than transaction instructions if the size
     288             :    of transactions is doubled in the future.
     289             : 
     290             :    https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/sdk/program/src/syscalls/mod.rs#L14 */
     291             : 
     292             : #define FD_CPI_MAX_INSTRUCTION_DATA_LEN    (10240UL)
     293             : 
     294             : /* Maximum CPI instruction accounts. 255 was chosen to ensure that instruction
     295             :    accounts are always within the maximum instruction account limit for BPF
     296             :    program instructions.
     297             : 
     298             :    https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/sdk/program/src/syscalls/mod.rs#L19
     299             :    https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/programs/bpf_loader/src/serialization.rs#L26 */
     300             : 
     301             : #define FD_CPI_MAX_INSTRUCTION_ACCOUNTS    (255UL)
     302             : 
     303             : 
     304             : /* fd_vm_syscall_cpi_check_instruction contains common instruction acct
     305             :    count and data sz checks.  Also consumes compute units proportional
     306             :    to instruction data size. */
     307             : 
     308             : static int
     309             : fd_vm_syscall_cpi_check_instruction( fd_vm_t const * vm,
     310             :                                      ulong           acct_cnt,
     311           0 :                                      ulong           data_sz ) {
     312             :   /* https://github.com/solana-labs/solana/blob/eb35a5ac1e7b6abe81947e22417f34508f89f091/programs/bpf_loader/src/syscalls/cpi.rs#L958-L959 */
     313           0 :   if( FD_FEATURE_ACTIVE( vm->instr_ctx->txn_ctx->slot, vm->instr_ctx->txn_ctx->features, loosen_cpi_size_restriction ) ) {
     314           0 :     if( FD_UNLIKELY( data_sz > FD_CPI_MAX_INSTRUCTION_DATA_LEN ) ) {
     315           0 :       FD_LOG_WARNING(( "cpi: data too long (%#lx)", data_sz ));
     316             :       // SyscallError::MaxInstructionDataLenExceeded
     317           0 :       return FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_DATA_LEN_EXCEEDED;
     318           0 :     }
     319           0 :     if( FD_UNLIKELY( acct_cnt > FD_CPI_MAX_INSTRUCTION_ACCOUNTS ) ) {
     320           0 :       FD_LOG_WARNING(( "cpi: too many accounts (%#lx)", acct_cnt ));
     321             :       // SyscallError::MaxInstructionAccountsExceeded
     322           0 :       return FD_VM_SYSCALL_ERR_MAX_INSTRUCTION_ACCOUNTS_EXCEEDED;
     323           0 :     }
     324           0 :   } else {
     325             :     // https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/programs/bpf_loader/src/syscalls/cpi.rs#L1114
     326           0 :     ulong tot_sz = fd_ulong_sat_add( fd_ulong_sat_mul( FD_VM_RUST_ACCOUNT_META_SIZE, acct_cnt ), data_sz );
     327           0 :     if ( FD_UNLIKELY( tot_sz > FD_VM_MAX_CPI_INSTRUCTION_SIZE ) ) {
     328           0 :       FD_LOG_WARNING(( "cpi: instruction too long (%#lx)", tot_sz ));
     329             :       // SyscallError::InstructionTooLarge
     330           0 :       return FD_VM_SYSCALL_ERR_INSTRUCTION_TOO_LARGE;
     331           0 :     }
     332           0 :   }
     333             : 
     334           0 :   return FD_VM_SUCCESS;
     335           0 : }
     336             : 
     337             : /**********************************************************************
     338             :   CROSS PROGRAM INVOCATION HELPERS
     339             :  **********************************************************************/
     340             : 
     341             : static inline int
     342             : fd_vm_syscall_cpi_check_id( fd_pubkey_t const * program_id,
     343           0 :           uchar const * loader ) {
     344           0 :   return !memcmp( program_id, loader, sizeof(fd_pubkey_t) );
     345           0 : }
     346             : 
     347             : /* fd_vm_syscall_cpi_is_precompile returns true if the given program_id
     348             :    corresponds to a precompile. It does this by checking against a hardcoded
     349             :    list of known pre-compiles.
     350             : 
     351             :    This mirrors the behaviour in solana_sdk::precompiles::is_precompile
     352             :    https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/sdk/src/precompiles.rs#L93
     353             :  */
     354             : static inline int
     355           0 : fd_vm_syscall_cpi_is_precompile( fd_pubkey_t const * program_id, fd_exec_txn_ctx_t const * txn_ctx ) {
     356           0 :   return fd_vm_syscall_cpi_check_id(program_id, fd_solana_keccak_secp_256k_program_id.key) |
     357           0 :          fd_vm_syscall_cpi_check_id(program_id, fd_solana_ed25519_sig_verify_program_id.key) |
     358           0 :          ( fd_vm_syscall_cpi_check_id(program_id, fd_solana_secp256r1_program_id.key) &&
     359           0 :            FD_FEATURE_ACTIVE( txn_ctx->slot, txn_ctx->features, enable_secp256r1_precompile ) );
     360           0 : }
     361             : 
     362             : /* fd_vm_syscall_cpi_check_authorized_program corresponds to
     363             : solana_bpf_loader_program::syscalls::cpi::check_authorized_program:
     364             : https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/programs/bpf_loader/src/syscalls/cpi.rs#L1032
     365             : 
     366             : It determines if the given program_id is authorized to execute a CPI call.
     367             : 
     368             : FIXME: return type
     369             :  */
     370             : static inline ulong
     371             : fd_vm_syscall_cpi_check_authorized_program( fd_pubkey_t const *       program_id,
     372             :                                             fd_exec_txn_ctx_t const * txn_ctx,
     373             :                                             uchar const *             instruction_data,
     374           0 :                                             ulong                     instruction_data_len ) {
     375             :   /* FIXME: do this in a branchless manner? using bitwise comparison would probably be faster */
     376           0 :   return ( fd_vm_syscall_cpi_check_id(program_id, fd_solana_native_loader_id.key)
     377           0 :             || fd_vm_syscall_cpi_check_id(program_id, fd_solana_bpf_loader_program_id.key)
     378           0 :             || fd_vm_syscall_cpi_check_id(program_id, fd_solana_bpf_loader_deprecated_program_id.key)
     379           0 :             || (fd_vm_syscall_cpi_check_id(program_id, fd_solana_bpf_loader_upgradeable_program_id.key)
     380           0 :                 && !((instruction_data_len != 0 && instruction_data[0] == 3)  /* is_upgrade_instruction() */
     381           0 :                     || (instruction_data_len != 0 && instruction_data[0] == 4)  /* is_set_authority_instruction() */
     382           0 :                     || (FD_FEATURE_ACTIVE( txn_ctx->slot, txn_ctx->features, enable_bpf_loader_set_authority_checked_ix )
     383           0 :                         && (instruction_data_len != 0 && instruction_data[0] == 7)) /* is_set_authority_checked_instruction() */
     384           0 :                     || (instruction_data_len != 0 && instruction_data[0] == 5))) /* is_close_instruction */
     385           0 :             || fd_vm_syscall_cpi_is_precompile( program_id, txn_ctx ) );
     386           0 : }
     387             : 
     388             : /* Helper functions to get the absolute vaddrs of the serialized accounts pubkey, lamports and owner.
     389             : 
     390             :    For the accounts not owned by the deprecated loader, all of these offsets into the accounts metadata region
     391             :    are static from fd_vm_acc_region_meta->metadata_region_offset.
     392             : 
     393             :    For accounts owned by the deprecated loader, the unaligned serializer is used, which means only the pubkey
     394             :    and lamports offsets are static from the metadata_region_offset. The owner is serialized into the region
     395             :    immediately following the account data region (if present) at a fixed offset.
     396             :  */
     397           0 : #define VM_SERIALIZED_PUBKEY_OFFSET   (8UL)
     398           0 : #define VM_SERIALIZED_OWNER_OFFSET    (40UL)
     399           0 : #define VM_SERIALIZED_LAMPORTS_OFFSET (72UL)
     400             : 
     401           0 : #define VM_SERIALIZED_UNALIGNED_PUBKEY_OFFSET   (3UL)
     402           0 : #define VM_SERIALIZED_UNALIGNED_LAMPORTS_OFFSET (35UL)
     403             : 
     404             : static inline
     405           0 : ulong serialized_pubkey_vaddr( fd_vm_t * vm, fd_vm_acc_region_meta_t * acc_region_meta ) {
     406           0 :   return FD_VM_MEM_MAP_INPUT_REGION_START + acc_region_meta->metadata_region_offset +
     407           0 :     (vm->is_deprecated ? VM_SERIALIZED_UNALIGNED_PUBKEY_OFFSET : VM_SERIALIZED_PUBKEY_OFFSET);
     408           0 : }
     409             : 
     410             : static inline
     411           0 : ulong serialized_owner_vaddr( fd_vm_t * vm, fd_vm_acc_region_meta_t * acc_region_meta ) {
     412           0 :   if ( vm->is_deprecated ) {
     413             :     /* For deprecated loader programs, the owner is serialized into the start of the region
     414             :        following the account data region (if present) at a fixed offset.
     415             :        If the account data region is not present, the owner is
     416             :        serialized into the same fixed offset following the account's
     417             :        metadata region.
     418             :      */
     419           0 :     return FD_VM_MEM_MAP_INPUT_REGION_START + vm->input_mem_regions[
     420           0 :       acc_region_meta->has_data_region ? acc_region_meta->region_idx+1U : acc_region_meta->region_idx
     421           0 :     ].vaddr_offset;
     422           0 :   }
     423             : 
     424           0 :   return FD_VM_MEM_MAP_INPUT_REGION_START + acc_region_meta->metadata_region_offset + VM_SERIALIZED_OWNER_OFFSET;
     425           0 : }
     426             : 
     427             : static inline
     428           0 : ulong serialized_lamports_vaddr( fd_vm_t * vm, fd_vm_acc_region_meta_t * acc_region_meta ) {
     429           0 :   return FD_VM_MEM_MAP_INPUT_REGION_START + acc_region_meta->metadata_region_offset +
     430           0 :     (vm->is_deprecated ? VM_SERIALIZED_UNALIGNED_LAMPORTS_OFFSET : VM_SERIALIZED_LAMPORTS_OFFSET);
     431           0 : }
     432             : 
     433             : /* The data and lamports fields are in an Rc<Refcell<T>> in the Rust ABI AccountInfo.
     434             :    These macros perform the equivalent of Rc<Refcell<T>>.as_ptr() in Agave.
     435             :    This function doesn't actually touch any memory.
     436             :    It performs pointer arithmetic.
     437             :  */
     438             : FD_FN_CONST static inline
     439           0 : ulong vm_syscall_cpi_acc_info_rc_refcell_as_ptr( ulong rc_refcell_vaddr ) {
     440           0 :   return (ulong) &(((fd_vm_rc_refcell_t *)rc_refcell_vaddr)->payload);
     441           0 : }
     442             : 
     443             : /* https://github.com/anza-xyz/agave/blob/v2.1.6/programs/bpf_loader/src/syscalls/cpi.rs#L327
     444             :  */
     445             : FD_FN_CONST static inline
     446           0 : ulong vm_syscall_cpi_data_len_vaddr_c( ulong acct_info_vaddr, ulong data_len_haddr, ulong acct_info_haddr ) {
     447           0 :   return fd_ulong_sat_sub( fd_ulong_sat_add( acct_info_vaddr, data_len_haddr ), acct_info_haddr );
     448           0 : }
     449             : 
     450             : /**********************************************************************
     451             :   CROSS PROGRAM INVOCATION (C ABI)
     452             :  **********************************************************************/
     453             : 
     454             : #define VM_SYSCALL_CPI_ABI                     c
     455           0 : #define VM_SYSCALL_CPI_INSTR_T                 fd_vm_c_instruction_t
     456             : #define VM_SYSCALL_CPI_INSTR_ALIGN             (FD_VM_C_INSTRUCTION_ALIGN)
     457             : #define VM_SYSCALL_CPI_INSTR_SIZE              (FD_VM_C_INSTRUCTION_SIZE)
     458           0 : #define VM_SYSCALL_CPI_ACC_META_T              fd_vm_c_account_meta_t
     459             : #define VM_SYSCALL_CPI_ACC_META_ALIGN          (FD_VM_C_ACCOUNT_META_ALIGN)
     460             : #define VM_SYSCALL_CPI_ACC_META_SIZE           (FD_VM_C_ACCOUNT_META_SIZE)
     461           0 : #define VM_SYSCALL_CPI_ACC_INFO_T              fd_vm_c_account_info_t
     462             : #define VM_SYSCALL_CPI_ACC_INFO_ALIGN          (FD_VM_C_ACCOUNT_INFO_ALIGN)
     463           0 : #define VM_SYSCALL_CPI_ACC_INFO_SIZE           (FD_VM_C_ACCOUNT_INFO_SIZE)
     464             : 
     465             : /* VM_SYSCALL_CPI_INSTR_T accessors */
     466             : #define VM_SYSCALL_CPI_INSTR_DATA_ADDR( instr ) instr->data_addr
     467           0 : #define VM_SYSCALL_CPI_INSTR_DATA_LEN( instr )  instr->data_len
     468             : #define VM_SYSCALL_CPI_INSTR_ACCS_ADDR( instr ) instr->accounts_addr
     469           0 : #define VM_SYSCALL_CPI_INSTR_ACCS_LEN( instr )  instr->accounts_len
     470             : #define VM_SYSCALL_CPI_INSTR_PROGRAM_ID( vm, instr ) \
     471           0 :   FD_VM_MEM_HADDR_LD( vm, instr->program_id_addr, alignof(uchar), sizeof(fd_pubkey_t)  )
     472             : 
     473             : /* VM_SYSCALL_CPI_ACC_META_T accessors */
     474           0 : #define VM_SYSCALL_CPI_ACC_META_IS_WRITABLE( acc_meta ) acc_meta->is_writable
     475           0 : #define VM_SYSCALL_CPI_ACC_META_IS_SIGNER( acc_meta ) acc_meta->is_signer
     476             : #define VM_SYSCALL_CPI_ACC_META_PUBKEY( vm, acc_meta ) \
     477           0 :   FD_VM_MEM_HADDR_LD( vm, acc_meta->pubkey_addr, alignof(uchar), sizeof(fd_pubkey_t) )
     478             : 
     479             : /* VM_SYSCALL_CPI_ACC_INFO_T accessors */
     480             : #define VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_VADDR( vm, acc_info, decl ) \
     481           0 :   ulong decl = acc_info->lamports_addr;
     482             : #define VM_SYSCALL_CPI_ACC_INFO_LAMPORTS( vm, acc_info, decl ) \
     483           0 :   ulong * decl = FD_VM_MEM_HADDR_ST( vm, acc_info->lamports_addr, alignof(ulong), sizeof(ulong) );
     484             : 
     485             : #define VM_SYSCALL_CPI_ACC_INFO_DATA_VADDR( vm, acc_info, decl ) \
     486           0 :   ulong decl = acc_info->data_addr;
     487             : #define VM_SYSCALL_CPI_ACC_INFO_DATA( vm, acc_info, decl ) \
     488           0 :   uchar * decl = FD_VM_MEM_HADDR_ST( vm, acc_info->data_addr, alignof(uchar), acc_info->data_sz ); \
     489           0 :   ulong FD_EXPAND_THEN_CONCAT2(decl, _vm_addr) = acc_info->data_addr; \
     490           0 :   ulong FD_EXPAND_THEN_CONCAT2(decl, _len) = acc_info->data_sz;
     491             : 
     492             : #define VM_SYSCALL_CPI_ACC_INFO_METADATA( vm, acc_info, decl ) \
     493           0 :   ulong FD_EXPAND_THEN_CONCAT2(decl, _vm_addr) = acc_info->data_addr; \
     494           0 :   ulong FD_EXPAND_THEN_CONCAT2(decl, _len) = acc_info->data_sz;
     495             : 
     496             : #define VM_SYSCALL_CPI_SET_ACC_INFO_DATA_GET_LEN( vm, acc_info, decl ) \
     497           0 :   ulong FD_EXPAND_THEN_CONCAT2(decl, _len) = acc_info->data_sz;
     498             : 
     499             : #include "fd_vm_syscall_cpi_common.c"
     500             : 
     501             : #undef VM_SYSCALL_CPI_ABI
     502             : #undef VM_SYSCALL_CPI_INSTR_T
     503             : #undef VM_SYSCALL_CPI_INSTR_ALIGN
     504             : #undef VM_SYSCALL_CPI_INSTR_SIZE
     505             : #undef VM_SYSCALL_CPI_ACC_META_T
     506             : #undef VM_SYSCALL_CPI_ACC_META_ALIGN
     507             : #undef VM_SYSCALL_CPI_ACC_META_SIZE
     508             : #undef VM_SYSCALL_CPI_ACC_INFO_T
     509             : #undef VM_SYSCALL_CPI_ACC_INFO_ALIGN
     510             : #undef VM_SYSCALL_CPI_ACC_INFO_SIZE
     511             : #undef VM_SYSCALL_CPI_INSTR_DATA_ADDR
     512             : #undef VM_SYSCALL_CPI_INSTR_DATA_LEN
     513             : #undef VM_SYSCALL_CPI_INSTR_ACCS_ADDR
     514             : #undef VM_SYSCALL_CPI_INSTR_ACCS_LEN
     515             : #undef VM_SYSCALL_CPI_INSTR_PROGRAM_ID
     516             : #undef VM_SYSCALL_CPI_ACC_META_IS_WRITABLE
     517             : #undef VM_SYSCALL_CPI_ACC_META_IS_SIGNER
     518             : #undef VM_SYSCALL_CPI_ACC_META_PUBKEY
     519             : #undef VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_VADDR
     520             : #undef VM_SYSCALL_CPI_ACC_INFO_LAMPORTS
     521             : #undef VM_SYSCALL_CPI_ACC_INFO_DATA_VADDR
     522             : #undef VM_SYSCALL_CPI_ACC_INFO_DATA
     523             : #undef VM_SYSCALL_CPI_ACC_INFO_METADATA
     524             : #undef VM_SYSCALL_CPI_SET_ACC_INFO_DATA_GET_LEN
     525             : 
     526             : /**********************************************************************
     527             :    CROSS PROGRAM INVOCATION (Rust ABI)
     528             :  **********************************************************************/
     529             : 
     530             : #define VM_SYSCALL_CPI_ABI                     rust
     531           0 : #define VM_SYSCALL_CPI_INSTR_T                 fd_vm_rust_instruction_t
     532             : #define VM_SYSCALL_CPI_INSTR_ALIGN             (FD_VM_RUST_INSTRUCTION_ALIGN)
     533             : #define VM_SYSCALL_CPI_INSTR_SIZE              (FD_VM_RUST_INSTRUCTION_SIZE)
     534           0 : #define VM_SYSCALL_CPI_ACC_META_T              fd_vm_rust_account_meta_t
     535             : #define VM_SYSCALL_CPI_ACC_META_ALIGN          (FD_VM_RUST_ACCOUNT_META_ALIGN)
     536             : #define VM_SYSCALL_CPI_ACC_META_SIZE           (FD_VM_RUST_ACCOUNT_META_SIZE)
     537           0 : #define VM_SYSCALL_CPI_ACC_INFO_T              fd_vm_rust_account_info_t
     538             : #define VM_SYSCALL_CPI_ACC_INFO_ALIGN          (FD_VM_RUST_ACCOUNT_INFO_ALIGN)
     539           0 : #define VM_SYSCALL_CPI_ACC_INFO_SIZE           (FD_VM_RUST_ACCOUNT_INFO_SIZE)
     540             : 
     541             : /* VM_SYSCALL_CPI_INSTR_T accessors */
     542             : #define VM_SYSCALL_CPI_INSTR_DATA_ADDR( instr ) instr->data.addr
     543           0 : #define VM_SYSCALL_CPI_INSTR_DATA_LEN( instr )  instr->data.len
     544             : #define VM_SYSCALL_CPI_INSTR_ACCS_ADDR( instr ) instr->accounts.addr
     545           0 : #define VM_SYSCALL_CPI_INSTR_ACCS_LEN( instr )  instr->accounts.len
     546           0 : #define VM_SYSCALL_CPI_INSTR_PROGRAM_ID( vm, instr ) instr->pubkey
     547             : 
     548             : /* VM_SYSCALL_CPI_ACC_META_T accessors */
     549           0 : #define VM_SYSCALL_CPI_ACC_META_IS_WRITABLE( acc_meta ) acc_meta->is_writable
     550           0 : #define VM_SYSCALL_CPI_ACC_META_IS_SIGNER( acc_meta ) acc_meta->is_signer
     551           0 : #define VM_SYSCALL_CPI_ACC_META_PUBKEY( vm, acc_meta ) acc_meta->pubkey
     552             : 
     553             : /* VM_SYSCALL_CPI_ACC_INFO_T accessors */
     554             : 
     555             : /* The lamports and the account data are stored behind RefCells,
     556             :    so we have an additional layer of indirection to unwrap. */
     557             : #define VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_VADDR( vm, acc_info, decl )                                                                             \
     558           0 :     ulong const * FD_EXPAND_THEN_CONCAT2(decl, _hptr_) =                                                                                         \
     559           0 :       FD_VM_MEM_HADDR_LD( vm, vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->lamports_box_addr ), FD_VM_RC_REFCELL_ALIGN, sizeof(ulong) ); \
     560           0 :     /* Extract the vaddr embedded in the RefCell */                                                                                              \
     561           0 :     ulong decl = *FD_EXPAND_THEN_CONCAT2(decl, _hptr_);
     562             : 
     563             : #define VM_SYSCALL_CPI_ACC_INFO_LAMPORTS( vm, acc_info, decl )                                                                                                     \
     564           0 :     ulong FD_EXPAND_THEN_CONCAT2(decl, _vaddr_) =                                                                                                                  \
     565           0 :       *((ulong const *)FD_VM_MEM_HADDR_LD( vm, vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->lamports_box_addr ), FD_VM_RC_REFCELL_ALIGN, sizeof(ulong) )); \
     566           0 :     ulong * decl = FD_VM_MEM_HADDR_ST( vm, FD_EXPAND_THEN_CONCAT2(decl, _vaddr_), alignof(ulong), sizeof(ulong) );
     567             : 
     568             : #define VM_SYSCALL_CPI_ACC_INFO_DATA_VADDR( vm, acc_info, decl )                                                                                   \
     569             :     /* Translate the vaddr to the slice */                                                                                                         \
     570           0 :     fd_vm_vec_t const * FD_EXPAND_THEN_CONCAT2(decl, _hptr_) =                                                                                     \
     571           0 :       FD_VM_MEM_HADDR_LD( vm, vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->data_box_addr ), FD_VM_RC_REFCELL_ALIGN, sizeof(fd_vm_vec_t) ); \
     572           0 :     /* Extract the vaddr embedded in the slice */                                                                                                  \
     573           0 :     ulong decl = FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->addr;
     574             : 
     575             : #define VM_SYSCALL_CPI_ACC_INFO_DATA_LEN_VADDR( vm, acc_info, decl ) \
     576           0 :     ulong decl = fd_ulong_sat_add( vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->data_box_addr ), sizeof(ulong) );
     577             : 
     578             : #define VM_SYSCALL_CPI_ACC_INFO_DATA( vm, acc_info, decl )                                                                                         \
     579             :     /* Translate the vaddr to the slice */                                                                                                         \
     580           0 :     fd_vm_vec_t const * FD_EXPAND_THEN_CONCAT2(decl, _hptr_) =                                                                                     \
     581           0 :       FD_VM_MEM_HADDR_LD( vm, vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->data_box_addr ), FD_VM_RC_REFCELL_ALIGN, sizeof(fd_vm_vec_t) ); \
     582           0 :     /* Declare the vaddr of the slice's underlying byte array */                                                                                   \
     583           0 :     ulong FD_EXPAND_THEN_CONCAT2(decl, _vm_addr) = FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->addr;                                                     \
     584           0 :     /* Declare the size of the slice's underlying byte array */                                                                                    \
     585           0 :     ulong FD_EXPAND_THEN_CONCAT2(decl, _len) = FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->len;                                                          \
     586           0 :     /* Translate the vaddr to the underlying byte array */                                                                                         \
     587           0 :     uchar * decl = FD_VM_MEM_SLICE_HADDR_ST(                                                                                                       \
     588           0 :       vm, FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->addr, alignof(uchar), FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->len );
     589             : 
     590             : #define VM_SYSCALL_CPI_ACC_INFO_METADATA( vm, acc_info, decl )                                                                                     \
     591             :     /* Translate the vaddr to the slice */                                                                                                         \
     592           0 :     fd_vm_vec_t const * FD_EXPAND_THEN_CONCAT2(decl, _hptr_) =                                                                                     \
     593           0 :       FD_VM_MEM_HADDR_LD( vm, vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->data_box_addr ), FD_VM_RC_REFCELL_ALIGN, sizeof(fd_vm_vec_t) ); \
     594           0 :     /* Declare the vaddr of the slice's underlying byte array */                                                                                   \
     595           0 :     ulong FD_EXPAND_THEN_CONCAT2(decl, _vm_addr) = FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->addr;                                                     \
     596           0 :     /* Declare the size of the slice's underlying byte array */                                                                                    \
     597           0 :     ulong FD_EXPAND_THEN_CONCAT2(decl, _len) = FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->len;
     598             : 
     599             : #define VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_RC_REFCELL_VADDR( vm, acc_info, decl ) \
     600           0 :     ulong decl = vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->lamports_box_addr );
     601             : 
     602             : #define VM_SYSCALL_CPI_ACC_INFO_DATA_RC_REFCELL_VADDR( vm, acc_info, decl ) \
     603           0 :     ulong decl = vm_syscall_cpi_acc_info_rc_refcell_as_ptr( acc_info->data_box_addr );
     604             : 
     605             : #define VM_SYSCALL_CPI_SET_ACC_INFO_DATA_GET_LEN( vm, acc_info, decl ) \
     606           0 :   ulong FD_EXPAND_THEN_CONCAT2(decl, _len) = FD_EXPAND_THEN_CONCAT2(decl, _hptr_)->len;
     607             : 
     608             : #include "fd_vm_syscall_cpi_common.c"
     609             : 
     610             : #undef VM_SYSCALL_CPI_ABI
     611             : #undef VM_SYSCALL_CPI_INSTR_T
     612             : #undef VM_SYSCALL_CPI_INSTR_ALIGN
     613             : #undef VM_SYSCALL_CPI_INSTR_SIZE
     614             : #undef VM_SYSCALL_CPI_ACC_META_T
     615             : #undef VM_SYSCALL_CPI_ACC_META_ALIGN
     616             : #undef VM_SYSCALL_CPI_ACC_META_SIZE
     617             : #undef VM_SYSCALL_CPI_ACC_INFO_T
     618             : #undef VM_SYSCALL_CPI_ACC_INFO_ALIGN
     619             : #undef VM_SYSCALL_CPI_ACC_INFO_SIZE
     620             : #undef VM_SYSCALL_CPI_INSTR_DATA_ADDR
     621             : #undef VM_SYSCALL_CPI_INSTR_DATA_LEN
     622             : #undef VM_SYSCALL_CPI_INSTR_ACCS_ADDR
     623             : #undef VM_SYSCALL_CPI_INSTR_ACCS_LEN
     624             : #undef VM_SYSCALL_CPI_INSTR_PROGRAM_ID
     625             : #undef VM_SYSCALL_CPI_ACC_META_IS_WRITABLE
     626             : #undef VM_SYSCALL_CPI_ACC_META_IS_SIGNER
     627             : #undef VM_SYSCALL_CPI_ACC_META_PUBKEY
     628             : #undef VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_VADDR
     629             : #undef VM_SYSCALL_CPI_ACC_INFO_LAMPORTS
     630             : #undef VM_SYSCALL_CPI_ACC_INFO_DATA_VADDR
     631             : #undef VM_SYSCALL_CPI_ACC_INFO_DATA
     632             : #undef VM_SYSCALL_CPI_ACC_INFO_DATA_LEN_VADDR
     633             : #undef VM_SYSCALL_CPI_ACC_INFO_METADATA
     634             : #undef VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_RC_REFCELL_VADDR
     635             : #undef VM_SYSCALL_CPI_ACC_INFO_DATA_RC_REFCELL_VADDR
     636             : #undef VM_SYSCALL_CPI_SET_ACC_INFO_DATA_GET_LEN

Generated by: LCOV version 1.14