LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_cost_tracker.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 43 299 14.4 %
Date: 2025-10-17 04:46:03 Functions: 4 17 23.5 %

          Line data    Source code
       1             : #include "fd_cost_tracker.h"
       2             : #include "fd_system_ids.h"
       3             : #include "fd_bank.h"
       4             : #include "../features/fd_features.h"
       5             : 
       6             : struct account_cost {
       7             :   fd_pubkey_t account;
       8             :   ulong       cost;
       9             : 
      10             :   struct {
      11             :     ulong next;
      12             :   } map;
      13             : };
      14             : 
      15             : typedef struct account_cost account_cost_t;
      16             : 
      17             : #define MAP_NAME               account_cost_map
      18             : #define MAP_KEY_T              fd_pubkey_t
      19             : #define MAP_ELE_T              account_cost_t
      20           0 : #define MAP_KEY                account
      21           0 : #define MAP_KEY_EQ(k0,k1)      (fd_pubkey_eq( k0, k1 ))
      22           0 : #define MAP_KEY_HASH(key,seed) (fd_hash( seed, key, sizeof(fd_pubkey_t) ))
      23           0 : #define MAP_NEXT               map.next
      24             : #include "../../util/tmpl/fd_map_chain.c"
      25             : 
      26             : struct cost_tracker_outer {
      27             :   fd_cost_tracker_t cost_tracker[1];
      28             :   ulong             pool_offset;
      29             :   ulong             accounts_used;
      30             :   ulong             magic;
      31             : };
      32             : 
      33             : typedef struct cost_tracker_outer cost_tracker_outer_t;
      34             : 
      35             : FD_FN_CONST ulong
      36         108 : fd_cost_tracker_align( void ) {
      37         108 :   return FD_COST_TRACKER_ALIGN;
      38         108 : }
      39             : 
      40             : FD_FN_CONST ulong
      41           9 : fd_cost_tracker_footprint( void ) {
      42           9 :   ulong map_chain_cnt = account_cost_map_chain_cnt_est( FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_SLOT );
      43             : 
      44           9 :   ulong l = FD_LAYOUT_INIT;
      45           9 :   l = FD_LAYOUT_APPEND( l,  fd_cost_tracker_align(),  sizeof(cost_tracker_outer_t) );
      46           9 :   l = FD_LAYOUT_APPEND( l,  account_cost_map_align(), account_cost_map_footprint( map_chain_cnt ) );
      47           9 :   l = FD_LAYOUT_APPEND( l,  alignof(account_cost_t),  FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_SLOT*sizeof(account_cost_t) );
      48           9 :   return FD_LAYOUT_FINI( l, fd_cost_tracker_align() );
      49           9 : }
      50             : 
      51             : void *
      52             : fd_cost_tracker_new( void * shmem,
      53          18 :                      ulong  seed ) {
      54          18 :   if( FD_UNLIKELY( !shmem ) ) {
      55           3 :     FD_LOG_WARNING(( "NULL shmem" ));
      56           3 :     return NULL;
      57           3 :   }
      58             : 
      59          15 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_cost_tracker_align() ) ) ) {
      60           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
      61           0 :     return NULL;
      62           0 :   }
      63             : 
      64          15 :   ulong map_chain_cnt = account_cost_map_chain_cnt_est( FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_SLOT );
      65             : 
      66          15 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      67          15 :   cost_tracker_outer_t * cost_tracker = FD_SCRATCH_ALLOC_APPEND( l, fd_cost_tracker_align(),  sizeof(cost_tracker_outer_t) );
      68          15 :   void * _map                         = FD_SCRATCH_ALLOC_APPEND( l, account_cost_map_align(), account_cost_map_footprint( map_chain_cnt ) );
      69          15 :   void * _accounts                    = FD_SCRATCH_ALLOC_APPEND( l, alignof(account_cost_t),  FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_SLOT*sizeof(account_cost_t) );
      70             : 
      71           0 :   account_cost_map_t * map = account_cost_map_join( account_cost_map_new( _map, map_chain_cnt, seed ) );
      72          15 :   FD_TEST( map );
      73             : 
      74          15 :   cost_tracker->pool_offset = (ulong)_accounts-(ulong)cost_tracker;
      75             : 
      76          15 :   (void)_accounts;
      77             : 
      78          15 :   FD_COMPILER_MFENCE();
      79          15 :   FD_VOLATILE( cost_tracker->magic ) = FD_COST_TRACKER_MAGIC;
      80          15 :   FD_COMPILER_MFENCE();
      81             : 
      82          15 :   return shmem;
      83          15 : }
      84             : 
      85             : fd_cost_tracker_t *
      86          21 : fd_cost_tracker_join( void * shct ) {
      87          21 :   if( FD_UNLIKELY( !shct ) ) {
      88           3 :     FD_LOG_WARNING(( "NULL mem" ));
      89           3 :     return NULL;
      90           3 :   }
      91             : 
      92          18 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shct, fd_cost_tracker_align() ) ) ) {
      93           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      94           0 :     return NULL;
      95           0 :   }
      96             : 
      97          18 :   cost_tracker_outer_t * cost_tracker = (cost_tracker_outer_t *)shct;
      98             : 
      99          18 :   if( FD_UNLIKELY( cost_tracker->magic!=FD_COST_TRACKER_MAGIC ) ) {
     100           3 :     FD_LOG_WARNING(( "Invalid cost tracker magic" ));
     101           3 :     return NULL;
     102           3 :   }
     103             : 
     104          15 :   return cost_tracker->cost_tracker;
     105          18 : }
     106             : 
     107             : ulong
     108           0 : fd_cost_tracker_block_cost_limit( fd_bank_t const * bank ) {
     109           0 :   fd_features_t const * features = fd_bank_features_query( bank );
     110           0 :   ulong slot = fd_bank_slot_get( bank );
     111             : 
     112           0 :   if( FD_FEATURE_ACTIVE( slot, features, raise_block_limits_to_100m ) ) return FD_MAX_BLOCK_UNITS_SIMD_0286;
     113           0 :   else if( FD_FEATURE_ACTIVE( slot, features, raise_block_limits_to_60m ) ) return FD_MAX_BLOCK_UNITS_SIMD_0256;
     114           0 :   else return FD_MAX_BLOCK_UNITS_SIMD_0207;
     115           0 : }
     116             : 
     117             : void
     118             : fd_cost_tracker_init( fd_cost_tracker_t *   cost_tracker,
     119             :                       fd_features_t const * features,
     120           0 :                       ulong                 slot ) {
     121           0 :   if( FD_FEATURE_ACTIVE( slot, features, raise_block_limits_to_100m ) ) {
     122           0 :     cost_tracker->block_cost_limit   = FD_MAX_BLOCK_UNITS_SIMD_0286;
     123           0 :     cost_tracker->vote_cost_limit    = FD_MAX_VOTE_UNITS;
     124           0 :     cost_tracker->account_cost_limit = FD_MAX_WRITABLE_ACCOUNT_UNITS;
     125           0 :   } else if( FD_FEATURE_ACTIVE( slot, features, raise_block_limits_to_60m ) ) {
     126           0 :     cost_tracker->block_cost_limit   = FD_MAX_BLOCK_UNITS_SIMD_0256;
     127           0 :     cost_tracker->vote_cost_limit    = FD_MAX_VOTE_UNITS;
     128           0 :     cost_tracker->account_cost_limit = FD_MAX_WRITABLE_ACCOUNT_UNITS;
     129           0 :   } else {
     130           0 :     cost_tracker->block_cost_limit   = FD_MAX_BLOCK_UNITS_SIMD_0207;
     131           0 :     cost_tracker->vote_cost_limit    = FD_MAX_VOTE_UNITS;
     132           0 :     cost_tracker->account_cost_limit = FD_MAX_WRITABLE_ACCOUNT_UNITS;
     133           0 :   }
     134             : 
     135             :   /* https://github.com/anza-xyz/agave/blob/v3.0.1/runtime/src/bank.rs#L4059-L4066 */
     136           0 :   if( FD_FEATURE_ACTIVE( slot, features, raise_account_cu_limit ) ) {
     137           0 :     cost_tracker->account_cost_limit = fd_ulong_sat_mul( cost_tracker->block_cost_limit, 40UL ) / 100UL;
     138           0 :   }
     139             : 
     140           0 :   cost_tracker->block_cost                   = 0UL;
     141           0 :   cost_tracker->vote_cost                    = 0UL;
     142           0 :   cost_tracker->allocated_accounts_data_size = 0UL;
     143             : 
     144           0 :   cost_tracker_outer_t * outer = fd_type_pun( cost_tracker );
     145           0 :   outer->accounts_used = 0UL;
     146           0 :   account_cost_map_reset( fd_type_pun( outer+1UL ) );
     147           0 : }
     148             : 
     149             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L313-L321 */
     150             : FD_FN_PURE static inline ulong
     151           0 : get_instructions_data_cost( fd_exec_txn_ctx_t const * txn_ctx ) {
     152           0 :   ulong total_instr_data_sz = 0UL;
     153           0 :   for( ushort i=0; i<TXN( &txn_ctx->txn )->instr_cnt; i++ ) {
     154           0 :     total_instr_data_sz += TXN( &txn_ctx->txn )->instr[ i ].data_sz;
     155           0 :   }
     156           0 :   return total_instr_data_sz / FD_PACK_INV_COST_PER_INSTR_DATA_BYTE;
     157           0 : }
     158             : 
     159             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L152-L187 */
     160             : FD_FN_PURE static inline ulong
     161           0 : get_signature_cost( fd_exec_txn_ctx_t const * txn_ctx ) {
     162           0 :   fd_txn_t const *       txn      = TXN( &txn_ctx->txn );
     163           0 :   void const *           payload  = txn_ctx->txn.payload;
     164           0 :   fd_acct_addr_t const * accounts = fd_txn_get_acct_addrs( txn, payload );
     165             : 
     166             :   /* Compute signature counts (both normal + precompile)
     167             :      TODO: Factor this logic out into a shared function that can be used
     168             :      both here and in fd_pack_cost.h */
     169           0 :   ulong signature_cost                       = fd_ulong_sat_mul( txn->signature_cnt, FD_PACK_COST_PER_SIGNATURE );
     170           0 :   ulong num_secp256k1_instruction_signatures = 0UL;
     171           0 :   ulong num_ed25519_instruction_signatures   = 0UL;
     172           0 :   ulong num_secp256r1_instruction_signatures = 0UL;
     173             : 
     174           0 :   for( ushort i=0; i<txn->instr_cnt; i++ ) {
     175           0 :     fd_txn_instr_t const * instr = &txn->instr[ i ];
     176           0 :     if( instr->data_sz==0UL ) continue;
     177             : 
     178           0 :     fd_acct_addr_t const * prog_id    = accounts + instr->program_id;
     179           0 :     uchar const *          instr_data = fd_txn_get_instr_data( instr, payload );
     180             : 
     181           0 :     if( fd_memeq( prog_id, fd_solana_ed25519_sig_verify_program_id.key, sizeof(fd_pubkey_t) ) ) {
     182           0 :       num_ed25519_instruction_signatures += (ulong)instr_data[ 0 ];
     183           0 :     } else if( fd_memeq( prog_id, fd_solana_keccak_secp_256k_program_id.key, sizeof(fd_pubkey_t) ) ) {
     184           0 :       num_secp256k1_instruction_signatures += (ulong)instr_data[ 0 ];
     185           0 :     } else if( fd_memeq( prog_id, fd_solana_secp256r1_program_id.key, sizeof(fd_pubkey_t) ) ) {
     186           0 :       num_secp256r1_instruction_signatures += (ulong)instr_data[ 0 ];
     187           0 :     }
     188           0 :   }
     189             : 
     190             :   /* No direct permalink, just factored out for readability */
     191           0 :   ulong secp256k1_verify_cost = fd_ulong_sat_mul( FD_PACK_COST_PER_SECP256K1_SIGNATURE, num_secp256k1_instruction_signatures );
     192             : 
     193             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L155-L160 */
     194           0 :   ulong ed25519_verify_cost;
     195           0 :   if( FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, ed25519_precompile_verify_strict ) ) {
     196           0 :     ed25519_verify_cost = fd_ulong_sat_mul( FD_PACK_COST_PER_ED25519_SIGNATURE, num_ed25519_instruction_signatures );
     197           0 :   } else {
     198           0 :     ed25519_verify_cost = fd_ulong_sat_mul( FD_PACK_COST_PER_NON_STRICT_ED25519_SIGNATURE, num_ed25519_instruction_signatures );
     199           0 :   }
     200             : 
     201             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L162-L167 */
     202           0 :   ulong secp256r1_verify_cost = 0UL;
     203           0 :   if( FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, enable_secp256r1_precompile ) ) {
     204           0 :     secp256r1_verify_cost = fd_ulong_sat_mul( FD_PACK_COST_PER_SECP256R1_SIGNATURE, num_secp256r1_instruction_signatures );
     205           0 :   }
     206             : 
     207             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L169-L186 */
     208           0 :   return fd_ulong_sat_add( signature_cost,
     209           0 :                            fd_ulong_sat_add( secp256k1_verify_cost,
     210           0 :                                              fd_ulong_sat_add( ed25519_verify_cost,
     211           0 :                                                                secp256r1_verify_cost ) ) );
     212           0 : }
     213             : 
     214             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L190-L192 */
     215             : FD_FN_PURE static inline ulong
     216           0 : get_write_lock_cost( ulong num_write_locks ) {
     217           0 :   return fd_ulong_sat_mul( num_write_locks, FD_WRITE_LOCK_UNITS );
     218           0 : }
     219             : 
     220             : /* Loop through all instructions here and deserialize the instruction data to try to determine any
     221             :    system program allocations done.
     222             : 
     223             :    https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L367-L386 */
     224             : static inline ulong
     225           0 : calculate_allocated_accounts_data_size( fd_exec_txn_ctx_t const * txn_ctx ) {
     226           0 :   fd_txn_t const * txn     = TXN( &txn_ctx->txn );
     227           0 :   void const *     payload = txn_ctx->txn.payload;
     228             : 
     229           0 :   ulong allocated_accounts_data_size = 0UL;
     230           0 :   for( ushort i=0; i<txn->instr_cnt; i++ ) {
     231           0 :     fd_txn_instr_t const * instr      = &txn->instr[ i ];
     232           0 :     fd_acct_addr_t const * accounts   = fd_txn_get_acct_addrs( txn, payload );
     233           0 :     fd_acct_addr_t const * prog_id    = accounts + instr->program_id;
     234           0 :     uchar const *          instr_data = fd_txn_get_instr_data( instr, payload );
     235             : 
     236           0 :     if( instr->data_sz==0UL || !fd_memeq( prog_id, &fd_solana_system_program_id, sizeof(fd_pubkey_t) ) ) continue;
     237             : 
     238           0 :     fd_bincode_decode_ctx_t ctx = {
     239           0 :       .data    = instr_data,
     240           0 :       .dataend = instr_data + instr->data_sz,
     241           0 :     };
     242             : 
     243           0 :     ulong total_sz = 0UL;
     244           0 :     int err = fd_system_program_instruction_decode_footprint( &ctx, &total_sz );
     245           0 :     if( FD_UNLIKELY( err ) ) continue;
     246             : 
     247           0 :     uchar buf[total_sz];
     248           0 :     fd_system_program_instruction_t * instruction = fd_system_program_instruction_decode( buf, &ctx );
     249           0 :     if( FD_UNLIKELY( !instruction ) ) continue;
     250             : 
     251             :     /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L330-L346 */
     252           0 :     ulong space = 0UL;
     253             : 
     254           0 :     switch( instruction->discriminant ) {
     255           0 :       case fd_system_program_instruction_enum_create_account: {
     256           0 :         space = instruction->inner.create_account.space;
     257           0 :         break;
     258           0 :       }
     259           0 :       case fd_system_program_instruction_enum_create_account_with_seed: {
     260           0 :         space = instruction->inner.create_account_with_seed.space;
     261           0 :         break;
     262           0 :       }
     263           0 :       case fd_system_program_instruction_enum_allocate: {
     264           0 :         space = instruction->inner.allocate;
     265           0 :         break;
     266           0 :       }
     267           0 :       case fd_system_program_instruction_enum_allocate_with_seed: {
     268           0 :         space = instruction->inner.allocate_with_seed.space;
     269           0 :         break;
     270           0 :       }
     271           0 :     }
     272             : 
     273             :     /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L373-L380 */
     274           0 :     if( FD_UNLIKELY( space>FD_RUNTIME_ACC_SZ_MAX ) ) return 0UL;
     275             : 
     276           0 :     allocated_accounts_data_size = fd_ulong_sat_add( allocated_accounts_data_size, space );
     277           0 :   }
     278             : 
     279             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L396-L397 */
     280           0 :   return fd_ulong_min( 2UL*FD_RUNTIME_ACC_SZ_MAX, allocated_accounts_data_size );
     281           0 : }
     282             : 
     283             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L123-L149 */
     284             : static inline fd_transaction_cost_t
     285             : calculate_non_vote_transaction_cost( fd_exec_txn_ctx_t const * txn_ctx,
     286             :                                      ulong                     loaded_accounts_data_size_cost,
     287           0 :                                      ulong                     data_bytes_cost ) {
     288             : 
     289             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L132 */
     290           0 :   ulong signature_cost = get_signature_cost( txn_ctx );
     291             : 
     292             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L133 */
     293           0 :   ulong write_lock_cost = get_write_lock_cost( fd_txn_account_cnt( TXN( &txn_ctx->txn ), FD_TXN_ACCT_CAT_WRITABLE ) );
     294             : 
     295             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L135-L136 */
     296           0 :   ulong allocated_accounts_data_size = calculate_allocated_accounts_data_size( txn_ctx );
     297             : 
     298           0 :   return (fd_transaction_cost_t){ .discriminant = fd_transaction_cost_enum_transaction,
     299           0 :                                   .inner = {
     300           0 :                                     .transaction = {
     301           0 :                                       .signature_cost                 = signature_cost,
     302           0 :                                       .write_lock_cost                = write_lock_cost,
     303           0 :                                       .data_bytes_cost                = data_bytes_cost,
     304           0 :                                       .programs_execution_cost        = fd_ulong_sat_sub( txn_ctx->compute_budget_details.compute_unit_limit,
     305           0 :                                                                                           txn_ctx->compute_budget_details.compute_meter ),
     306           0 :                                       .loaded_accounts_data_size_cost = loaded_accounts_data_size_cost,
     307           0 :                                       .allocated_accounts_data_size   = allocated_accounts_data_size,
     308           0 :                                     }
     309           0 :                                   }
     310           0 :                                 };
     311           0 : }
     312             : 
     313             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/transaction_cost.rs#L26-L42 */
     314             : FD_FN_PURE static inline ulong
     315           0 : transaction_cost_sum( fd_transaction_cost_t const * txn_cost ) {
     316           0 :   switch( txn_cost->discriminant ) {
     317           0 :     case fd_transaction_cost_enum_simple_vote: {
     318             :       /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/transaction_cost.rs#L38 */
     319           0 :       return FD_PACK_SIMPLE_VOTE_COST;
     320           0 :     }
     321           0 :     case fd_transaction_cost_enum_transaction: {
     322             :       /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/transaction_cost.rs#L164-L171 */
     323           0 :       fd_usage_cost_details_t const * usage_cost = &txn_cost->inner.transaction;
     324           0 :       ulong                           cost       = 0UL;
     325             : 
     326           0 :       cost = fd_ulong_sat_add( cost, usage_cost->signature_cost );
     327           0 :       cost = fd_ulong_sat_add( cost, usage_cost->write_lock_cost );
     328           0 :       cost = fd_ulong_sat_add( cost, usage_cost->data_bytes_cost );
     329           0 :       cost = fd_ulong_sat_add( cost, usage_cost->programs_execution_cost );
     330           0 :       cost = fd_ulong_sat_add( cost, usage_cost->loaded_accounts_data_size_cost );
     331             : 
     332           0 :       return cost;
     333           0 :     }
     334           0 :     default: {
     335           0 :       __builtin_unreachable();
     336           0 :     }
     337           0 :   }
     338           0 : }
     339             : 
     340             : FD_FN_PURE static inline ulong
     341           0 : get_allocated_accounts_data_size( fd_transaction_cost_t const * txn_cost ) {
     342           0 :   switch( txn_cost->discriminant ) {
     343           0 :     case fd_transaction_cost_enum_simple_vote:
     344           0 :       return 0UL;
     345           0 :     case fd_transaction_cost_enum_transaction:
     346           0 :       return txn_cost->inner.transaction.allocated_accounts_data_size;
     347           0 :     default:
     348           0 :       __builtin_unreachable();
     349           0 :   }
     350           0 : }
     351             : 
     352             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L277-L322 */
     353             : static inline int
     354             : would_fit( fd_cost_tracker_t const *     cost_tracker,
     355             :            fd_exec_txn_ctx_t const *     txn_ctx,
     356           0 :            fd_transaction_cost_t const * tx_cost ) {
     357             : 
     358             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L281 */
     359           0 :   ulong cost = transaction_cost_sum( tx_cost );
     360             : 
     361             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L283-L288 */
     362           0 :   if( fd_transaction_cost_is_simple_vote( tx_cost ) ) {
     363           0 :     if( FD_UNLIKELY( fd_ulong_sat_add( cost_tracker->vote_cost, cost )>cost_tracker->vote_cost_limit ) ) {
     364           0 :       return FD_COST_TRACKER_ERROR_WOULD_EXCEED_VOTE_MAX_LIMIT;
     365           0 :     }
     366           0 :   }
     367             : 
     368             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L290-L293 */
     369           0 :   if( FD_UNLIKELY( fd_ulong_sat_add( cost_tracker->block_cost, cost )>cost_tracker->block_cost_limit ) ) {
     370           0 :     return FD_COST_TRACKER_ERROR_WOULD_EXCEED_BLOCK_MAX_LIMIT;
     371           0 :   }
     372             : 
     373             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L295-L298 */
     374           0 :   if( FD_UNLIKELY( cost>cost_tracker->account_cost_limit ) ) {
     375           0 :     return FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_MAX_LIMIT;
     376           0 :   }
     377             : 
     378             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L300-L301 */
     379           0 :   ulong allocated_accounts_data_size = fd_ulong_sat_add( cost_tracker->allocated_accounts_data_size,
     380           0 :                                                          get_allocated_accounts_data_size( tx_cost ) );
     381             : 
     382             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L303-L304 */
     383           0 :   if( FD_UNLIKELY( allocated_accounts_data_size>FD_MAX_BLOCK_ACCOUNTS_DATA_SIZE_DELTA ) ) {
     384           0 :     return FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_DATA_BLOCK_LIMIT;
     385           0 :   }
     386             : 
     387             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L308-L319 */
     388             : 
     389           0 :   account_cost_map_t const * map = fd_type_pun_const(((cost_tracker_outer_t const *)cost_tracker)+1UL);
     390           0 :   account_cost_t const * pool = fd_type_pun_const( (void*)((ulong)cost_tracker + ((cost_tracker_outer_t const *)cost_tracker)->pool_offset) );
     391             : 
     392           0 :   for( ulong i=0UL; i<txn_ctx->accounts_cnt; i++ ) {
     393           0 :     if( !fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, (ushort)i ) ) continue;
     394             : 
     395           0 :     fd_pubkey_t const * writable_acc = &txn_ctx->account_keys[i];
     396             : 
     397           0 :     account_cost_t const * chained_cost = account_cost_map_ele_query_const( map, writable_acc, NULL, pool );
     398           0 :     if( FD_UNLIKELY( chained_cost && fd_ulong_sat_add( chained_cost->cost, cost )>cost_tracker->account_cost_limit ) ) {
     399           0 :       return FD_COST_TRACKER_ERROR_WOULD_EXCEED_ACCOUNT_MAX_LIMIT;
     400           0 :     }
     401           0 :   }
     402             : 
     403           0 :   return FD_COST_TRACKER_SUCCESS;
     404           0 : }
     405             : 
     406             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L352-L372 */
     407             : static inline void
     408             : add_transaction_execution_cost( fd_cost_tracker_t *           _cost_tracker,
     409             :                                 fd_exec_txn_ctx_t const *     txn_ctx,
     410             :                                 fd_transaction_cost_t const * tx_cost,
     411           0 :                                 ulong                         adjustment ) {
     412           0 :   cost_tracker_outer_t * cost_tracker = fd_type_pun( _cost_tracker );
     413           0 :   account_cost_map_t * map = fd_type_pun( cost_tracker+1UL );
     414           0 :   account_cost_t * pool = fd_type_pun( (void*)((ulong)cost_tracker+cost_tracker->pool_offset) );
     415             : 
     416           0 :   for( ulong i=0UL; i<txn_ctx->accounts_cnt; i++ ) {
     417           0 :     if( FD_LIKELY( !fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, (ushort)i ) ) ) continue;
     418             : 
     419           0 :     fd_pubkey_t const * writable_acc = &txn_ctx->account_keys[i];
     420             : 
     421           0 :     account_cost_t * account_cost = account_cost_map_ele_query( map, writable_acc, NULL, pool );
     422           0 :     if( FD_UNLIKELY( !account_cost ) ) {
     423           0 :       FD_TEST( cost_tracker->accounts_used<FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_SLOT );
     424             : 
     425           0 :       account_cost = pool+cost_tracker->accounts_used;
     426           0 :       cost_tracker->accounts_used++;
     427             : 
     428           0 :       account_cost->account = *writable_acc;
     429           0 :       account_cost->cost    = adjustment;
     430             : 
     431           0 :       account_cost_map_ele_insert( map, account_cost, pool );
     432           0 :     } else {
     433           0 :       account_cost->cost = fd_ulong_sat_add( account_cost->cost, adjustment );
     434           0 :     }
     435           0 :   }
     436             : 
     437           0 :   cost_tracker->cost_tracker->block_cost = fd_ulong_sat_add( cost_tracker->cost_tracker->block_cost, adjustment );
     438           0 :   if( FD_UNLIKELY( fd_transaction_cost_is_simple_vote( tx_cost ) ) ) {
     439           0 :     cost_tracker->cost_tracker->vote_cost = fd_ulong_sat_add( cost_tracker->cost_tracker->vote_cost, adjustment );
     440           0 :   }
     441           0 : }
     442             : 
     443             : /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L325-L335 */
     444             : static inline void
     445             : add_transaction_cost( fd_cost_tracker_t *           cost_tracker,
     446             :                       fd_exec_txn_ctx_t const *     txn_ctx,
     447           0 :                       fd_transaction_cost_t const * tx_cost ) {
     448             :   /* Note: We purposely omit signature counts updates since they're not relevant to cost calculations right now. */
     449           0 :   cost_tracker->allocated_accounts_data_size += get_allocated_accounts_data_size( tx_cost );
     450           0 :   add_transaction_execution_cost( cost_tracker, txn_ctx, tx_cost, transaction_cost_sum( tx_cost ) );
     451           0 : }
     452             : 
     453             : int
     454             : fd_cost_tracker_calculate_cost_and_add( fd_cost_tracker_t *       cost_tracker,
     455           0 :                                         fd_exec_txn_ctx_t const * txn_ctx ) {
     456           0 :   if( FD_UNLIKELY( !txn_ctx ) ) {
     457           0 :     return FD_COST_TRACKER_SUCCESS;
     458           0 :   }
     459             : 
     460             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/cost-model/src/cost_model.rs#L83-L85 */
     461           0 :   fd_transaction_cost_t txn_cost;
     462           0 :   if( fd_txn_is_simple_vote_transaction( TXN( &txn_ctx->txn ), txn_ctx->txn.payload ) ) {
     463           0 :     txn_cost = (fd_transaction_cost_t){ .discriminant = fd_transaction_cost_enum_simple_vote };
     464           0 :   } else {
     465             :     /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L78-L81 */
     466           0 :     ulong loaded_accounts_data_size_cost = fd_cost_tracker_calculate_loaded_accounts_data_size_cost( txn_ctx );
     467             : 
     468             :     /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L82-L83 */
     469           0 :     ulong instructions_data_cost = get_instructions_data_cost( txn_ctx );
     470             : 
     471             :     /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L85-L93 */
     472           0 :     txn_cost = calculate_non_vote_transaction_cost( txn_ctx, loaded_accounts_data_size_cost, instructions_data_cost );
     473           0 :   }
     474             : 
     475             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L167 */
     476           0 :   int err = would_fit( cost_tracker, txn_ctx, &txn_cost );
     477           0 :   if( FD_UNLIKELY( err ) ) return err;
     478             : 
     479             :   /* We don't need `updated_costliest_account_cost` since it seems to be
     480             :      for a different use case other than validating block cost limits.
     481             :      https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_tracker.rs#L168 */
     482           0 :   add_transaction_cost( cost_tracker, txn_ctx, &txn_cost );
     483           0 :   return FD_COST_TRACKER_SUCCESS;
     484           0 : }

Generated by: LCOV version 1.14