LCOV - code coverage report
Current view: top level - flamenco/runtime/tests - fd_cost_harness.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 68 0.0 %
Date: 2026-07-17 05:22:26 Functions: 0 1 0.0 %

          Line data    Source code
       1             : #include "fd_solfuzz_private.h"
       2             : #include "fd_txn_harness.h"
       3             : #include "generated/cost.pb.h"
       4             : 
       5             : #include "../fd_cost_tracker.h"
       6             : #include "../program/fd_compute_budget_program.h"
       7             : 
       8             : ulong
       9             : fd_solfuzz_pb_cost_run( fd_solfuzz_runner_t * runner,
      10             :                         void const *          input_,
      11             :                         void **               output_,
      12             :                         void *                output_buf,
      13           0 :                         ulong                 output_bufsz ) {
      14           0 :   fd_exec_test_cost_context_t const * input  = fd_type_pun_const( input_ );
      15           0 :   fd_exec_test_cost_result_t **       output = fd_type_pun( output_ );
      16             : 
      17           0 :   if( FD_UNLIKELY( !input->has_tx || !input->has_features ) ) return 0UL;
      18             : 
      19           0 :   fd_banks_clear_bank( runner->banks, runner->bank, 64UL );
      20           0 :   runner->bank->f.slot = 1UL;
      21           0 :   FD_TEST( fd_solfuzz_pb_restore_features( &runner->bank->f.features, &input->features ) );
      22             : 
      23           0 :   fd_txn_p_t * txn_p = fd_spad_alloc( runner->spad, alignof(fd_txn_p_t), sizeof(fd_txn_p_t) );
      24           0 :   ulong txn_sz = fd_solfuzz_pb_txn_serialize( txn_p->payload, &input->tx );
      25           0 :   if( FD_UNLIKELY( txn_sz==ULONG_MAX ) ) return 0UL;
      26             : 
      27           0 :   txn_p->payload_sz = txn_sz;
      28           0 :   if( FD_UNLIKELY( !fd_txn_parse( txn_p->payload, txn_p->payload_sz, TXN( txn_p ), NULL ) ) ) {
      29           0 :     return 0UL;
      30           0 :   }
      31             : 
      32           0 :   fd_txn_in_t txn_in = {0};
      33           0 :   txn_in.txn = txn_p;
      34             : 
      35           0 :   fd_txn_out_t * txn_out = fd_spad_alloc( runner->spad, alignof(fd_txn_out_t), sizeof(fd_txn_out_t) );
      36           0 :   fd_memset( txn_out, 0, sizeof(fd_txn_out_t) );
      37           0 :   fd_compute_budget_details_new( &txn_out->details.compute_budget );
      38           0 :   txn_out->details.loaded_accounts_data_size = txn_out->details.compute_budget.loaded_accounts_data_size_limit;
      39           0 :   txn_out->details.is_simple_vote = fd_txn_is_simple_vote_transaction( TXN( txn_p ), txn_p->payload );
      40             : 
      41           0 :   int err = fd_executor_compute_budget_program_execute_instructions( runner->bank, &txn_in, txn_out );
      42           0 :   if( FD_LIKELY( !err ) ) err = fd_sanitize_compute_unit_limits( txn_out );
      43           0 :   if( FD_UNLIKELY( err ) ) return 0UL;
      44             : 
      45           0 :   if( input->mode==FD_EXEC_TEST_TXN_COST_MODE_ACTUAL ) {
      46           0 :     ulong actual_cost = (ulong)input->actual_programs_execution_cost;
      47           0 :     ulong limit = txn_out->details.compute_budget.compute_unit_limit;
      48           0 :     txn_out->details.compute_budget.compute_meter = fd_ulong_sat_sub( limit, fd_ulong_min( actual_cost, limit ) );
      49           0 :     txn_out->details.loaded_accounts_data_size = (ulong)input->actual_loaded_accounts_data_size_bytes;
      50           0 :   } else {
      51             :     /* In ESTIMATE mode, programs_execution_cost = compute_unit_limit (see
      52             :        agave cost_model.rs:get_estimated_execution_cost). fd_cost_tracker
      53             :        computes programs_execution_cost as (limit - compute_meter), so zero
      54             :        the meter here to yield the full limit. */
      55           0 :     txn_out->details.compute_budget.compute_meter = 0UL;
      56           0 :     txn_out->details.loaded_accounts_data_size = txn_out->details.compute_budget.loaded_accounts_data_size_limit;
      57           0 :   }
      58             : 
      59           0 :   fd_cost_tracker_calculate_cost( runner->bank, &txn_in, txn_out );
      60             : 
      61             :   /* In ACTUAL mode agave passes actual_programs_execution_cost through
      62             :      without clamping to compute_unit_limit (see agave cost_model.rs:
      63             :      calculate_cost_for_executed_transaction). The (limit - meter)
      64             :      formula in fd_cost_tracker inherently clamps, so overwrite with the
      65             :      raw actual value here for parity. */
      66           0 :   if( input->mode==FD_EXEC_TEST_TXN_COST_MODE_ACTUAL &&
      67           0 :       txn_out->details.txn_cost.type==FD_TXN_COST_TYPE_TRANSACTION ) {
      68           0 :     txn_out->details.txn_cost.transaction.programs_execution_cost = input->actual_programs_execution_cost;
      69           0 :   }
      70             : 
      71             :   /* Build output into the caller-provided scratch buffer */
      72           0 :   ulong output_end = (ulong)output_buf + output_bufsz;
      73           0 :   FD_SCRATCH_ALLOC_INIT( l, output_buf );
      74           0 :   fd_exec_test_cost_result_t * result =
      75           0 :     FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_cost_result_t), sizeof(fd_exec_test_cost_result_t) );
      76           0 :   FD_TEST( _l <= output_end );
      77           0 :   *result = (fd_exec_test_cost_result_t)FD_EXEC_TEST_COST_RESULT_INIT_ZERO;
      78             : 
      79           0 :   result->has_cost = 1;
      80           0 :   if( txn_out->details.txn_cost.type==FD_TXN_COST_TYPE_TRANSACTION ) {
      81           0 :     result->signature_cost = txn_out->details.txn_cost.transaction.signature_cost;
      82           0 :     result->write_lock_cost = txn_out->details.txn_cost.transaction.write_lock_cost;
      83           0 :     result->data_bytes_cost = txn_out->details.txn_cost.transaction.data_bytes_cost;
      84           0 :     result->programs_execution_cost = txn_out->details.txn_cost.transaction.programs_execution_cost;
      85           0 :     result->loaded_accounts_data_size_cost = txn_out->details.txn_cost.transaction.loaded_accounts_data_size_cost;
      86           0 :     result->allocated_accounts_data_size = txn_out->details.txn_cost.transaction.allocated_accounts_data_size;
      87           0 :   } else {
      88             :     /* Simple-vote branch: proto CostResult fields have to match agave's
      89             :        TransactionCost::SimpleVote component-wise (cost-model/src/
      90             :        transaction_cost.rs:48-51 and :86-93). The 2100 here is
      91             :        solana_vote_program::vote_processor::DEFAULT_COMPUTE_UNITS --
      92             :        the vote program's per-invocation cost. Components sum to
      93             :        FD_SIMPLE_VOTE_USAGE_COST (3428). */
      94           0 :     result->signature_cost = FD_PACK_COST_PER_SIGNATURE;
      95           0 :     result->write_lock_cost = FD_WRITE_LOCK_UNITS * 2UL;
      96           0 :     result->data_bytes_cost = 0UL;
      97           0 :     result->programs_execution_cost = 2100UL;
      98           0 :     result->loaded_accounts_data_size_cost = 8UL;
      99           0 :     result->allocated_accounts_data_size = 0UL;
     100           0 :   }
     101             :   /* Saturating add to match agave's UsageCostDetails::sum (transaction_cost.rs:
     102             :      saturating_add chain). Plain + wraps on u64::MAX inputs (e.g. adversarial
     103             :      actual_programs_execution_cost = u64::MAX). */
     104           0 :   result->total_cost = fd_ulong_sat_add( result->signature_cost, result->write_lock_cost );
     105           0 :   result->total_cost = fd_ulong_sat_add( result->total_cost, result->data_bytes_cost );
     106           0 :   result->total_cost = fd_ulong_sat_add( result->total_cost, result->programs_execution_cost );
     107           0 :   result->total_cost = fd_ulong_sat_add( result->total_cost, result->loaded_accounts_data_size_cost );
     108             : 
     109           0 :   ulong actual_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
     110           0 :   *output = result;
     111           0 :   return actual_end - (ulong)output_buf;
     112           0 : }

Generated by: LCOV version 1.14