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: 137 217 63.1 %
Date: 2025-01-08 12:08:44 Functions: 13 18 72.2 %

          Line data    Source code
       1             : #include "fd_exec_txn_ctx.h"
       2             : #include "fd_exec_slot_ctx.h"
       3             : #include "../fd_acc_mgr.h"
       4             : #include "../fd_executor.h"
       5             : #include "../../vm/fd_vm.h"
       6             : #include "../fd_account.h"
       7             : 
       8             : void *
       9      407859 : fd_exec_txn_ctx_new( void * mem ) {
      10      407859 :   if( FD_UNLIKELY( !mem ) ) {
      11           0 :     FD_LOG_WARNING(( "NULL mem" ));
      12           0 :     return NULL;
      13           0 :   }
      14             : 
      15      407859 :   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      407859 :   fd_exec_txn_ctx_t * self = (fd_exec_txn_ctx_t *) mem;
      21             : 
      22      407859 :   FD_COMPILER_MFENCE();
      23      407859 :   self->magic = FD_EXEC_TXN_CTX_MAGIC;
      24      407859 :   FD_COMPILER_MFENCE();
      25             : 
      26      407859 :   return mem;
      27      407859 : }
      28             : 
      29             : fd_exec_txn_ctx_t *
      30      395118 : fd_exec_txn_ctx_join( void * mem ) {
      31      395118 :   if( FD_UNLIKELY( !mem ) ) {
      32           0 :     FD_LOG_WARNING(( "NULL block" ));
      33           0 :     return NULL;
      34           0 :   }
      35             : 
      36      395118 :   fd_exec_txn_ctx_t * ctx = (fd_exec_txn_ctx_t *) mem;
      37             : 
      38      395118 :   if( FD_UNLIKELY( ctx->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) {
      39           0 :     FD_LOG_WARNING(( "bad magic" ));
      40           0 :     return NULL;
      41           0 :   }
      42             : 
      43      395118 :   return ctx;
      44      395118 : }
      45             : 
      46             : void *
      47           0 : fd_exec_txn_ctx_leave( fd_exec_txn_ctx_t * ctx) {
      48           0 :   if( FD_UNLIKELY( !ctx ) ) {
      49           0 :     FD_LOG_WARNING(( "NULL block" ));
      50           0 :     return NULL;
      51           0 :   }
      52             : 
      53           0 :   if( FD_UNLIKELY( ctx->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) {
      54           0 :     FD_LOG_WARNING(( "bad magic" ));
      55           0 :     return NULL;
      56           0 :   }
      57             : 
      58           0 :   return (void *) ctx;
      59           0 : }
      60             : 
      61             : void *
      62           0 : fd_exec_txn_ctx_delete( void * mem ) {
      63           0 :   if( FD_UNLIKELY( !mem ) ) {
      64           0 :     FD_LOG_WARNING(( "NULL mem" ));
      65           0 :     return NULL;
      66           0 :   }
      67             : 
      68           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_TXN_CTX_ALIGN) ) )  {
      69           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      70           0 :     return NULL;
      71           0 :   }
      72             : 
      73           0 :   fd_exec_txn_ctx_t * hdr = (fd_exec_txn_ctx_t *)mem;
      74           0 :   if( FD_UNLIKELY( hdr->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) {
      75           0 :     FD_LOG_WARNING(( "bad magic" ));
      76           0 :     return NULL;
      77           0 :   }
      78             : 
      79           0 :   FD_COMPILER_MFENCE();
      80           0 :   FD_VOLATILE( hdr->magic ) = 0UL;
      81           0 :   FD_COMPILER_MFENCE();
      82             : 
      83           0 :   return mem;
      84           0 : }
      85             : 
      86             : int
      87             : fd_txn_borrowed_account_view_idx( fd_exec_txn_ctx_t * ctx,
      88             :                                   uchar idx,
      89       96378 :                                   fd_borrowed_account_t * * account ) {
      90       96378 :   if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) {
      91           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
      92           0 :   }
      93             : 
      94       96378 :   fd_borrowed_account_t * txn_account = &ctx->borrowed_accounts[idx];
      95       96378 :   *account = txn_account;
      96             : 
      97       96378 :   if( FD_UNLIKELY( !fd_acc_exists( txn_account->const_meta ) ) ) {
      98        2265 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
      99        2265 :   }
     100             : 
     101       94113 :   return FD_ACC_MGR_SUCCESS;
     102       96378 : }
     103             : 
     104             : int
     105             : fd_txn_borrowed_account_view_idx_allow_dead( fd_exec_txn_ctx_t * ctx,
     106             :                                              uchar idx,
     107       10953 :                                              fd_borrowed_account_t * * account ) {
     108       10953 :   if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) {
     109           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     110           0 :   }
     111             : 
     112       10953 :   fd_borrowed_account_t * txn_account = &ctx->borrowed_accounts[idx];
     113       10953 :   *account = txn_account;
     114             : 
     115       10953 :   return FD_ACC_MGR_SUCCESS;
     116       10953 : }
     117             : 
     118             : int
     119             : fd_txn_borrowed_account_view( fd_exec_txn_ctx_t * ctx,
     120             :                               fd_pubkey_t const *      pubkey,
     121          93 :                               fd_borrowed_account_t * * account ) {
     122         309 :   for( ulong i = 0; i < ctx->accounts_cnt; i++ ) {
     123         309 :     if( memcmp( pubkey->uc, ctx->accounts[i].uc, sizeof(fd_pubkey_t) )==0 ) {
     124             :       // TODO: check if readable???
     125          93 :       fd_borrowed_account_t * txn_account = &ctx->borrowed_accounts[i];
     126          93 :       *account = txn_account;
     127             : 
     128          93 :       if( FD_UNLIKELY( !fd_acc_exists( txn_account->const_meta ) ) ) {
     129          87 :         return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     130          87 :       }
     131             : 
     132           6 :       return FD_ACC_MGR_SUCCESS;
     133          93 :     }
     134         309 :   }
     135             : 
     136           0 :   return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     137          93 : }
     138             : 
     139             : int
     140             : fd_txn_borrowed_account_executable_view( fd_exec_txn_ctx_t * ctx,
     141             :                                          fd_pubkey_t const *      pubkey,
     142         918 :                                          fd_borrowed_account_t * * account ) {
     143        1071 :   for( ulong i = 0; i < ctx->executable_cnt; i++ ) {
     144        1062 :     if( memcmp( pubkey->uc, ctx->executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) )==0 ) {
     145             :       // TODO: check if readable???
     146         909 :       fd_borrowed_account_t * txn_account = &ctx->executable_accounts[i];
     147         909 :       *account = txn_account;
     148             : 
     149         909 :       if( FD_UNLIKELY( !fd_acc_exists( txn_account->const_meta ) ) )
     150           0 :         return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     151             : 
     152         909 :       return FD_ACC_MGR_SUCCESS;
     153         909 :     }
     154        1062 :   }
     155             : 
     156           9 :   return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     157         918 : }
     158             : 
     159             : int
     160             : fd_txn_borrowed_account_modify_fee_payer( fd_exec_txn_ctx_t *       ctx, 
     161        6831 :                                           fd_borrowed_account_t * * account ) {
     162             : 
     163        6831 :   *account = &ctx->borrowed_accounts[ FD_FEE_PAYER_TXN_IDX ];
     164             : 
     165        6831 :   if( FD_UNLIKELY( !fd_txn_is_writable( ctx->txn_descriptor, FD_FEE_PAYER_TXN_IDX ) ) ) {
     166           0 :     return FD_ACC_MGR_ERR_WRITE_FAILED;
     167           0 :   }
     168        6831 :   return FD_ACC_MGR_SUCCESS;
     169        6831 : }
     170             : 
     171             : int
     172             : fd_txn_borrowed_account_modify_idx( fd_exec_txn_ctx_t *        ctx,
     173             :                                     uchar                      idx,
     174             :                                     ulong                      min_data_sz,
     175           0 :                                     fd_borrowed_account_t * *  account ) {
     176           0 :   if( idx >= ctx->accounts_cnt ) {
     177           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     178           0 :   }
     179             : 
     180           0 :   fd_borrowed_account_t * txn_account = &ctx->borrowed_accounts[idx];
     181           0 :   if( FD_UNLIKELY( !fd_txn_account_is_writable_idx( ctx, (int)idx ) ) ) {
     182           0 :     return FD_ACC_MGR_ERR_WRITE_FAILED;
     183           0 :   }
     184             : 
     185           0 :   if( min_data_sz > txn_account->const_meta->dlen ) {
     186           0 :     fd_borrowed_account_resize( txn_account, min_data_sz );
     187           0 :   }
     188             : 
     189           0 :   *account = txn_account;
     190           0 :   return FD_ACC_MGR_SUCCESS;
     191           0 : }
     192             : 
     193             : int
     194             : fd_txn_borrowed_account_modify( fd_exec_txn_ctx_t *       ctx,
     195             :                                 fd_pubkey_t const *       pubkey,
     196             :                                 ulong                     min_data_sz,
     197           0 :                                 fd_borrowed_account_t * * account ) {
     198           0 :   for( ulong i = 0; i < ctx->accounts_cnt; i++ ) {
     199           0 :     if( memcmp( pubkey->uc, ctx->accounts[i].uc, sizeof(fd_pubkey_t) )==0 ) {
     200             :       // TODO: check if writable???
     201           0 :       fd_borrowed_account_t * txn_account = &ctx->borrowed_accounts[i];
     202           0 :       if( min_data_sz > txn_account->const_meta->dlen ) {
     203           0 :         fd_borrowed_account_resize( txn_account, min_data_sz );
     204           0 :       }
     205           0 :       *account = txn_account;
     206           0 :       return FD_ACC_MGR_SUCCESS;
     207           0 :     }
     208           0 :   }
     209             : 
     210           0 :   return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     211           0 : }
     212             : 
     213             : void
     214      407859 : fd_exec_txn_ctx_setup_basic( fd_exec_txn_ctx_t * txn_ctx ) {
     215      407859 :   txn_ctx->compute_unit_limit = 200000;
     216      407859 :   txn_ctx->compute_unit_price = 0;
     217      407859 :   txn_ctx->compute_meter      = 200000;
     218      407859 :   txn_ctx->prioritization_fee_type = FD_COMPUTE_BUDGET_PRIORITIZATION_FEE_TYPE_DEPRECATED;
     219      407859 :   txn_ctx->custom_err         = UINT_MAX;
     220             : 
     221      407859 :   txn_ctx->instr_stack_sz     = 0;
     222      407859 :   txn_ctx->accounts_cnt       = 0;
     223      407859 :   txn_ctx->executable_cnt     = 0;
     224      407859 :   txn_ctx->paid_fees          = 0;
     225      407859 :   txn_ctx->heap_size          = FD_VM_HEAP_DEFAULT;
     226      407859 :   txn_ctx->loaded_accounts_data_size_limit = FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT;
     227      407859 :   txn_ctx->accounts_resize_delta = 0;
     228      407859 :   txn_ctx->collected_rent     = 0UL;
     229             : 
     230      407859 :   txn_ctx->num_instructions = 0;
     231      407859 :   memset( txn_ctx->return_data.program_id.key, 0, sizeof(fd_pubkey_t) );
     232      407859 :   txn_ctx->return_data.len = 0;
     233             : 
     234      407859 :   txn_ctx->dirty_vote_acc  = 0;
     235      407859 :   txn_ctx->dirty_stake_acc = 0;
     236      407859 :   txn_ctx->failed_instr    = NULL;
     237      407859 :   txn_ctx->instr_err_idx   = INT_MAX;
     238      407859 :   txn_ctx->capture_ctx     = NULL;
     239             : 
     240      407859 :   txn_ctx->instr_info_cnt     = 0;
     241      407859 :   txn_ctx->instr_trace_length = 0;
     242             : 
     243      407859 :   txn_ctx->exec_err      = 0;
     244      407859 :   txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_EBPF;
     245             :   
     246      407859 :   txn_ctx->has_program_id = 0;
     247      407859 : }
     248             : 
     249             : void
     250             : fd_exec_txn_ctx_setup( fd_exec_txn_ctx_t   * txn_ctx,
     251             :                        fd_txn_t      const * txn_descriptor,
     252       12741 :                        fd_rawtxn_b_t const * txn_raw ) {
     253       12741 :   fd_exec_txn_ctx_setup_basic( txn_ctx );
     254       12741 :   txn_ctx->txn_descriptor   = txn_descriptor;
     255       12741 :   txn_ctx->_txn_raw->raw    = txn_raw->raw;
     256       12741 :   txn_ctx->_txn_raw->txn_sz = txn_raw->txn_sz;
     257       12741 : }
     258             : 
     259             : void
     260           0 : fd_exec_txn_ctx_teardown( fd_exec_txn_ctx_t * txn_ctx ) {
     261           0 :   (void)txn_ctx;
     262           0 : }
     263             : 
     264             : void
     265             : fd_exec_txn_ctx_from_exec_slot_ctx( fd_exec_slot_ctx_t * slot_ctx,
     266      407859 :                                     fd_exec_txn_ctx_t * txn_ctx ) {
     267      407859 :   txn_ctx->slot_ctx = slot_ctx;
     268      407859 :   txn_ctx->epoch_ctx = slot_ctx->epoch_ctx;
     269      407859 :   txn_ctx->funk_txn = NULL;
     270      407859 :   txn_ctx->acc_mgr = slot_ctx->acc_mgr;
     271      407859 : }
     272             : 
     273             : void
     274       68793 : fd_exec_txn_ctx_reset_return_data( fd_exec_txn_ctx_t * txn_ctx ) {
     275       68793 :   txn_ctx->return_data.len = 0;
     276       68793 : }
     277             : 
     278             : /* https://github.com/anza-xyz/agave/blob/v2.1.1/sdk/program/src/message/versions/v0/loaded.rs#L162 */
     279             : int
     280             : fd_txn_account_is_demotion( fd_exec_txn_ctx_t const * txn_ctx, int idx )
     281      118596 : {
     282      118596 :   uint is_program = 0U;
     283      314025 :   for( ulong j=0UL; j<txn_ctx->txn_descriptor->instr_cnt; j++ ) {
     284      216885 :     if( txn_ctx->txn_descriptor->instr[j].program_id == idx ) {
     285       21456 :       is_program = 1U;
     286       21456 :       break;
     287       21456 :     }
     288      216885 :   }
     289             : 
     290      118596 :   uint bpf_upgradeable_in_txn = 0U;
     291     1459209 :   for( ulong j = 0; j < txn_ctx->accounts_cnt; j++ ) {
     292     1358691 :     const fd_pubkey_t * acc = &txn_ctx->accounts[j];
     293     1358691 :     if ( memcmp( acc->uc, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) == 0 ) {
     294       18078 :       bpf_upgradeable_in_txn = 1U;
     295       18078 :       break;
     296       18078 :     }
     297     1358691 :   }
     298      118596 :   return (is_program && !bpf_upgradeable_in_txn);
     299      118596 : }
     300             : 
     301             : int
     302      166962 : fd_txn_account_is_writable_idx( fd_exec_txn_ctx_t const * txn_ctx, int idx ) {
     303             : 
     304      166962 :   int acct_addr_cnt = txn_ctx->txn_descriptor->acct_addr_cnt;
     305      166962 :   if( txn_ctx->txn_descriptor->transaction_version == FD_TXN_V0 ) {
     306      157473 :     acct_addr_cnt += txn_ctx->txn_descriptor->addr_table_adtl_cnt;
     307      157473 :   }
     308             : 
     309      166962 :   if( idx==acct_addr_cnt ) {
     310           3 :     return 0;
     311           3 :   }
     312             : 
     313      166959 :   if( fd_pubkey_is_active_reserved_key(&txn_ctx->accounts[idx] ) ||
     314      166959 :       ( FD_FEATURE_ACTIVE( txn_ctx->slot_ctx, add_new_reserved_account_keys ) && 
     315      119763 :                            fd_pubkey_is_pending_reserved_key( &txn_ctx->accounts[idx] ) )) {
     316       48363 :     return 0;
     317       48363 :   }
     318             : 
     319      118596 :   if( fd_txn_account_is_demotion( txn_ctx, idx ) ) {
     320       20148 :     return 0;
     321       20148 :   }
     322             : 
     323       98448 :   return fd_txn_is_writable( txn_ctx->txn_descriptor, idx );
     324      118596 : }

Generated by: LCOV version 1.14