LCOV - code coverage report
Current view: top level - flamenco/runtime/context - fd_exec_instr_ctx.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 26 30 86.7 %
Date: 2026-10-22 18:10:43 Functions: 6 420 1.4 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_context_fd_exec_instr_ctx_h
       2             : #define HEADER_fd_src_flamenco_runtime_context_fd_exec_instr_ctx_h
       3             : 
       4             : #include "../info/fd_instr_info.h"
       5             : #include "../fd_executor_err.h"
       6             : #include "../sysvar/fd_sysvar_cache.h"
       7             : #include "../../fd_flamenco_base.h"
       8             : #include "../../../ballet/txn/fd_txn.h"
       9             : 
      10             : /* Avoid circular include dependency with forward declaration */
      11             : struct fd_borrowed_account;
      12             : typedef struct fd_borrowed_account fd_borrowed_account_t;
      13             : 
      14             : /* fd_exec_instr_ctx_t is the context needed to execute a single
      15             :    instruction (program invocation). */
      16             : 
      17             : struct fd_exec_instr_ctx {
      18             :   fd_instr_info_t const *   instr;   /* The instruction info for this instruction */
      19             :   fd_runtime_t *            runtime; /* The runtime for this instruction */
      20             :   fd_txn_in_t const *       txn_in;  /* The input for this instruction */
      21             :   fd_txn_out_t *            txn_out; /* The output for this instruction */
      22             :   fd_sysvar_cache_t const * sysvar_cache;
      23             :   fd_bank_t *               bank;
      24             : 
      25             :   /* Most instructions log the base58 program id multiple times, so it's
      26             :      convenient to compute it once and reuse it. */
      27             :   char program_id_base58[ FD_BASE58_ENCODED_32_SZ ];
      28             : };
      29             : 
      30             : #define FD_EXEC_INSTR_CTX_ALIGN     (alignof(fd_exec_instr_ctx_t))
      31             : #define FD_EXEC_INSTR_CTX_FOOTPRINT (sizeof (fd_exec_instr_ctx_t))
      32             : 
      33             : /* Be careful when using this macro. There may be places where the error
      34             :    will need to be handled differently. */
      35       73110 : #define FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, idx, acc ) do { \
      36       73110 :   int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, idx, acc );    \
      37       73110 :   if( FD_UNLIKELY( err ) ) return err;                                      \
      38       73110 : } while (0)
      39             : 
      40             : FD_PROTOTYPES_BEGIN
      41             : 
      42             : /* Operators */
      43             : 
      44             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::check_number_of_instruction_accounts
      45             : 
      46             :    Assert that enough accounts were supplied to this instruction. Returns
      47             :    FD_EXECUTOR_INSTR_SUCCESS if the number of accounts is as expected and
      48             :    FD_EXECUTOR_INSTR_ERR_MISSING_ACC otherwise.
      49             : 
      50             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L490 */
      51             : 
      52             : static inline int
      53             : fd_exec_instr_ctx_check_num_insn_accounts( fd_exec_instr_ctx_t const * ctx,
      54        4567 :                                            uint                        expected_accounts ) {
      55             : 
      56        4567 :   if( FD_UNLIKELY( ctx->instr->acct_cnt<expected_accounts ) ) {
      57           7 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
      58           7 :   }
      59        4560 :   return FD_EXECUTOR_INSTR_SUCCESS;
      60        4567 : }
      61             : 
      62             : /* fd_exec_instr_ctx_instr_account_map fills map with, for each
      63             :    transaction account index, the first index of that account in the
      64             :    instruction, or USHORT_MAX.  Transaction keys are unique, so
      65             :    map[ fd_runtime_find_index_of_account( pubkey ) ] is the index of
      66             :    pubkey in the instruction. */
      67             : 
      68             : void
      69             : fd_exec_instr_ctx_instr_account_map( fd_exec_instr_ctx_t const * ctx,
      70             :                                      ushort                      map[ MAX_TX_ACCOUNT_LOCKS ] );
      71             : 
      72             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_index_of_instruction_account_in_transaction
      73             : 
      74             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L552 */
      75             : 
      76             : static inline int
      77             : fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( fd_exec_instr_ctx_t const * ctx,
      78             :                                                              ushort                      idx_in_instr,
      79      251644 :                                                              ushort *                    idx_in_txn ) {
      80      251644 :   if( FD_UNLIKELY( idx_in_instr==USHORT_MAX ) ) {
      81           1 :     *idx_in_txn = USHORT_MAX;
      82           1 :     return FD_EXECUTOR_INSTR_SUCCESS;
      83           1 :   }
      84             : 
      85             :   /* Return a NotEnoughAccountKeys error if the idx is out of bounds.
      86             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L559 */
      87      251643 :   if( FD_UNLIKELY( idx_in_instr>=ctx->instr->acct_cnt ) ) {
      88         173 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
      89         173 :   }
      90             : 
      91      251470 :   *idx_in_txn = ctx->instr->accounts[ idx_in_instr ].index_in_transaction;
      92      251470 :   return FD_EXECUTOR_INSTR_SUCCESS;
      93      251643 : }
      94             : 
      95             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_number_of_program_accounts.
      96             : 
      97             :    Strictly returns 1, as we only support one program account per instruction.
      98             : 
      99             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L480-L482 */
     100             : 
     101             : static inline ushort
     102           0 : fd_exec_instr_ctx_get_number_of_program_accounts( fd_exec_instr_ctx_t const * ctx ) {
     103           0 :   (void) ctx;
     104           0 :   return 1U;
     105           0 : }
     106             : 
     107             : /* A helper function to get the pubkey of an account using its instruction context index */
     108             : int
     109             : fd_exec_instr_ctx_get_key_of_account_at_index( fd_exec_instr_ctx_t const * ctx,
     110             :                                                ushort                      idx_in_instr,
     111             :                                                fd_pubkey_t const * *       key );
     112             : 
     113             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_last_program_key.
     114             : 
     115             :    There can only be one program per instruction, so this function simply retrieves
     116             :    that program's pubkey, despite the name implying multiple programs per instruction.
     117             :    The function exists to match semantics with Agave.
     118             : 
     119             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L582 */
     120             : 
     121             : int
     122             : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx,
     123             :                                         fd_pubkey_t const * *       key );
     124             : 
     125             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::try_borrow_account.
     126             : 
     127             :    Borrows an account from the instruction context with a given account index.
     128             : 
     129             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L594 */
     130             : 
     131             : int
     132             : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx,
     133             :                                             ushort                      idx,
     134             :                                             fd_borrowed_account_t *     account );
     135             : 
     136             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::try_borrow_last_program_account
     137             : 
     138             :    Borrows the instruction's program account. Since there is only one program account per
     139             :    instruction, this function simply borrows the instruction's only program account, despite the name.
     140             : 
     141             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L616 */
     142             : 
     143             : int
     144             : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx,
     145             :                                                    fd_borrowed_account_t *     account );
     146             : 
     147             : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_signers
     148             : 
     149             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L684 */
     150             : 
     151             : int
     152             : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx,
     153             :                                fd_pubkey_t const *         signers[ static FD_INSTR_SIGNERS_MAX ],
     154             :                                ulong *                     signers_cnt );
     155             : 
     156             : /* fd_exec_instr_ctx_any_signed matches
     157             :    solana_system_program::system_processor::Address::is_signer
     158             : 
     159             :    Scans instruction accounts for matching signer.
     160             : 
     161             :    Returns 1 if *any* instruction account with the given pubkey is a
     162             :    signer and 0 otherwise.  Note that the same account/pubkey can be
     163             :    specified as multiple different instruction accounts that might not
     164             :    all have the signer bit.
     165             : 
     166             :    https://github.com/anza-xyz/agave/blob/v2.1.14/programs/system/src/system_processor.rs#L35-L41 */
     167             : 
     168             : FD_FN_PURE int
     169             : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx,
     170             :                               fd_pubkey_t const *         pubkey );
     171             : 
     172             : /* Although fd_signers_contains does not take an instruction context,
     173             :    it is included here for relevance to signer helper functions
     174             : 
     175             :    Loop conditions could be optimized to allow for unroll/vectorize */
     176             : 
     177             : static inline int
     178             : fd_signers_contains( fd_pubkey_t const * signers[ static FD_INSTR_SIGNERS_MAX ],
     179             :                      ulong               signers_cnt,
     180       13801 :                      fd_pubkey_t const * pubkey ) {
     181       26125 :   for( ulong i=0; i<signers_cnt; i++ )
     182       15742 :     if( 0==memcmp( signers[i], pubkey, sizeof( fd_pubkey_t ) ) ) return 1;
     183       10383 :   return 0;
     184       13801 : }
     185             : 
     186             : FD_PROTOTYPES_END
     187             : 
     188             : #endif /* HEADER_fd_src_flamenco_runtime_context_fd_exec_instr_ctx_h */

Generated by: LCOV version 1.14