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

Generated by: LCOV version 1.14