LCOV - code coverage report
Current view: top level - flamenco/runtime/context - fd_exec_instr_ctx.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 77 84 91.7 %
Date: 2026-10-23 04:27:11 Functions: 8 8 100.0 %

          Line data    Source code
       1             : #include "fd_exec_instr_ctx.h"
       2             : #include "../fd_runtime.h"
       3             : #include "../fd_borrowed_account.h"
       4             : 
       5             : void
       6             : fd_exec_instr_ctx_instr_account_map( fd_exec_instr_ctx_t const * ctx,
       7        6366 :                                      ushort                      map[ MAX_TX_ACCOUNT_LOCKS ] ) {
       8        6366 :   memset( map, 0xff, MAX_TX_ACCOUNT_LOCKS*sizeof(ushort) );
       9       21516 :   for( ulong i=ctx->instr->acct_cnt; i; i-- ) {
      10       15150 :     ushort idx_in_txn = ctx->instr->accounts[ i-1UL ].index_in_transaction;
      11       15150 :     if( FD_LIKELY( idx_in_txn<MAX_TX_ACCOUNT_LOCKS ) ) map[ idx_in_txn ] = (ushort)(i-1UL);
      12       15150 :   }
      13        6366 : }
      14             : 
      15             : int
      16             : fd_exec_instr_ctx_get_key_of_account_at_index( fd_exec_instr_ctx_t const * ctx,
      17             :                                                ushort                      idx_in_instr,
      18        4449 :                                                fd_pubkey_t const * *       key ) {
      19        4449 :   ushort idx_in_txn;
      20        4449 :   int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
      21        4449 :                                                                          idx_in_instr,
      22        4449 :                                                                          &idx_in_txn );
      23        4449 :   if( FD_UNLIKELY( err ) ) return err;
      24             : 
      25        4449 :   return fd_runtime_get_key_of_account_at_index( ctx->txn_out, idx_in_txn, key );
      26        4449 : }
      27             : 
      28             : int
      29             : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx,
      30       18348 :                                         fd_pubkey_t const * *       key ) {
      31       18348 :   return fd_runtime_get_key_of_account_at_index( ctx->txn_out, ctx->instr->program_id, key );
      32       18348 : }
      33             : 
      34             : int
      35             : fd_exec_instr_ctx_try_borrow_account( fd_exec_instr_ctx_t const * ctx,
      36             :                                       ushort                      idx_in_instr,
      37             :                                       ushort                      idx_in_txn,
      38       29355 :                                       fd_borrowed_account_t *     account ) {
      39             :   /* Get the account from the transaction context using idx_in_txn.
      40             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L600-L602 */
      41       29355 :   fd_acc_t * ref = fd_runtime_get_account_at_index( ctx->txn_in, ctx->txn_out, idx_in_txn, NULL );
      42       29355 :   if( FD_UNLIKELY( !ref ) ) {
      43             :     /* Return a MissingAccount error if the account is not found.
      44             :        https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L603 */
      45           0 :     FD_TXN_ERR_FOR_LOG_INSTR( ctx->txn_out, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, ctx->txn_out->err.exec_err_idx );
      46           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
      47           0 :   }
      48             : 
      49             :   /* Return an AccountBorrowFailed error if the write is not acquirable.
      50             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L605 */
      51       29355 :   if( FD_UNLIKELY( ctx->runtime->accounts.refcnt[idx_in_txn]!=0UL ) ) {
      52           6 :     return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
      53           6 :   }
      54       29349 :   ctx->runtime->accounts.refcnt[idx_in_txn]++;
      55             : 
      56             :   /* Create a BorrowedAccount upon success.
      57             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L606 */
      58       29349 :   fd_borrowed_account_init( account,
      59       29349 :                             ref,
      60       29349 :                             ctx,
      61       29349 :                             idx_in_instr,
      62       29349 :                             &ctx->runtime->accounts.refcnt[idx_in_txn],
      63       29349 :                             &ctx->txn_out->accounts.touched[idx_in_txn] );
      64       29349 :   return FD_EXECUTOR_INSTR_SUCCESS;
      65       29355 : }
      66             : 
      67             : int
      68             : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx,
      69             :                                             ushort                      idx,
      70       26796 :                                             fd_borrowed_account_t *     account ) {
      71             :   /* Find the index of the account in the transaction context.
      72             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L649-L650 */
      73       26796 :   ushort idx_in_txn;
      74       26796 :   int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
      75       26796 :                                                                          idx,
      76       26796 :                                                                          &idx_in_txn );
      77       26796 :   if( FD_UNLIKELY( err ) ) {
      78           0 :     return err;
      79           0 :   }
      80             : 
      81       26796 :   return fd_exec_instr_ctx_try_borrow_account( ctx,
      82       26796 :                                                idx,
      83       26796 :                                                idx_in_txn,
      84       26796 :                                                account );
      85       26796 : }
      86             : 
      87             : int
      88             : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx,
      89        2559 :                                                    fd_borrowed_account_t *     account ) {
      90             :   /* The index_in_instruction for a borrowed program account is invalid,
      91             :      so it is set to a sentinel value of USHORT_MAX. */
      92        2559 :   return fd_exec_instr_ctx_try_borrow_account( ctx,
      93        2559 :                                                USHORT_MAX,
      94        2559 :                                                ctx->instr->program_id,
      95        2559 :                                                account );
      96        2559 : }
      97             : 
      98             : int
      99             : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx,
     100             :                                fd_pubkey_t const *         signers[static FD_INSTR_SIGNERS_MAX],
     101         120 :                                ulong *                     signers_cnt ) {
     102         120 :   ulong j = 0UL;
     103         495 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     104         375 :     if( fd_instr_acc_is_signer_idx( ctx->instr, i, NULL ) ) {
     105         153 :       ushort idx_in_txn = ctx->instr->accounts[i].index_in_transaction;
     106         153 :       fd_pubkey_t const * pubkey = NULL;
     107         153 :       int err = fd_runtime_get_key_of_account_at_index( ctx->txn_out, idx_in_txn, &pubkey );
     108         153 :       if( FD_UNLIKELY( err ) ) return err;
     109             : 
     110             :       /* Skip if duplicate signer */
     111         153 :       if( FD_UNLIKELY( fd_signers_contains( signers, j, pubkey ) ) ) {
     112          12 :         continue;
     113          12 :       }
     114             : 
     115             :       /* This should never be possible */
     116         141 :       if( FD_UNLIKELY( j>=FD_INSTR_SIGNERS_MAX ) ) {
     117           0 :         FD_LOG_CRIT(( "invariant violation: too many signers (cnt=%lu, FD_INSTR_SIGNERS_MAX=%lu)", j, (ulong)FD_INSTR_SIGNERS_MAX ));
     118           0 :       }
     119             : 
     120         141 :       signers[j++] = pubkey;
     121         141 :     }
     122         375 :   }
     123             : 
     124         120 :   *signers_cnt = j;
     125         120 :   return FD_EXECUTOR_INSTR_SUCCESS;
     126         120 : }
     127             : 
     128             : int
     129             : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx,
     130         123 :                               fd_pubkey_t const *         pubkey ) {
     131         123 :   int is_signer = 0;
     132         351 :   for( ushort j=0; j<ctx->instr->acct_cnt; j++ ) {
     133         228 :     ushort idx_in_txn = ctx->instr->accounts[ j ].index_in_transaction;
     134         228 :     is_signer |=
     135             :         ( ( !!fd_instr_acc_is_signer_idx( ctx->instr, j, NULL ) ) &
     136         228 :         ( 0==memcmp( pubkey->key, ctx->txn_out->accounts.keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) );
     137         228 :   }
     138         123 :   return is_signer;
     139         123 : }

Generated by: LCOV version 1.14