LCOV - code coverage report
Current view: top level - flamenco/runtime/context - fd_exec_txn_ctx.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 149 0.0 %
Date: 2025-11-21 04:43:39 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #include "fd_exec_txn_ctx.h"
       2             : #include "../fd_acc_mgr.h"
       3             : #include "../fd_executor.h"
       4             : #include "../../vm/fd_vm.h"
       5             : #include "../fd_system_ids.h"
       6             : #include "../fd_bank.h"
       7             : 
       8             : void *
       9           0 : fd_exec_txn_ctx_new( void * mem ) {
      10           0 :   if( FD_UNLIKELY( !mem ) ) {
      11           0 :     FD_LOG_WARNING(( "NULL mem" ));
      12           0 :     return NULL;
      13           0 :   }
      14             : 
      15           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_TXN_CTX_ALIGN ) ) ) {
      16           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      17           0 :     return NULL;
      18           0 :   }
      19             : 
      20           0 :   fd_exec_txn_ctx_t * self = (fd_exec_txn_ctx_t *) mem;
      21           0 :   fd_memset( self, 0, sizeof(fd_exec_txn_ctx_t) );
      22             : 
      23           0 :   return mem;
      24           0 : }
      25             : 
      26             : fd_exec_txn_ctx_t *
      27           0 : fd_exec_txn_ctx_join( void * mem ) {
      28           0 :   if( FD_UNLIKELY( !mem ) ) {
      29           0 :     FD_LOG_WARNING(( "NULL block" ));
      30           0 :     return NULL;
      31           0 :   }
      32             : 
      33           0 :   fd_exec_txn_ctx_t * ctx = (fd_exec_txn_ctx_t *) mem;
      34             : 
      35           0 :   return ctx;
      36           0 : }
      37             : 
      38             : void *
      39           0 : fd_exec_txn_ctx_leave( fd_exec_txn_ctx_t * ctx) {
      40           0 :   if( FD_UNLIKELY( !ctx ) ) {
      41           0 :     FD_LOG_WARNING(( "NULL block" ));
      42           0 :     return NULL;
      43           0 :   }
      44             : 
      45           0 :   return (void *) ctx;
      46           0 : }
      47             : 
      48             : void *
      49           0 : fd_exec_txn_ctx_delete( void * mem ) {
      50           0 :   if( FD_UNLIKELY( !mem ) ) {
      51           0 :     FD_LOG_WARNING(( "NULL mem" ));
      52           0 :     return NULL;
      53           0 :   }
      54             : 
      55           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_TXN_CTX_ALIGN) ) )  {
      56           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      57           0 :     return NULL;
      58           0 :   }
      59             : 
      60           0 :   return mem;
      61           0 : }
      62             : 
      63             : int
      64             : fd_exec_txn_ctx_get_account_at_index( fd_exec_txn_ctx_t *             ctx,
      65             :                                       ushort                          idx,
      66             :                                       fd_txn_account_t * *            account,
      67           0 :                                       fd_txn_account_condition_fn_t * condition ) {
      68           0 :   if( FD_UNLIKELY( idx>=ctx->accounts.accounts_cnt ) ) {
      69           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
      70           0 :   }
      71             : 
      72           0 :   fd_txn_account_t * txn_account = &ctx->accounts.accounts[idx];
      73           0 :   *account = txn_account;
      74             : 
      75           0 :   if( FD_LIKELY( condition != NULL ) ) {
      76           0 :     if( FD_UNLIKELY( !condition( *account, ctx, idx ) ) ) {
      77           0 :       return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
      78           0 :     }
      79           0 :   }
      80             : 
      81           0 :   return FD_ACC_MGR_SUCCESS;
      82           0 : }
      83             : 
      84             : int
      85             : fd_exec_txn_ctx_get_account_with_key( fd_exec_txn_ctx_t *             ctx,
      86             :                                       fd_pubkey_t const *             pubkey,
      87             :                                       fd_txn_account_t * *            account,
      88           0 :                                       fd_txn_account_condition_fn_t * condition ) {
      89           0 :   int index = fd_exec_txn_ctx_find_index_of_account( ctx, pubkey );
      90           0 :   if( FD_UNLIKELY( index==-1 ) ) {
      91           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
      92           0 :   }
      93             : 
      94           0 :   return fd_exec_txn_ctx_get_account_at_index( ctx,
      95           0 :                                                (uchar)index,
      96           0 :                                                account,
      97           0 :                                                condition );
      98           0 : }
      99             : 
     100             : int
     101             : fd_exec_txn_ctx_get_executable_account( fd_exec_txn_ctx_t *             ctx,
     102             :                                         fd_pubkey_t const *             pubkey,
     103             :                                         fd_txn_account_t * *            account,
     104           0 :                                         fd_txn_account_condition_fn_t * condition ) {
     105             :   /* First try to fetch the executable account from the existing borrowed accounts.
     106             :      If the pubkey is in the account keys, then we want to re-use that
     107             :      borrowed account since it reflects changes from prior instructions. Referencing the
     108             :      read-only executable accounts list is incorrect behavior when the program
     109             :      data account is written to in a prior instruction (e.g. program upgrade + invoke within the same txn) */
     110           0 :   int err = fd_exec_txn_ctx_get_account_with_key( ctx, pubkey, account, condition );
     111           0 :   if( FD_UNLIKELY( err==FD_ACC_MGR_SUCCESS ) ) {
     112           0 :     return FD_ACC_MGR_SUCCESS;
     113           0 :   }
     114             : 
     115           0 :   for( ushort i=0; i<ctx->accounts.executable_cnt; i++ ) {
     116           0 :     if( memcmp( pubkey->uc, ctx->accounts.executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) )==0 ) {
     117           0 :       fd_txn_account_t * txn_account = &ctx->accounts.executable_accounts[i];
     118           0 :       *account = txn_account;
     119             : 
     120           0 :       if( FD_LIKELY( condition != NULL ) ) {
     121           0 :         if( FD_UNLIKELY( !condition( *account, ctx, i ) ) ) {
     122           0 :           return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     123           0 :         }
     124           0 :       }
     125             : 
     126           0 :       return FD_ACC_MGR_SUCCESS;
     127           0 :     }
     128           0 :   }
     129             : 
     130           0 :   return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     131           0 : }
     132             : 
     133             : int
     134             : fd_exec_txn_ctx_get_key_of_account_at_index( fd_exec_txn_ctx_t *  ctx,
     135             :                                              ushort               idx,
     136           0 :                                              fd_pubkey_t const * * key ) {
     137             :   /* Return a NotEnoughAccountKeys error if idx is out of bounds.
     138             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L218 */
     139           0 :   if( FD_UNLIKELY( idx>=ctx->accounts.accounts_cnt ) ) {
     140           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     141           0 :   }
     142             : 
     143           0 :   *key = &ctx->accounts.account_keys[ idx ];
     144           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     145           0 : }
     146             : 
     147             : /* https://github.com/anza-xyz/agave/blob/v2.1.1/sdk/program/src/message/versions/v0/loaded.rs#L162 */
     148             : int
     149             : fd_txn_account_is_demotion( const int        idx,
     150             :                             const fd_txn_t * txn_descriptor,
     151           0 :                             const uint       bpf_upgradeable_in_txn ) {
     152           0 :   uint is_program = 0U;
     153           0 :   for( ulong j=0UL; j<txn_descriptor->instr_cnt; j++ ) {
     154           0 :     if( txn_descriptor->instr[j].program_id == idx ) {
     155           0 :       is_program = 1U;
     156           0 :       break;
     157           0 :     }
     158           0 :   }
     159             : 
     160           0 :   return (is_program && !bpf_upgradeable_in_txn);
     161           0 : }
     162             : 
     163             : uint
     164             : fd_txn_account_has_bpf_loader_upgradeable( const fd_pubkey_t * account_keys,
     165           0 :                                            const ulong         accounts_cnt ) {
     166           0 :   for( ulong j=0; j<accounts_cnt; j++ ) {
     167           0 :     const fd_pubkey_t * acc = &account_keys[j];
     168           0 :     if ( memcmp( acc->uc, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) == 0 ) {
     169           0 :       return 1U;
     170           0 :     }
     171           0 :   }
     172           0 :   return 0U;
     173           0 : }
     174             : 
     175             : /* This function aims to mimic the writable accounts check to populate the writable accounts cache, used
     176             :    to determine if accounts are writable or not.
     177             : 
     178             :    https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L38-L47 */
     179             : int
     180           0 : fd_exec_txn_ctx_account_is_writable_idx( fd_exec_txn_ctx_t const * txn_ctx, ushort idx ) {
     181           0 :   uint bpf_upgradeable = fd_txn_account_has_bpf_loader_upgradeable( txn_ctx->accounts.account_keys, txn_ctx->accounts.accounts_cnt );
     182           0 :   return fd_exec_txn_account_is_writable_idx_flat( fd_bank_slot_get( txn_ctx->bank ),
     183           0 :                                                    idx,
     184           0 :                                                    &txn_ctx->accounts.account_keys[idx],
     185           0 :                                                    TXN( &txn_ctx->txn ),
     186           0 :                                                    fd_bank_features_query( txn_ctx->bank ),
     187           0 :                                                    bpf_upgradeable );
     188           0 : }
     189             : 
     190             : int
     191             : fd_exec_txn_account_is_writable_idx_flat( const ulong           slot,
     192             :                                           const ushort          idx,
     193             :                                           const fd_pubkey_t *   addr_at_idx,
     194             :                                           const fd_txn_t *      txn_descriptor,
     195             :                                           const fd_features_t * features,
     196           0 :                                           const uint            bpf_upgradeable_in_txn ) {
     197             :   /* https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L43 */
     198           0 :   if( !fd_txn_is_writable( txn_descriptor, idx ) ) {
     199           0 :     return 0;
     200           0 :   }
     201             : 
     202             :   /* See comments in fd_system_ids.h.
     203             :      https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L44 */
     204           0 :   if( fd_pubkey_is_active_reserved_key( addr_at_idx ) ||
     205           0 :       fd_pubkey_is_pending_reserved_key( addr_at_idx ) ||
     206           0 :       ( FD_FEATURE_ACTIVE( slot, features, enable_secp256r1_precompile ) &&
     207           0 :                            fd_pubkey_is_secp256r1_key( addr_at_idx ) ) ) {
     208             : 
     209           0 :     return 0;
     210           0 :   }
     211             : 
     212           0 :   if( fd_txn_account_is_demotion( idx, txn_descriptor, bpf_upgradeable_in_txn ) ) {
     213           0 :     return 0;
     214           0 :   }
     215             : 
     216           0 :   return 1;
     217           0 : }
     218             : 
     219             : /* Account pre-condition filtering functions */
     220             : 
     221             : int
     222             : fd_txn_account_check_exists( fd_txn_account_t *        acc,
     223             :                              fd_exec_txn_ctx_t const * ctx,
     224           0 :                              ushort                    idx ) {
     225           0 :   (void) ctx;
     226           0 :   (void) idx;
     227           0 :   return fd_account_meta_exists( fd_txn_account_get_meta( acc ) );
     228           0 : }
     229             : 
     230             : int
     231             : fd_txn_account_check_is_writable( fd_txn_account_t *        acc,
     232             :                                   fd_exec_txn_ctx_t const * ctx,
     233           0 :                                   ushort                    idx ) {
     234           0 :   (void) acc;
     235           0 :   return fd_exec_txn_ctx_account_is_writable_idx( ctx, idx );
     236           0 : }
     237             : 
     238             : int
     239             : fd_txn_account_check_fee_payer_writable( fd_txn_account_t *        acc,
     240             :                                          fd_exec_txn_ctx_t const * ctx,
     241           0 :                                          ushort                    idx ) {
     242           0 :   (void) acc;
     243           0 :   return fd_txn_is_writable( TXN( &ctx->txn ), idx );
     244           0 : }
     245             : 
     246             : int
     247             : fd_txn_account_check_borrow_mut( fd_txn_account_t *        acc,
     248             :                                  fd_exec_txn_ctx_t const * ctx,
     249           0 :                                  ushort                    idx ) {
     250           0 :   (void) ctx;
     251           0 :   (void) idx;
     252           0 :   return fd_txn_account_is_mutable( acc ) && fd_txn_account_try_borrow_mut( acc );
     253           0 : }

Generated by: LCOV version 1.14