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 211 0.0 %
Date: 2025-07-01 05:00:49 Functions: 0 20 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             : 
       7             : void *
       8           0 : fd_exec_txn_ctx_new( void * mem ) {
       9           0 :   if( FD_UNLIKELY( !mem ) ) {
      10           0 :     FD_LOG_WARNING(( "NULL mem" ));
      11           0 :     return NULL;
      12           0 :   }
      13             : 
      14           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_TXN_CTX_ALIGN ) ) ) {
      15           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      16           0 :     return NULL;
      17           0 :   }
      18             : 
      19           0 :   fd_exec_txn_ctx_t * self = (fd_exec_txn_ctx_t *) mem;
      20             : 
      21           0 :   FD_COMPILER_MFENCE();
      22           0 :   self->magic = FD_EXEC_TXN_CTX_MAGIC;
      23           0 :   FD_COMPILER_MFENCE();
      24             : 
      25           0 :   return mem;
      26           0 : }
      27             : 
      28             : fd_exec_txn_ctx_t *
      29             : fd_exec_txn_ctx_join( void *      mem,
      30             :                       fd_spad_t * spad,
      31           0 :                       fd_wksp_t * spad_wksp ) {
      32           0 :   if( FD_UNLIKELY( !mem ) ) {
      33           0 :     FD_LOG_WARNING(( "NULL block" ));
      34           0 :     return NULL;
      35           0 :   }
      36             : 
      37           0 :   fd_exec_txn_ctx_t * ctx = (fd_exec_txn_ctx_t *) mem;
      38             : 
      39           0 :   if( FD_UNLIKELY( ctx->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) {
      40           0 :     FD_LOG_WARNING(( "bad magic" ));
      41           0 :     return NULL;
      42           0 :   }
      43             : 
      44             :   /* Rejoin the wksp */
      45           0 :   ctx->spad      = spad;
      46           0 :   ctx->spad_wksp = spad_wksp;
      47             : 
      48           0 :   return ctx;
      49           0 : }
      50             : 
      51             : void *
      52           0 : fd_exec_txn_ctx_leave( fd_exec_txn_ctx_t * ctx) {
      53           0 :   if( FD_UNLIKELY( !ctx ) ) {
      54           0 :     FD_LOG_WARNING(( "NULL block" ));
      55           0 :     return NULL;
      56           0 :   }
      57             : 
      58           0 :   if( FD_UNLIKELY( ctx->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) {
      59           0 :     FD_LOG_WARNING(( "bad magic" ));
      60           0 :     return NULL;
      61           0 :   }
      62             : 
      63           0 :   return (void *) ctx;
      64           0 : }
      65             : 
      66             : void *
      67           0 : fd_exec_txn_ctx_delete( void * mem ) {
      68           0 :   if( FD_UNLIKELY( !mem ) ) {
      69           0 :     FD_LOG_WARNING(( "NULL mem" ));
      70           0 :     return NULL;
      71           0 :   }
      72             : 
      73           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_TXN_CTX_ALIGN) ) )  {
      74           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      75           0 :     return NULL;
      76           0 :   }
      77             : 
      78           0 :   fd_exec_txn_ctx_t * hdr = (fd_exec_txn_ctx_t *)mem;
      79           0 :   if( FD_UNLIKELY( hdr->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) {
      80           0 :     FD_LOG_WARNING(( "bad magic" ));
      81           0 :     return NULL;
      82           0 :   }
      83             : 
      84           0 :   FD_COMPILER_MFENCE();
      85           0 :   FD_VOLATILE( hdr->magic ) = 0UL;
      86           0 :   FD_COMPILER_MFENCE();
      87             : 
      88           0 :   return mem;
      89           0 : }
      90             : 
      91             : int
      92             : fd_exec_txn_ctx_get_account_at_index( fd_exec_txn_ctx_t *             ctx,
      93             :                                       ushort                          idx,
      94             :                                       fd_txn_account_t * *            account,
      95           0 :                                       fd_txn_account_condition_fn_t * condition ) {
      96           0 :   if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) {
      97           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
      98           0 :   }
      99             : 
     100           0 :   fd_txn_account_t * txn_account = &ctx->accounts[idx];
     101           0 :   *account = txn_account;
     102             : 
     103           0 :   if( FD_LIKELY( condition != NULL ) ) {
     104           0 :     if( FD_UNLIKELY( !condition( *account, ctx, idx ) ) ) {
     105           0 :       return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     106           0 :     }
     107           0 :   }
     108             : 
     109           0 :   return FD_ACC_MGR_SUCCESS;
     110           0 : }
     111             : 
     112             : int
     113             : fd_exec_txn_ctx_get_account_with_key( fd_exec_txn_ctx_t *             ctx,
     114             :                                       fd_pubkey_t const *             pubkey,
     115             :                                       fd_txn_account_t * *            account,
     116           0 :                                       fd_txn_account_condition_fn_t * condition ) {
     117           0 :   int index = fd_exec_txn_ctx_find_index_of_account( ctx, pubkey );
     118           0 :   if( FD_UNLIKELY( index==-1 ) ) {
     119           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     120           0 :   }
     121             : 
     122           0 :   return fd_exec_txn_ctx_get_account_at_index( ctx,
     123           0 :                                                (uchar)index,
     124           0 :                                                account,
     125           0 :                                                condition );
     126           0 : }
     127             : 
     128             : int
     129             : fd_exec_txn_ctx_get_executable_account( fd_exec_txn_ctx_t *             ctx,
     130             :                                         fd_pubkey_t const *             pubkey,
     131             :                                         fd_txn_account_t * *            account,
     132           0 :                                         fd_txn_account_condition_fn_t * condition ) {
     133             :   /* First try to fetch the executable account from the existing borrowed accounts.
     134             :      If the pubkey is in the account keys, then we want to re-use that
     135             :      borrowed account since it reflects changes from prior instructions. Referencing the
     136             :      read-only executable accounts list is incorrect behavior when the program
     137             :      data account is written to in a prior instruction (e.g. program upgrade + invoke within the same txn) */
     138           0 :   int err = fd_exec_txn_ctx_get_account_with_key( ctx, pubkey, account, condition );
     139           0 :   if( FD_UNLIKELY( err==FD_ACC_MGR_SUCCESS ) ) {
     140           0 :     return FD_ACC_MGR_SUCCESS;
     141           0 :   }
     142             : 
     143           0 :   for( ushort i=0; i<ctx->executable_cnt; i++ ) {
     144           0 :     if( memcmp( pubkey->uc, ctx->executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) )==0 ) {
     145           0 :       fd_txn_account_t * txn_account = &ctx->executable_accounts[i];
     146           0 :       *account = txn_account;
     147             : 
     148           0 :       if( FD_LIKELY( condition != NULL ) ) {
     149           0 :         if( FD_UNLIKELY( !condition( *account, ctx, i ) ) ) {
     150           0 :           return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     151           0 :         }
     152           0 :       }
     153             : 
     154           0 :       return FD_ACC_MGR_SUCCESS;
     155           0 :     }
     156           0 :   }
     157             : 
     158           0 :   return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     159           0 : }
     160             : 
     161             : int
     162             : fd_exec_txn_ctx_get_key_of_account_at_index( fd_exec_txn_ctx_t *  ctx,
     163             :                                              ushort               idx,
     164           0 :                                              fd_pubkey_t const * * key ) {
     165             :   /* Return a NotEnoughAccountKeys error if idx is out of bounds.
     166             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L218 */
     167           0 :   if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) {
     168           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     169           0 :   }
     170             : 
     171           0 :   *key = &ctx->account_keys[ idx ];
     172           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     173           0 : }
     174             : 
     175             : void
     176           0 : fd_exec_txn_ctx_setup_basic( fd_exec_txn_ctx_t * ctx ) {
     177           0 :   ctx->compute_unit_limit = 200000;
     178           0 :   ctx->compute_unit_price = 0;
     179           0 :   ctx->compute_meter      = 200000;
     180           0 :   ctx->prioritization_fee_type = FD_COMPUTE_BUDGET_PRIORITIZATION_FEE_TYPE_DEPRECATED;
     181           0 :   ctx->custom_err         = UINT_MAX;
     182             : 
     183           0 :   ctx->instr_stack_sz                  = 0;
     184           0 :   ctx->accounts_cnt                    = 0UL;
     185           0 :   ctx->executable_cnt                  = 0UL;
     186           0 :   ctx->paid_fees                       = 0UL;
     187           0 :   ctx->heap_size                       = FD_VM_HEAP_DEFAULT;
     188           0 :   ctx->loaded_accounts_data_size_limit = FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT;
     189           0 :   ctx->loaded_accounts_data_size       = 0UL;
     190           0 :   ctx->accounts_resize_delta           = 0UL;
     191           0 :   ctx->collected_rent                  = 0UL;
     192             : 
     193           0 :   ctx->num_instructions = 0;
     194           0 :   memset( ctx->return_data.program_id.key, 0, sizeof(fd_pubkey_t) );
     195           0 :   ctx->return_data.len = 0;
     196             : 
     197           0 :   ctx->dirty_vote_acc  = 0;
     198           0 :   ctx->dirty_stake_acc = 0;
     199           0 :   ctx->failed_instr    = NULL;
     200           0 :   ctx->instr_err_idx   = INT_MAX;
     201           0 :   ctx->capture_ctx     = NULL;
     202             : 
     203           0 :   ctx->instr_info_cnt     = 0UL;
     204           0 :   ctx->cpi_instr_info_cnt = 0UL;
     205           0 :   ctx->instr_trace_length = 0UL;
     206             : 
     207           0 :   ctx->exec_err      = 0;
     208           0 :   ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE;
     209           0 : }
     210             : 
     211             : void
     212             : fd_exec_txn_ctx_setup( fd_exec_txn_ctx_t   * ctx,
     213             :                        fd_txn_t      const * txn_descriptor,
     214           0 :                        fd_rawtxn_b_t const * txn_raw ) {
     215           0 :   fd_exec_txn_ctx_setup_basic( ctx );
     216           0 :   ctx->txn_descriptor   = txn_descriptor;
     217           0 :   ctx->_txn_raw->raw    = txn_raw->raw;
     218           0 :   ctx->_txn_raw->txn_sz = txn_raw->txn_sz;
     219           0 : }
     220             : 
     221             : void
     222           0 : fd_exec_txn_ctx_teardown( fd_exec_txn_ctx_t * ctx ) {
     223           0 :   (void)ctx;
     224           0 : }
     225             : 
     226             : void
     227           0 : fd_exec_txn_ctx_reset_return_data( fd_exec_txn_ctx_t * txn_ctx ) {
     228           0 :   txn_ctx->return_data.len = 0;
     229           0 : }
     230             : 
     231             : /* https://github.com/anza-xyz/agave/blob/v2.1.1/sdk/program/src/message/versions/v0/loaded.rs#L162 */
     232             : int
     233             : fd_txn_account_is_demotion( const int        idx,
     234             :                             const fd_txn_t * txn_descriptor,
     235           0 :                             const uint       bpf_upgradeable_in_txn ) {
     236           0 :   uint is_program = 0U;
     237           0 :   for( ulong j=0UL; j<txn_descriptor->instr_cnt; j++ ) {
     238           0 :     if( txn_descriptor->instr[j].program_id == idx ) {
     239           0 :       is_program = 1U;
     240           0 :       break;
     241           0 :     }
     242           0 :   }
     243             : 
     244           0 :   return (is_program && !bpf_upgradeable_in_txn);
     245           0 : }
     246             : 
     247             : uint
     248             : fd_txn_account_has_bpf_loader_upgradeable( const fd_pubkey_t * account_keys,
     249           0 :                                            const ulong         accounts_cnt ) {
     250           0 :   for( ulong j=0; j<accounts_cnt; j++ ) {
     251           0 :     const fd_pubkey_t * acc = &account_keys[j];
     252           0 :     if ( memcmp( acc->uc, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) == 0 ) {
     253           0 :       return 1U;
     254           0 :     }
     255           0 :   }
     256           0 :   return 0U;
     257           0 : }
     258             : 
     259             : /* This function aims to mimic the writable accounts check to populate the writable accounts cache, used
     260             :    to determine if accounts are writable or not.
     261             : 
     262             :    https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L38-L47 */
     263             : int
     264           0 : fd_exec_txn_ctx_account_is_writable_idx( fd_exec_txn_ctx_t const * txn_ctx, ushort idx ) {
     265           0 :   uint bpf_upgradeable = fd_txn_account_has_bpf_loader_upgradeable( txn_ctx->account_keys, txn_ctx->accounts_cnt );
     266           0 :   return fd_exec_txn_account_is_writable_idx_flat( txn_ctx->slot,
     267           0 :                                                    idx,
     268           0 :                                                    &txn_ctx->account_keys[idx],
     269           0 :                                                    txn_ctx->txn_descriptor,
     270           0 :                                                    &txn_ctx->features,
     271           0 :                                                    bpf_upgradeable );
     272           0 : }
     273             : 
     274             : int
     275             : fd_exec_txn_account_is_writable_idx_flat( const ulong           slot,
     276             :                                           const ushort          idx,
     277             :                                           const fd_pubkey_t *   addr_at_idx,
     278             :                                           const fd_txn_t *      txn_descriptor,
     279             :                                           const fd_features_t * features,
     280           0 :                                           const uint            bpf_upgradeable_in_txn ) {
     281             :   /* https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L43 */
     282           0 :   if( !fd_txn_is_writable( txn_descriptor, idx ) ) {
     283           0 :     return 0;
     284           0 :   }
     285             : 
     286             :   /* See comments in fd_system_ids.h.
     287             :      https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L44 */
     288           0 :   if( fd_pubkey_is_active_reserved_key( addr_at_idx ) ||
     289           0 :       ( FD_FEATURE_ACTIVE( slot, features, add_new_reserved_account_keys ) &&
     290           0 :                            fd_pubkey_is_pending_reserved_key( addr_at_idx ) ) ||
     291           0 :       ( FD_FEATURE_ACTIVE( slot, features, enable_secp256r1_precompile ) &&
     292           0 :                            fd_pubkey_is_secp256r1_key( addr_at_idx ) ) ) {
     293             : 
     294           0 :     return 0;
     295           0 :   }
     296             : 
     297           0 :   if( fd_txn_account_is_demotion( idx, txn_descriptor, bpf_upgradeable_in_txn ) ) {
     298           0 :     return 0;
     299           0 :   }
     300             : 
     301           0 :   return 1;
     302           0 : }
     303             : 
     304             : /* Account pre-condition filtering functions */
     305             : 
     306             : int
     307             : fd_txn_account_check_exists( fd_txn_account_t *        acc,
     308             :                              fd_exec_txn_ctx_t const * ctx,
     309           0 :                              ushort                    idx ) {
     310           0 :   (void) ctx;
     311           0 :   (void) idx;
     312           0 :   return fd_account_meta_exists( acc->vt->get_meta( acc ) );
     313           0 : }
     314             : 
     315             : int
     316             : fd_txn_account_check_is_writable( fd_txn_account_t *        acc,
     317             :                                   fd_exec_txn_ctx_t const * ctx,
     318           0 :                                   ushort                    idx ) {
     319           0 :   (void) acc;
     320           0 :   return fd_exec_txn_ctx_account_is_writable_idx( ctx, idx );
     321           0 : }
     322             : 
     323             : int
     324             : fd_txn_account_check_fee_payer_writable( fd_txn_account_t *        acc,
     325             :                                          fd_exec_txn_ctx_t const * ctx,
     326           0 :                                          ushort                    idx ) {
     327           0 :   (void) acc;
     328           0 :   return fd_txn_is_writable( ctx->txn_descriptor, idx );
     329           0 : }
     330             : 
     331             : int
     332             : fd_txn_account_check_borrow_mut( fd_txn_account_t *        acc,
     333             :                                  fd_exec_txn_ctx_t const * ctx,
     334           0 :                                  ushort                    idx ) {
     335           0 :   (void) ctx;
     336           0 :   (void) idx;
     337           0 :   return acc->vt->is_mutable( acc ) && acc->vt->try_borrow_mut( acc );
     338           0 : }

Generated by: LCOV version 1.14