LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_account.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 93 153 60.8 %
Date: 2025-01-08 12:08:44 Functions: 39 408 9.6 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_fd_account_h
       2             : #define HEADER_fd_src_flamenco_runtime_fd_account_h
       3             : 
       4             : /* fd_account.h contains safe API helpers for accounts.
       5             : 
       6             :    ### Account Existence
       7             : 
       8             :    "Does an account exist?" is not trivial to answer.  We can instead
       9             :    look at qualifiers:
      10             : 
      11             :      A: Does a database record exist?
      12             :      B: Is the native (lamport) balance greater than zero?
      13             :      C: Is the account "dead"?
      14             : 
      15             :    From the on-chain program's perspective, even addresses that have
      16             :    never been interacted with can be read.  That account would show up
      17             :    as zero balance, zero owner (system program), and has no data.  This
      18             :    means, logically, for all possible 2^256 account addresses, it
      19             :    appears that an account exists.  We call such accounts "dead"
      20             :    accounts (C).
      21             : 
      22             :    C also implies B.  There are may be intermediate account states
      23             :    however where an account has zero balance, but is still owned by a
      24             :    program.  Thus, B does not necessarily imply C.
      25             : 
      26             :    Obviously, we only have finite database space.  Whenever an account
      27             :    becomes dead, we try to free the record.  If no funk record for
      28             :    an account exists (C), it is dead (A).  This doesn't always work, so
      29             :    sometimes there is a leftover record containing a dead account.
      30             :    (Also called a "tombstone")
      31             : 
      32             :    For the on-chain program developer this means:  DO NOT assume a funk
      33             :    record exists for all accounts.  DO NOT look at the funk record
      34             :    pointer, as its existence is U.B. for dead accounts.
      35             : 
      36             :    See fd_acc_exists and the below helper functions for safe use in
      37             :    native programs. */
      38             : 
      39             : #include "fd_executor_err.h"
      40             : #include "fd_system_ids.h"
      41             : #include "context/fd_exec_epoch_ctx.h"
      42             : #include "context/fd_exec_txn_ctx.h"
      43             : #include "program/fd_program_util.h"
      44             : #include "sysvar/fd_sysvar_rent.h"
      45             : #include <assert.h>  /* TODO remove */
      46             : 
      47             : /* FD_ACC_SZ_MAX is the hardcoded size limit of a Solana account. */
      48             : 
      49           0 : #define MAX_PERMITTED_DATA_LENGTH                 (10UL<<20) /* 10MiB */
      50             : #define MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN (10UL<<21) /* 20MiB */
      51             : 
      52             : /* Convenience macro for `fd_account_check_num_insn_accounts()` */
      53           0 : #define CHECK_NUM_INSN_ACCS( _ctx, _expected ) do {                        \
      54           0 :   if( FD_UNLIKELY( (_ctx)->instr->acct_cnt<(_expected) ) ) {               \
      55           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                      \
      56           0 :   }                                                                        \
      57           0 : } while(0)
      58             : 
      59             : FD_PROTOTYPES_BEGIN
      60             : 
      61             : /* Instruction account APIs *******************************************/
      62             : 
      63             : /* Assert that enough ccounts were supplied to this instruction. Returns 
      64             :    FD_EXECUTOR_INSTR_SUCCESS if the number of accounts is as expected and 
      65             :    FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS otherwise.
      66             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L492-L503 */
      67             : static inline int
      68             : fd_account_check_num_insn_accounts( fd_exec_instr_ctx_t * ctx,
      69        1911 :                                     uint                  expected_accounts ) {
      70             : 
      71        1911 :   if( FD_UNLIKELY( ctx->instr->acct_cnt<expected_accounts ) ) {
      72           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
      73           0 :   }
      74        1911 :   return FD_EXECUTOR_INSTR_SUCCESS;
      75        1911 : }
      76             : 
      77             : /* fd_account_get_owner mirrors Anza function 
      78             :    solana_sdk::transaction_context:Borrowed_account::get_owner.  Returns 0
      79             :    iff the owner is retrieved successfully.
      80             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L734-L738 */
      81             : static inline fd_pubkey_t const *
      82             : fd_account_get_owner( fd_exec_instr_ctx_t const * ctx,
      83           0 :                       ulong                       instr_acc_idx ) {
      84           0 :   fd_borrowed_account_t * account = NULL;
      85           0 :   do {
      86           0 :     int err = fd_instr_borrowed_account_view_idx( ctx, (uchar)instr_acc_idx, &account );
      87           0 :     if( FD_UNLIKELY( err ) ) {
      88           0 :       FD_LOG_ERR(( "fd_instr_borrowed_account_view_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
      89           0 :     }
      90           0 :   } while(0);
      91           0 : 
      92           0 :   return (fd_pubkey_t const *) account->const_meta->info.owner;
      93           0 : }
      94             : 
      95             : /* fd_account_set_owner mirrors Anza function 
      96             :    solana_sdk::transaction_context:Borrowed_account::set_owner.  Returns 0
      97             :    iff the owner is set successfully.  Acquires a writable handle. */
      98             : int
      99             : fd_account_set_owner( fd_exec_instr_ctx_t const * ctx,
     100             :                       ulong                       instr_acc_idx,
     101             :                       fd_pubkey_t const *         owner );
     102             : 
     103             : /* fd_account_get_lamports mirrors Anza function
     104             :    solana_sdk::transaction_context::BorrowedAccount::get_lamports.
     105             :    Returns current number of lamports in account.  Well behaved if meta
     106             :    is NULL. */
     107             : 
     108             : static inline ulong
     109           0 : fd_account_get_lamports( fd_account_meta_t const * meta ) {
     110           0 :   if( FD_UNLIKELY( !meta ) ) return 0UL;  /* (!meta) considered an internal error */
     111           0 :   return meta->info.lamports;
     112           0 : }
     113             : 
     114             : static inline ulong
     115             : fd_account_get_lamports2( fd_exec_instr_ctx_t const * ctx,
     116          27 :                           ulong                       instr_acc_idx ) {
     117          27 :   fd_borrowed_account_t * account = NULL;
     118          27 :   do {
     119          27 :     int err = fd_instr_borrowed_account_view_idx( ctx, (uchar)instr_acc_idx, &account );
     120          27 :     if( FD_UNLIKELY( err ) ) {
     121           0 :       return 0UL;
     122           0 :     }
     123          27 :   } while(0);
     124             : 
     125          27 :   return account->const_meta->info.lamports;
     126          27 : }
     127             : 
     128             : /* fd_account_set_lamports mirrors Anza function
     129             :    solana_sdk::transaction_context::BorrowedAccount::set_lamports.
     130             :    Runs through a sequence of permission checks, then sets the account
     131             :    balance.  Does not update global capitalization.  On success, returns
     132             :    0 and updates meta->lamports.  On failure, returns an
     133             :    FD_EXECUTOR_INSTR_ERR_{...} code.  Acquires a writable handle. */
     134             : 
     135             : int
     136             : fd_account_set_lamports( fd_exec_instr_ctx_t const * ctx,
     137             :                          ulong                       instr_acc_idx,
     138             :                          ulong                       lamports );
     139             : 
     140             : /* 
     141             :   fd_account_checked_{add,sub}_lamports mirros Anza 
     142             :    add/removes lamports to/from an
     143             :    account.  Does not update global capitalization.  Returns 0 on
     144             :    success or an FD_EXECUTOR_INSTR_ERR_{...} code on failure.
     145             :    Gracefully handles underflow.  Acquires a writable handle. 
     146             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L798-L817 */
     147             : 
     148             : static inline int
     149             : fd_account_checked_add_lamports( fd_exec_instr_ctx_t const * ctx,
     150             :                                  ulong                       instr_acc_idx,
     151        3870 :                                  ulong                       lamports ) {
     152             : 
     153        3870 :   fd_borrowed_account_t * account = NULL;
     154        3870 :   do {
     155        3870 :     int err = fd_instr_borrowed_account_modify_idx( ctx, (uchar)instr_acc_idx, 0UL, &account );
     156        3870 :     if( FD_UNLIKELY( err ) ) { 
     157           0 :       FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
     158           0 :     }
     159        3870 :   } while(0);
     160             : 
     161        3870 :   ulong balance_post = 0UL;
     162        3870 :   int err = fd_ulong_checked_add( account->const_meta->info.lamports, lamports, &balance_post );
     163        3870 :   if( FD_UNLIKELY( err ) ) {
     164         111 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     165         111 :   }
     166             : 
     167        3759 :   return fd_account_set_lamports( ctx, instr_acc_idx, balance_post );
     168        3870 : }
     169             : 
     170             : static inline int
     171             : fd_account_checked_sub_lamports( fd_exec_instr_ctx_t const * ctx,
     172             :                                  ulong                       instr_acc_idx,
     173        3756 :                                  ulong                       lamports ) {
     174             : 
     175        3756 :   fd_borrowed_account_t * account = NULL;
     176        3756 :   do {
     177        3756 :     int err = fd_instr_borrowed_account_modify_idx( ctx, (uchar)instr_acc_idx, 0UL, &account );
     178        3756 :     if( FD_UNLIKELY( err ) ) { 
     179           0 :       FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
     180           0 :     }
     181        3756 :   } while(0);
     182             : 
     183        3756 :   ulong balance_post = 0UL;
     184        3756 :   int err = fd_ulong_checked_sub( account->const_meta->info.lamports, lamports, &balance_post );
     185        3756 :   if( FD_UNLIKELY( err ) ) {
     186           3 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     187           3 :   }
     188             : 
     189        3753 :   return fd_account_set_lamports( ctx, instr_acc_idx, balance_post );
     190        3756 : }
     191             : 
     192             : /* fd_account_get_data_mut mirrors Anza function 
     193             :    solana_sdk::transaction_context::BorrowedAccount::set_lamports. 
     194             :    Returns a writable slice of the account data (transaction wide).
     195             :    Acquires a writable handle. This function assumes that the relevant
     196             :    borrowed has already acquired exclusive write access.
     197             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L824-L831 */
     198             : int 
     199             : fd_account_get_data_mut( fd_exec_instr_ctx_t const * ctx, 
     200             :                          ulong                       instr_acc_idx,
     201             :                          uchar * *                   data_out,
     202             :                          ulong *                     dlen_out );
     203             :               
     204             : /* TODO: Implement fd_account_spare_data_capacity_mut which is used in direct mapping */
     205             : 
     206             : /* fd_account_set_data_from_slice mirrors Anza function
     207             :    solana_sdk::transaction_context::BorrowedAccount::set_data_from_slice.
     208             :    In the firedancer client, it also mirrors the Anza function
     209             :    solana_sdk::transaction_context::BorrowedAccount::set_data.
     210             :    Assumes that destination account already has enough space to fit
     211             :    data.  Acquires a writable handle.
     212             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L867-882 */
     213             : 
     214             : int
     215             : fd_account_set_data_from_slice( fd_exec_instr_ctx_t const * ctx,
     216             :                                 ulong                       instr_acc_idx,
     217             :                                 uchar const *               data,
     218             :                                 ulong                       data_sz );
     219             : 
     220             : /* fd_account_set_data_length mirrors Anza function
     221             :    solana_sdk::transaction_context::BorrowedAccount::set_data_length.
     222             :    Acquires a writable handle. Returns 0 on success.
     223             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L994-L900 */
     224             : 
     225             : int
     226             : fd_account_set_data_length( fd_exec_instr_ctx_t const * ctx,
     227             :                             ulong                       instr_acc_idx,
     228             :                             ulong                       new_len );
     229             : 
     230             : /* fd_account_is_rent_exempt_at_data_length mirrors Anza function
     231             :    solana_sdk::transaction_context::BorrowedAccount::is_rent_exempt_at_data_length.
     232             :    Returns 1 if an account is rent exempt at it's current data length.
     233             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L990-997 */
     234             : 
     235             : static inline int
     236             : fd_account_is_rent_exempt_at_data_length( fd_exec_instr_ctx_t const * ctx,
     237           0 :                                           fd_account_meta_t   const * meta ) {
     238           0 :   assert( meta != NULL );
     239           0 :   fd_rent_t rent    = ctx->epoch_ctx->epoch_bank.rent;
     240           0 :   ulong min_balance = fd_rent_exempt_minimum_balance( &rent, meta->dlen );
     241           0 :   return meta->info.lamports >= min_balance; 
     242           0 : }
     243             : 
     244             : /* fd_account_is_executable returns 1 if the given account has the
     245             :    executable flag set.  Otherwise, returns 0.  Mirrors Anza's
     246             :    solana_sdk::transaction_context::BorrowedAccount::is_executable.
     247             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1001-1003 */
     248             : 
     249             : FD_FN_PURE static inline int
     250       72333 : fd_account_is_executable( fd_account_meta_t const * meta ) {
     251       72333 :   return !!meta->info.executable;
     252       72333 : }
     253             : 
     254             : /* fd_account_is_executable_internal was introduced to move towards deprecating the `is_executable` flag.
     255             :    It returns true if the `remove_accounts_executable_flag_checks` feature is inactive AND fd_account_is_executable
     256             :    return true. This is newly used in account modification logic to eventually allow "executable" accounts to be
     257             :    modified. 
     258             :    https://github.com/anza-xyz/agave/blob/89872fdb074e6658646b2b57a299984f0059cc84/sdk/transaction-context/src/lib.rs#L1052-L1060 */
     259             : 
     260             : FD_FN_PURE static inline int
     261             : fd_account_is_executable_internal( fd_exec_slot_ctx_t const * slot_ctx,
     262       22773 :                                    fd_account_meta_t  const * meta ) {
     263       22773 :   return !FD_FEATURE_ACTIVE( slot_ctx, remove_accounts_executable_flag_checks ) &&
     264       22773 :          fd_account_is_executable( meta );
     265       22773 : }
     266             : 
     267             : /* fd_account_set_executable mirrors Anza function
     268             :    solana_sdk::transaction_context::BorrowedAccount::set_executable.
     269             :    Returns FD_EXECUTOR_INSTR_SUCCESS if the set is successful.
     270             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1007-1035 */
     271             : 
     272             : int
     273             : fd_account_set_executable( fd_exec_instr_ctx_t const * ctx,
     274             :                            ulong                       instr_acc_idx,
     275             :                            int                         is_executable );
     276             : 
     277             : /* fd_account_get_rent_epoch mirrors Anza function 
     278             :    solana_sdk::transaction_context::BorrowedAccount::get_rent_epoch. 
     279             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1040-1042 */
     280             : 
     281             : static inline ulong
     282           0 : fd_account_get_rent_epoch( fd_account_meta_t const * meta ) {
     283           0 :   assert( meta != NULL );
     284           0 :   return meta->info.rent_epoch;
     285           0 : }
     286             : 
     287             : /* fd_account_is_{signer,writable} mirror the Anza functions
     288             :    solana_sdk::transaction_context::BorrowedAccount::is_{signer,writer}.
     289             :    Returns 1 if the account is a signer or is writable and 0 otherwise.
     290             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1044-1068 */
     291             : 
     292             : static inline int
     293             : fd_account_is_signer( fd_exec_instr_ctx_t const * ctx,
     294           0 :                       ulong                       instr_acc_idx ) {
     295           0 :   if( FD_UNLIKELY( instr_acc_idx >= ctx->instr->acct_cnt ) ) {
     296           0 :     return 0;
     297           0 :   }
     298           0 :   return fd_instr_acc_is_signer_idx( ctx->instr, instr_acc_idx );
     299           0 : }
     300             : 
     301             : static inline int
     302             : fd_account_is_writable( fd_exec_instr_ctx_t const * ctx,
     303           0 :                         ulong                       instr_acc_idx ) {
     304           0 :   if( FD_UNLIKELY( instr_acc_idx >= ctx->instr->acct_cnt ) ) {
     305           0 :     return 0;
     306           0 :   }
     307           0 : 
     308           0 :   return fd_instr_acc_is_writable_idx( ctx->instr, instr_acc_idx );
     309           0 : }
     310             : 
     311             : /* fd_account_is_owned_by_current_program returns 1 if the given
     312             :    account is owned by the program invoked in the current instruction.
     313             :    Otherwise, returns 0.  Mirrors Anza's
     314             :    solana_sdk::transaction_context::BorrowedAccount::is_owned_by_current_program */
     315             : 
     316             : FD_FN_PURE static inline int
     317             : fd_account_is_owned_by_current_program( fd_instr_info_t const *   info,
     318       27333 :                                         fd_account_meta_t const * acct ) {
     319       27333 :   return 0==memcmp( info->program_id_pubkey.key, acct->info.owner, sizeof(fd_pubkey_t) );
     320       27333 : }
     321             : 
     322             : /* fd_account_can_data_be changed mirrors Anza function 
     323             :    solana_sdk::transaction_context::BorrowedAccount::can_data_be_changed.
     324             :    https://github.com/anza-xyz/agave/blob/89872fdb074e6658646b2b57a299984f0059cc84/sdk/transaction-context/src/lib.rs#L1136-L1152 */
     325             : static inline int
     326             : fd_account_can_data_be_changed( fd_exec_instr_ctx_t const * ctx,
     327             :                                 ulong                       instr_acc_idx,
     328       13284 :                                 int *                       err ) {
     329             : 
     330       13284 :   fd_instr_info_t const * instr = ctx->instr;
     331       13284 :   assert( instr_acc_idx < instr->acct_cnt );
     332           0 :   fd_account_meta_t const * meta = instr->borrowed_accounts[ instr_acc_idx ]->const_meta;
     333             : 
     334       13284 :   if( FD_UNLIKELY( fd_account_is_executable_internal( ctx->slot_ctx, meta ) ) ) {
     335        1011 :     *err = FD_EXECUTOR_INSTR_ERR_EXECUTABLE_DATA_MODIFIED;
     336        1011 :     return 0;
     337        1011 :   }
     338             : 
     339       12273 :   if( FD_UNLIKELY( !fd_instr_acc_is_writable_idx( instr, instr_acc_idx ) ) ) {
     340         924 :     *err = FD_EXECUTOR_INSTR_ERR_READONLY_DATA_MODIFIED;
     341         924 :     return 0;
     342         924 :   }
     343             : 
     344       11349 :   if( FD_UNLIKELY( !fd_account_is_owned_by_current_program( instr, meta ) ) ) {
     345        1236 :     *err = FD_EXECUTOR_INSTR_ERR_EXTERNAL_DATA_MODIFIED;
     346        1236 :     return 0;
     347        1236 :   }
     348             : 
     349       10113 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     350       10113 :   return 1;
     351       11349 : }
     352             : 
     353             : /* fd_account_can_data_be_resized mirrors Anza function 
     354             :    solana_sdk::transaction_context::BorrowedAccount::can_data_be_resized 
     355             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1096-L1119
     356             : */
     357             : static inline int
     358             : fd_account_can_data_be_resized( fd_exec_instr_ctx_t const * instr_ctx,
     359             :                                 fd_account_meta_t const *   acct,
     360             :                                 ulong                       new_length,
     361        5994 :                                 int *                       err ) {
     362             :   /* Only the owner can change the length of the data */
     363        5994 :   if( FD_UNLIKELY( ( acct->dlen != new_length ) &
     364        5994 :                    ( !fd_account_is_owned_by_current_program( instr_ctx->instr, acct ) ) ) ) {
     365           3 :     *err = FD_EXECUTOR_INSTR_ERR_ACC_DATA_SIZE_CHANGED;
     366           3 :     return 0;
     367           3 :   }
     368             : 
     369             :   /* The new length can not exceed the maximum permitted length */
     370        5991 :   if( FD_UNLIKELY( new_length>MAX_PERMITTED_DATA_LENGTH ) ) {
     371           0 :     *err = FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     372           0 :     return 0;
     373           0 :   }
     374             : 
     375             :   /* The resize can not exceed the per-transaction maximum
     376             :      https://github.com/firedancer-io/agave/blob/1e460f466da60a63c7308e267c053eec41dc1b1c/sdk/src/transaction_context.rs#L1107-L1111 */
     377        5991 :   ulong length_delta = fd_ulong_sat_sub( new_length, acct->dlen );
     378        5991 :   ulong new_accounts_resize_delta = fd_ulong_sat_add( instr_ctx->txn_ctx->accounts_resize_delta, length_delta );
     379        5991 :   if( FD_UNLIKELY( new_accounts_resize_delta>MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN ) ) {
     380           0 :     *err = FD_EXECUTOR_INSTR_ERR_MAX_ACCS_DATA_ALLOCS_EXCEEDED;
     381           0 :     return 0;
     382           0 :   }
     383             : 
     384        5991 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     385        5991 :   return 1;
     386        5991 : }
     387             : 
     388             : /* fd_account_update_acounts_resize_delta mirrors Anza function
     389             :    solana_sdk::transaction_context:BorrowedAccount::update_accounts_resize_delta. 
     390             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1128-L1138 */
     391             : 
     392             : int
     393             : fd_account_update_accounts_resize_delta( fd_exec_instr_ctx_t const * ctx,
     394             :                                          ulong                       instr_acc_idx,
     395             :                                          ulong                       new_len,
     396             :                                          int *                       err );
     397             : 
     398             : FD_FN_PURE static inline int
     399        1944 : fd_account_is_zeroed( fd_account_meta_t const * acct ) {
     400             :   // TODO: optimize this
     401        1944 :   uchar const * data = ((uchar *) acct) + acct->hlen;
     402  5763198933 :   for( ulong i=0UL; i < acct->dlen; i++ )
     403  5763197046 :     if( data[i] != 0 )
     404          57 :       return 0;
     405        1887 :   return 1;
     406        1944 : }
     407             : 
     408             : /* fd_account_find_idx_of_insn_account returns the idx of the instruction account
     409             :     or -1 if the account is not found
     410             :     https://github.com/anza-xyz/agave/blob/d5a84daebd2a7225684aa3f722b330e9d5381e76/sdk/src/transaction_context.rs#L527
     411             :  */
     412             : static inline int
     413             : fd_account_find_idx_of_insn_account( fd_exec_instr_ctx_t const * ctx,
     414         522 :                                      fd_pubkey_t *               pubkey ) {
     415        4437 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     416        4437 :     if( 0==memcmp( pubkey, &ctx->instr->acct_pubkeys[i], sizeof(fd_pubkey_t) ) ) {
     417         522 :       return (int)i;
     418         522 :     }
     419        4437 :   }
     420           0 :   return -1;
     421         522 : }
     422             : 
     423             : FD_PROTOTYPES_END
     424             : 
     425             : #include "fd_account_old.h"
     426             : 
     427             : #endif /* HEADER_fd_src_flamenco_runtime_fd_account_h */

Generated by: LCOV version 1.14