LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_account.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 164 0.0 %
Date: 2025-03-11 12:29:46 Functions: 0 456 0.0 %

          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 "fd_runtime.h"
      42             : #include "context/fd_exec_epoch_ctx.h"
      43             : #include "context/fd_exec_txn_ctx.h"
      44             : #include "program/fd_program_util.h"
      45             : #include "sysvar/fd_sysvar_rent.h"
      46             : #include <assert.h>  /* TODO remove */
      47             : 
      48             : /* FD_ACC_SZ_MAX is the hardcoded size limit of a Solana account. */
      49             : 
      50           0 : #define MAX_PERMITTED_DATA_LENGTH                 (10UL<<20) /* 10MiB */
      51             : #define MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN (10L<<21 ) /* 20MiB */
      52             : 
      53             : /* Convenience macro for `fd_account_check_num_insn_accounts()` */
      54           0 : #define CHECK_NUM_INSN_ACCS( _ctx, _expected ) do {                        \
      55           0 :   if( FD_UNLIKELY( (_ctx)->instr->acct_cnt<(_expected) ) ) {               \
      56           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                      \
      57           0 :   }                                                                        \
      58           0 : } while(0)
      59             : 
      60             : FD_PROTOTYPES_BEGIN
      61             : 
      62             : /* Instruction account APIs *******************************************/
      63             : 
      64             : /* FIXME: I don't like this way of accessing the account data... */
      65             : static inline void *
      66           0 : fd_account_get_data( fd_account_meta_t * m ) {
      67           0 :   return ((char *) m) + m->hlen;
      68           0 : }
      69             : 
      70             : /* Assert that enough ccounts were supplied to this instruction. Returns
      71             :    FD_EXECUTOR_INSTR_SUCCESS if the number of accounts is as expected and
      72             :    FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS otherwise.
      73             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L492-L503 */
      74             : static inline int
      75             : fd_account_check_num_insn_accounts( fd_exec_instr_ctx_t * ctx,
      76           0 :                                     uint                  expected_accounts ) {
      77             : 
      78           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt<expected_accounts ) ) {
      79           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
      80           0 :   }
      81           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      82           0 : }
      83             : 
      84             : /* fd_account_get_owner mirrors Anza function
      85             :    solana_sdk::transaction_context:Borrowed_account::get_owner.  Returns 0
      86             :    iff the owner is retrieved successfully.
      87             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L734-L738 */
      88             : static inline fd_pubkey_t const *
      89             : fd_account_get_owner( fd_exec_instr_ctx_t const * ctx,
      90           0 :                       ulong                       instr_acc_idx ) {
      91           0 :   fd_borrowed_account_t * account = NULL;
      92           0 :   do {
      93           0 :     int err = fd_instr_borrowed_account_view_idx( ctx, (uchar)instr_acc_idx, &account );
      94           0 :     if( FD_UNLIKELY( err ) ) {
      95           0 :       FD_LOG_ERR(( "fd_instr_borrowed_account_view_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
      96           0 :     }
      97           0 :   } while(0);
      98           0 : 
      99           0 :   return (fd_pubkey_t const *) account->const_meta->info.owner;
     100           0 : }
     101             : 
     102             : /* fd_account_set_owner mirrors Anza function
     103             :    solana_sdk::transaction_context:Borrowed_account::set_owner.  Returns 0
     104             :    iff the owner is set successfully.  Acquires a writable handle. */
     105             : int
     106             : fd_account_set_owner( fd_exec_instr_ctx_t const * ctx,
     107             :                       ulong                       instr_acc_idx,
     108             :                       fd_pubkey_t const *         owner );
     109             : 
     110             : /* fd_account_get_lamports mirrors Anza function
     111             :    solana_sdk::transaction_context::BorrowedAccount::get_lamports.
     112             :    Returns current number of lamports in account.  Well behaved if meta
     113             :    is NULL. */
     114             : 
     115             : static inline ulong
     116           0 : fd_account_get_lamports( fd_account_meta_t const * meta ) {
     117           0 :   if( FD_UNLIKELY( !meta ) ) return 0UL;  /* (!meta) considered an internal error */
     118           0 :   return meta->info.lamports;
     119           0 : }
     120             : 
     121             : static inline ulong
     122             : fd_account_get_lamports2( fd_exec_instr_ctx_t const * ctx,
     123           0 :                           ulong                       instr_acc_idx ) {
     124           0 :   fd_borrowed_account_t * account = NULL;
     125           0 :   do {
     126           0 :     int err = fd_instr_borrowed_account_view_idx( ctx, (uchar)instr_acc_idx, &account );
     127           0 :     if( FD_UNLIKELY( err ) ) {
     128           0 :       return 0UL;
     129           0 :     }
     130           0 :   } while(0);
     131             : 
     132           0 :   return account->const_meta->info.lamports;
     133           0 : }
     134             : 
     135             : /* fd_account_set_lamports mirrors Anza function
     136             :    solana_sdk::transaction_context::BorrowedAccount::set_lamports.
     137             :    Runs through a sequence of permission checks, then sets the account
     138             :    balance.  Does not update global capitalization.  On success, returns
     139             :    0 and updates meta->lamports.  On failure, returns an
     140             :    FD_EXECUTOR_INSTR_ERR_{...} code.  Acquires a writable handle. */
     141             : 
     142             : int
     143             : fd_account_set_lamports( fd_exec_instr_ctx_t const * ctx,
     144             :                          ulong                       instr_acc_idx,
     145             :                          ulong                       lamports );
     146             : 
     147             : /*
     148             :   fd_account_checked_{add,sub}_lamports mirros Anza
     149             :    add/removes lamports to/from an
     150             :    account.  Does not update global capitalization.  Returns 0 on
     151             :    success or an FD_EXECUTOR_INSTR_ERR_{...} code on failure.
     152             :    Gracefully handles underflow.  Acquires a writable handle.
     153             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L798-L817 */
     154             : 
     155             : static inline int
     156             : fd_account_checked_add_lamports( fd_exec_instr_ctx_t const * ctx,
     157             :                                  ulong                       instr_acc_idx,
     158           0 :                                  ulong                       lamports ) {
     159             : 
     160           0 :   fd_borrowed_account_t * account = NULL;
     161           0 :   do {
     162           0 :     int err = fd_instr_borrowed_account_modify_idx( ctx, (uchar)instr_acc_idx, 0UL, &account );
     163           0 :     if( FD_UNLIKELY( err ) ) {
     164           0 :       FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
     165           0 :     }
     166           0 :   } while(0);
     167             : 
     168           0 :   ulong balance_post = 0UL;
     169           0 :   int err = fd_ulong_checked_add( account->const_meta->info.lamports, lamports, &balance_post );
     170           0 :   if( FD_UNLIKELY( err ) ) {
     171           0 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     172           0 :   }
     173             : 
     174           0 :   return fd_account_set_lamports( ctx, instr_acc_idx, balance_post );
     175           0 : }
     176             : 
     177             : static inline int
     178             : fd_account_checked_sub_lamports( fd_exec_instr_ctx_t const * ctx,
     179             :                                  ulong                       instr_acc_idx,
     180           0 :                                  ulong                       lamports ) {
     181             : 
     182           0 :   fd_borrowed_account_t * account = NULL;
     183           0 :   do {
     184           0 :     int err = fd_instr_borrowed_account_modify_idx( ctx, (uchar)instr_acc_idx, 0UL, &account );
     185           0 :     if( FD_UNLIKELY( err ) ) {
     186           0 :       FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
     187           0 :     }
     188           0 :   } while(0);
     189             : 
     190           0 :   ulong balance_post = 0UL;
     191           0 :   int err = fd_ulong_checked_sub( account->const_meta->info.lamports, lamports, &balance_post );
     192           0 :   if( FD_UNLIKELY( err ) ) {
     193           0 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     194           0 :   }
     195             : 
     196           0 :   return fd_account_set_lamports( ctx, instr_acc_idx, balance_post );
     197           0 : }
     198             : 
     199             : /* fd_account_get_data_mut mirrors Anza function
     200             :    solana_sdk::transaction_context::BorrowedAccount::set_lamports.
     201             :    Returns a writable slice of the account data (transaction wide).
     202             :    Acquires a writable handle. This function assumes that the relevant
     203             :    borrowed has already acquired exclusive write access.
     204             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L824-L831 */
     205             : int
     206             : fd_account_get_data_mut( fd_exec_instr_ctx_t const * ctx,
     207             :                          ulong                       instr_acc_idx,
     208             :                          uchar * *                   data_out,
     209             :                          ulong *                     dlen_out );
     210             : 
     211             : /* TODO: Implement fd_account_spare_data_capacity_mut which is used in direct mapping */
     212             : 
     213             : /* fd_account_set_data_from_slice mirrors Anza function
     214             :    solana_sdk::transaction_context::BorrowedAccount::set_data_from_slice.
     215             :    In the firedancer client, it also mirrors the Anza function
     216             :    solana_sdk::transaction_context::BorrowedAccount::set_data.
     217             :    Assumes that destination account already has enough space to fit
     218             :    data.  Acquires a writable handle.
     219             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L867-882 */
     220             : 
     221             : int
     222             : fd_account_set_data_from_slice( fd_exec_instr_ctx_t const * ctx,
     223             :                                 ulong                       instr_acc_idx,
     224             :                                 uchar const *               data,
     225             :                                 ulong                       data_sz );
     226             : 
     227             : /* fd_account_set_data_length mirrors Anza function
     228             :    solana_sdk::transaction_context::BorrowedAccount::set_data_length.
     229             :    Acquires a writable handle. Returns 0 on success.
     230             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L994-L900 */
     231             : 
     232             : int
     233             : fd_account_set_data_length( fd_exec_instr_ctx_t const * ctx,
     234             :                             ulong                       instr_acc_idx,
     235             :                             ulong                       new_len );
     236             : 
     237             : /* fd_account_is_rent_exempt_at_data_length mirrors Anza function
     238             :    solana_sdk::transaction_context::BorrowedAccount::is_rent_exempt_at_data_length.
     239             :    Returns 1 if an account is rent exempt at it's current data length.
     240             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L990-997 */
     241             : 
     242             : static inline int
     243             : fd_account_is_rent_exempt_at_data_length( fd_exec_instr_ctx_t const * ctx,
     244           0 :                                           fd_account_meta_t   const * meta ) {
     245           0 :   assert( meta != NULL );
     246           0 :   fd_rent_t rent    = ctx->epoch_ctx->epoch_bank.rent;
     247           0 :   ulong min_balance = fd_rent_exempt_minimum_balance( &rent, meta->dlen );
     248           0 :   return meta->info.lamports >= min_balance;
     249           0 : }
     250             : 
     251             : /* fd_account_is_executable returns 1 if the given account has the
     252             :    executable flag set.  Otherwise, returns 0.  Mirrors Anza's
     253             :    solana_sdk::transaction_context::BorrowedAccount::is_executable.
     254             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1001-1003 */
     255             : 
     256             : FD_FN_PURE static inline int
     257           0 : fd_account_is_executable( fd_account_meta_t const * meta ) {
     258           0 :   return !!meta->info.executable;
     259           0 : }
     260             : 
     261             : /* fd_account_is_executable_internal was introduced to move towards deprecating the `is_executable` flag.
     262             :    It returns true if the `remove_accounts_executable_flag_checks` feature is inactive AND fd_account_is_executable
     263             :    return true. This is newly used in account modification logic to eventually allow "executable" accounts to be
     264             :    modified.
     265             :    https://github.com/anza-xyz/agave/blob/89872fdb074e6658646b2b57a299984f0059cc84/sdk/transaction-context/src/lib.rs#L1052-L1060 */
     266             : 
     267             : FD_FN_PURE static inline int
     268             : fd_account_is_executable_internal( fd_exec_slot_ctx_t const * slot_ctx,
     269           0 :                                    fd_account_meta_t  const * meta ) {
     270           0 :   return !FD_FEATURE_ACTIVE( slot_ctx, remove_accounts_executable_flag_checks ) &&
     271           0 :          fd_account_is_executable( meta );
     272           0 : }
     273             : 
     274             : /* fd_account_set_executable mirrors Anza function
     275             :    solana_sdk::transaction_context::BorrowedAccount::set_executable.
     276             :    Returns FD_EXECUTOR_INSTR_SUCCESS if the set is successful.
     277             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1007-1035 */
     278             : 
     279             : int
     280             : fd_account_set_executable( fd_exec_instr_ctx_t const * ctx,
     281             :                            ulong                       instr_acc_idx,
     282             :                            int                         is_executable );
     283             : 
     284             : /* fd_account_get_rent_epoch mirrors Anza function
     285             :    solana_sdk::transaction_context::BorrowedAccount::get_rent_epoch.
     286             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1040-1042 */
     287             : 
     288             : static inline ulong
     289           0 : fd_account_get_rent_epoch( fd_account_meta_t const * meta ) {
     290           0 :   assert( meta != NULL );
     291           0 :   return meta->info.rent_epoch;
     292           0 : }
     293             : 
     294             : /* fd_account_is_{signer,writable} mirror the Anza functions
     295             :    solana_sdk::transaction_context::BorrowedAccount::is_{signer,writer}.
     296             :    Returns 1 if the account is a signer or is writable and 0 otherwise.
     297             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1044-1068 */
     298             : 
     299             : static inline int
     300             : fd_account_is_signer( fd_exec_instr_ctx_t const * ctx,
     301           0 :                       ulong                       instr_acc_idx ) {
     302           0 :   if( FD_UNLIKELY( instr_acc_idx >= ctx->instr->acct_cnt ) ) {
     303           0 :     return 0;
     304           0 :   }
     305           0 :   return fd_instr_acc_is_signer_idx( ctx->instr, instr_acc_idx );
     306           0 : }
     307             : 
     308             : static inline int
     309             : fd_account_is_writable( fd_exec_instr_ctx_t const * ctx,
     310           0 :                         ulong                       instr_acc_idx ) {
     311           0 :   if( FD_UNLIKELY( instr_acc_idx >= ctx->instr->acct_cnt ) ) {
     312           0 :     return 0;
     313           0 :   }
     314           0 : 
     315           0 :   return fd_instr_acc_is_writable_idx( ctx->instr, instr_acc_idx );
     316           0 : }
     317             : 
     318             : /* fd_account_is_owned_by_current_program returns 1 if the given
     319             :    account is owned by the program invoked in the current instruction.
     320             :    Otherwise, returns 0.  Mirrors Anza's
     321             :    solana_sdk::transaction_context::BorrowedAccount::is_owned_by_current_program */
     322             : 
     323             : FD_FN_PURE static inline int
     324             : fd_account_is_owned_by_current_program( fd_instr_info_t const *   info,
     325           0 :                                         fd_account_meta_t const * acct ) {
     326           0 :   return 0==memcmp( info->program_id_pubkey.key, acct->info.owner, sizeof(fd_pubkey_t) );
     327           0 : }
     328             : 
     329             : /* fd_account_can_data_be changed mirrors Anza function
     330             :    solana_sdk::transaction_context::BorrowedAccount::can_data_be_changed.
     331             :    https://github.com/anza-xyz/agave/blob/89872fdb074e6658646b2b57a299984f0059cc84/sdk/transaction-context/src/lib.rs#L1136-L1152 */
     332             : static inline int
     333             : fd_account_can_data_be_changed( fd_exec_instr_ctx_t const * ctx,
     334             :                                 ulong                       instr_acc_idx,
     335           0 :                                 int *                       err ) {
     336             : 
     337           0 :   fd_instr_info_t const * instr = ctx->instr;
     338           0 :   assert( instr_acc_idx < instr->acct_cnt );
     339           0 :   fd_account_meta_t const * meta = instr->borrowed_accounts[ instr_acc_idx ]->const_meta;
     340             : 
     341           0 :   if( FD_UNLIKELY( fd_account_is_executable_internal( ctx->slot_ctx, meta ) ) ) {
     342           0 :     *err = FD_EXECUTOR_INSTR_ERR_EXECUTABLE_DATA_MODIFIED;
     343           0 :     return 0;
     344           0 :   }
     345             : 
     346           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_writable_idx( instr, instr_acc_idx ) ) ) {
     347           0 :     *err = FD_EXECUTOR_INSTR_ERR_READONLY_DATA_MODIFIED;
     348           0 :     return 0;
     349           0 :   }
     350             : 
     351           0 :   if( FD_UNLIKELY( !fd_account_is_owned_by_current_program( instr, meta ) ) ) {
     352           0 :     *err = FD_EXECUTOR_INSTR_ERR_EXTERNAL_DATA_MODIFIED;
     353           0 :     return 0;
     354           0 :   }
     355             : 
     356           0 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     357           0 :   return 1;
     358           0 : }
     359             : 
     360             : /* fd_account_can_data_be_resized mirrors Anza function
     361             :    solana_sdk::transaction_context::BorrowedAccount::can_data_be_resized
     362             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1096-L1119
     363             : */
     364             : static inline int
     365             : fd_account_can_data_be_resized( fd_exec_instr_ctx_t const * instr_ctx,
     366             :                                 fd_account_meta_t const *   acct,
     367             :                                 ulong                       new_length,
     368           0 :                                 int *                       err ) {
     369             :   /* Only the owner can change the length of the data */
     370           0 :   if( FD_UNLIKELY( ( acct->dlen != new_length ) &
     371           0 :                    ( !fd_account_is_owned_by_current_program( instr_ctx->instr, acct ) ) ) ) {
     372           0 :     *err = FD_EXECUTOR_INSTR_ERR_ACC_DATA_SIZE_CHANGED;
     373           0 :     return 0;
     374           0 :   }
     375             : 
     376             :   /* The new length can not exceed the maximum permitted length */
     377           0 :   if( FD_UNLIKELY( new_length>MAX_PERMITTED_DATA_LENGTH ) ) {
     378           0 :     *err = FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     379           0 :     return 0;
     380           0 :   }
     381             : 
     382             :   /* The resize can not exceed the per-transaction maximum
     383             :      https://github.com/firedancer-io/agave/blob/1e460f466da60a63c7308e267c053eec41dc1b1c/sdk/src/transaction_context.rs#L1107-L1111 */
     384           0 :   long length_delta = fd_long_sat_sub( (long)new_length, (long)acct->dlen );
     385           0 :   long new_accounts_resize_delta = fd_long_sat_add( (long)instr_ctx->txn_ctx->accounts_resize_delta, length_delta );
     386           0 :   if( FD_UNLIKELY( new_accounts_resize_delta>MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN ) ) {
     387           0 :     *err = FD_EXECUTOR_INSTR_ERR_MAX_ACCS_DATA_ALLOCS_EXCEEDED;
     388           0 :     return 0;
     389           0 :   }
     390             : 
     391           0 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     392           0 :   return 1;
     393           0 : }
     394             : 
     395             : /* fd_account_update_acounts_resize_delta mirrors Anza function
     396             :    solana_sdk::transaction_context:BorrowedAccount::update_accounts_resize_delta.
     397             :    https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1128-L1138 */
     398             : 
     399             : int
     400             : fd_account_update_accounts_resize_delta( fd_exec_instr_ctx_t const * ctx,
     401             :                                          ulong                       instr_acc_idx,
     402             :                                          ulong                       new_len,
     403             :                                          int *                       err );
     404             : 
     405             : FD_FN_PURE static inline int
     406           0 : fd_account_is_zeroed( fd_account_meta_t const * acct ) {
     407             :   // TODO: optimize this
     408           0 :   uchar const * data = ((uchar *) acct) + acct->hlen;
     409           0 :   for( ulong i=0UL; i < acct->dlen; i++ )
     410           0 :     if( data[i] != 0 )
     411           0 :       return 0;
     412           0 :   return 1;
     413           0 : }
     414             : 
     415             : /* fd_account_find_idx_of_insn_account returns the idx of the instruction account
     416             :     or -1 if the account is not found
     417             :     https://github.com/anza-xyz/agave/blob/d5a84daebd2a7225684aa3f722b330e9d5381e76/sdk/src/transaction_context.rs#L527
     418             :  */
     419             : static inline int
     420             : fd_account_find_idx_of_insn_account( fd_exec_instr_ctx_t const * ctx,
     421           0 :                                      fd_pubkey_t *               pubkey ) {
     422           0 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     423           0 :     if( 0==memcmp( pubkey, &ctx->instr->acct_pubkeys[i], sizeof(fd_pubkey_t) ) ) {
     424           0 :       return (int)i;
     425           0 :     }
     426           0 :   }
     427           0 :   return -1;
     428           0 : }
     429             : 
     430             : /* Backward scan over transaction accounts
     431             :    Returns -1 if not found
     432             :    https://github.com/anza-xyz/agave/blob/228d3b3427abcf3ecfe9757bfa5de411fc020773/sdk/src/transaction_context.rs#L249
     433             :  */
     434             : static inline int
     435             : fd_account_find_index_of_program_account( fd_exec_txn_ctx_t const * ctx,
     436           0 :                                           fd_pubkey_t *             pubkey ) {
     437           0 :   for( ulong i=ctx->accounts_cnt; i>0UL; i-- ) {
     438           0 :     if( 0==memcmp( pubkey, &ctx->accounts[ i-1UL ], sizeof(fd_pubkey_t) ) ) {
     439           0 :       return (int)((ushort)i);
     440           0 :     }
     441           0 :   }
     442           0 :   return -1;
     443           0 : }
     444             : 
     445             : FD_PROTOTYPES_END
     446             : 
     447             : #endif /* HEADER_fd_src_flamenco_runtime_fd_account_h */

Generated by: LCOV version 1.14