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: 68 109 62.4 %
Date: 2026-02-04 05:34:24 Functions: 7 9 77.8 %

          Line data    Source code
       1             : #include "fd_exec_instr_ctx.h"
       2             : #include "../fd_runtime.h"
       3             : #include "../fd_borrowed_account.h"
       4             : 
       5             : int
       6             : fd_exec_instr_ctx_find_idx_of_instr_account( fd_exec_instr_ctx_t const * ctx,
       7         108 :                                              fd_pubkey_t const *         pubkey ) {
       8         216 :   for( int i=0; i<ctx->instr->acct_cnt; i++ ) {
       9         216 :     ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
      10         216 :     if( memcmp( pubkey->uc, ctx->txn_out->accounts.keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
      11         108 :       return i;
      12         108 :     }
      13         216 :   }
      14           0 :   return -1;
      15         108 : }
      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           6 :                                                fd_pubkey_t const * *       key ) {
      21           6 :   ushort idx_in_txn;
      22           6 :   int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
      23           6 :                                                                          idx_in_instr,
      24           6 :                                                                          &idx_in_txn );
      25           6 :   if( FD_UNLIKELY( err ) ) {
      26           0 :     return err;
      27           0 :   }
      28             : 
      29           6 :   return fd_runtime_get_key_of_account_at_index( ctx->txn_out,
      30           6 :                                                       idx_in_txn,
      31           6 :                                                       key );
      32           6 : }
      33             : 
      34             : int
      35             : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx,
      36         522 :                                         fd_pubkey_t const * *       key ) {
      37         522 :   return fd_runtime_get_key_of_account_at_index( ctx->txn_out,
      38         522 :                                                       ctx->instr->program_id,
      39         522 :                                                       key );
      40         522 : }
      41             : 
      42             : int
      43             : fd_exec_instr_ctx_try_borrow_account( fd_exec_instr_ctx_t const * ctx,
      44             :                                       ushort                      idx_in_instr,
      45             :                                       ushort                      idx_in_txn,
      46         750 :                                       fd_borrowed_account_t *     account ) {
      47             :   /* Get the account from the transaction context using idx_in_txn.
      48             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L600-L602 */
      49         750 :   int err = fd_runtime_get_account_at_index( ctx->txn_in,
      50         750 :                                              ctx->txn_out,
      51         750 :                                              idx_in_txn,
      52         750 :                                              NULL );
      53         750 :   if( FD_UNLIKELY( err ) ) {
      54             :     /* Return a MissingAccount error if the account is not found.
      55             :        https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L603 */
      56           0 :     FD_TXN_ERR_FOR_LOG_INSTR( ctx->txn_out, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, ctx->txn_out->err.exec_err_idx );
      57           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
      58           0 :   }
      59             : 
      60         750 :   fd_account_meta_t * meta = ctx->txn_out->accounts.account[idx_in_txn].meta;
      61             : 
      62             :   /* Return an AccountBorrowFailed error if the write is not acquirable.
      63             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L605 */
      64         750 :   if( FD_UNLIKELY( ctx->runtime->accounts.refcnt[idx_in_txn]!=0UL ) ) {
      65           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
      66           0 :   }
      67         750 :   ctx->runtime->accounts.refcnt[idx_in_txn]++;
      68             : 
      69             :   /* Create a BorrowedAccount upon success.
      70             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L606 */
      71         750 :   fd_borrowed_account_init( account,
      72         750 :                             &ctx->txn_out->accounts.keys[idx_in_txn],
      73         750 :                             meta,
      74         750 :                             ctx,
      75         750 :                             idx_in_instr,
      76         750 :                             &ctx->runtime->accounts.refcnt[idx_in_txn] );
      77         750 :   return FD_EXECUTOR_INSTR_SUCCESS;
      78         750 : }
      79             : 
      80             : int
      81             : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx,
      82             :                                             ushort                      idx,
      83         750 :                                             fd_borrowed_account_t *     account ) {
      84             :   /* Find the index of the account in the transaction context.
      85             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L649-L650 */
      86         750 :   ushort idx_in_txn;
      87         750 :   int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
      88         750 :                                                                          idx,
      89         750 :                                                                          &idx_in_txn );
      90         750 :   if( FD_UNLIKELY( err ) ) {
      91           0 :     return err;
      92           0 :   }
      93             : 
      94         750 :   return fd_exec_instr_ctx_try_borrow_account( ctx,
      95         750 :                                                idx,
      96         750 :                                                idx_in_txn,
      97         750 :                                                account );
      98         750 : }
      99             : 
     100             : int
     101             : fd_exec_instr_ctx_try_borrow_instr_account_with_key( fd_exec_instr_ctx_t const * ctx,
     102             :                                                      fd_pubkey_t const *         pubkey,
     103          48 :                                                      fd_borrowed_account_t *     account ) {
     104         120 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     105         120 :     ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
     106         120 :     if( memcmp( pubkey->uc, ctx->txn_out->accounts.keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
     107          48 :       return fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, account );
     108          48 :     }
     109         120 :   }
     110             : 
     111             :   /* Return a NotEnoughAccountKeys error if the account is not found
     112             :      in the instruction context to match the error code returned by
     113             :      fd_exec_instr_ctx_try_borrow_instr_account. */
     114           0 :   return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     115          48 : }
     116             : 
     117             : int
     118             : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx,
     119           0 :                                                    fd_borrowed_account_t *     account ) {
     120             :   /* The index_in_instruction for a borrowed program account is invalid,
     121             :      so it is set to a sentinel value of USHORT_MAX. */
     122           0 :   return fd_exec_instr_ctx_try_borrow_account( ctx,
     123           0 :                                                USHORT_MAX,
     124           0 :                                                ctx->instr->program_id,
     125           0 :                                                account );
     126           0 : }
     127             : 
     128             : int
     129             : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx,
     130             :                                fd_pubkey_t const *         signers[static FD_TXN_SIG_MAX],
     131           0 :                                ulong *                     signers_cnt ) {
     132           0 :   ulong j = 0UL;
     133           0 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     134           0 :     if( fd_instr_acc_is_signer_idx( ctx->instr, i, NULL ) ) {
     135           0 :       ushort idx_in_txn = ctx->instr->accounts[i].index_in_transaction;
     136           0 :       fd_pubkey_t const * pubkey = NULL;
     137           0 :       int err = fd_runtime_get_key_of_account_at_index( ctx->txn_out,
     138           0 :                                                         idx_in_txn,
     139           0 :                                                         &pubkey );
     140           0 :       if( FD_UNLIKELY( err ) ) {
     141           0 :         return err;
     142           0 :       }
     143             : 
     144             :       /* Skip if duplicate signer */
     145           0 :       if( FD_UNLIKELY( fd_signers_contains( signers, j, pubkey ) ) ) {
     146           0 :         continue;
     147           0 :       }
     148             : 
     149             :       /* This should never be possible */
     150           0 :       if( FD_UNLIKELY( j>=FD_TXN_SIG_MAX ) ) {
     151           0 :         FD_LOG_CRIT(( "invariant violation: too many signers (cnt=%lu, FD_TXN_SIG_MAX=%lu)", j, (ulong)FD_TXN_SIG_MAX ));
     152           0 :       }
     153             : 
     154           0 :       signers[j++] = pubkey;
     155           0 :     }
     156           0 :   }
     157             : 
     158           0 :   *signers_cnt = j;
     159           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     160           0 : }
     161             : 
     162             : int
     163             : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx,
     164          24 :                               fd_pubkey_t const *         pubkey ) {
     165          24 :   int is_signer = 0;
     166          48 :   for( ushort j=0; j<ctx->instr->acct_cnt; j++ ) {
     167          24 :     ushort idx_in_txn = ctx->instr->accounts[ j ].index_in_transaction;
     168          24 :     is_signer |=
     169             :         ( ( !!fd_instr_acc_is_signer_idx( ctx->instr, j, NULL ) ) &
     170          24 :         ( 0==memcmp( pubkey->key, ctx->txn_out->accounts.keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) );
     171          24 :   }
     172          24 :   return is_signer;
     173          24 : }

Generated by: LCOV version 1.14