LCOV - code coverage report
Current view: top level - flamenco/runtime/tests - fd_solfuzz_exec.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 254 0.0 %
Date: 2025-09-19 04:41:14 Functions: 0 10 0.0 %

          Line data    Source code
       1             : /* fd_solfuzz_exec.c contains internal executors */
       2             : 
       3             : #include "fd_solfuzz_private.h"
       4             : #include "generated/block.pb.h"
       5             : #include "generated/invoke.pb.h"
       6             : #include "generated/txn.pb.h"
       7             : #include "generated/vm.pb.h"
       8             : #include "generated/elf.pb.h"
       9             : #include "../fd_executor_err.h"
      10             : #include <assert.h>
      11             : 
      12             : /*
      13             :  * fixtures
      14             :  */
      15             : 
      16             : static int
      17             : sol_compat_cmp_binary_strict( void const * effects,
      18             :                               void const * expected,
      19             :                               pb_msgdesc_t const * encode_type,
      20           0 :                               fd_spad_t * spad ) {
      21           0 : #define MAX_SZ 32*1024*1024
      22           0 : FD_SPAD_FRAME_BEGIN( spad ) {
      23           0 :   if( effects==NULL ) {
      24           0 :     FD_LOG_WARNING(( "No output effects" ));
      25           0 :     return 0;
      26           0 :   }
      27             : 
      28             :   /* Note: Most likely this spad allocation won't fail. If it does, you may need to bump
      29             :      the allocated spad memory amount in fd_exec_sol_compat.c. */
      30           0 :   ulong out_sz = MAX_SZ;
      31           0 :   uchar * out = fd_spad_alloc( spad, 1UL, out_sz );
      32           0 :   if( !sol_compat_encode( out, &out_sz, effects, encode_type ) ) {
      33           0 :     FD_LOG_WARNING(( "Error encoding effects" ));
      34           0 :     return 0;
      35           0 :   }
      36             : 
      37           0 :   ulong exp_sz = MAX_SZ;
      38           0 :   uchar * exp = fd_spad_alloc( spad, 1UL, exp_sz );
      39           0 :   if( !sol_compat_encode( exp, &exp_sz, expected, encode_type ) ) {
      40           0 :     FD_LOG_WARNING(( "Error encoding expected" ));
      41           0 :     return 0;
      42           0 :   }
      43             : 
      44           0 :   if( out_sz!=exp_sz ) {
      45           0 :     FD_LOG_WARNING(( "Binary cmp failed: different size. out_sz=%lu exp_sz=%lu", out_sz, exp_sz  ));
      46           0 :     return 0;
      47           0 :   }
      48           0 :   if( !fd_memeq( out, exp, out_sz ) ) {
      49           0 :     FD_LOG_WARNING(( "Binary cmp failed: different values." ));
      50           0 :     return 0;
      51           0 :   }
      52             : 
      53           0 :   return 1;
      54           0 : } FD_SPAD_FRAME_END;
      55           0 : #undef MAX_SIZE
      56           0 : }
      57             : 
      58             : static int
      59             : _diff_txn_acct( fd_exec_test_acct_state_t * expected,
      60           0 :                 fd_exec_test_acct_state_t * actual ) {
      61             :   /* AcctState -> address (This must hold true when calling this function!) */
      62           0 :   assert( fd_memeq( expected->address, actual->address, sizeof(fd_pubkey_t) ) );
      63             : 
      64             :   /* AcctState -> lamports */
      65           0 :   if( expected->lamports != actual->lamports ) {
      66           0 :     FD_LOG_WARNING(( "Lamports mismatch: expected=%lu actual=%lu", expected->lamports, actual->lamports ));
      67           0 :     return 0;
      68           0 :   }
      69             : 
      70             :   /* AcctState -> data */
      71           0 :   if( expected->data != NULL || actual->data != NULL ) {
      72           0 :     if( expected->data == NULL ) {
      73           0 :       FD_LOG_WARNING(( "Expected account data is NULL, actual is non-NULL" ));
      74           0 :       return 0;
      75           0 :     }
      76             : 
      77           0 :     if( actual->data == NULL ) {
      78           0 :       FD_LOG_WARNING(( "Expected account data is NULL, actual is non-NULL" ));
      79           0 :       return 0;
      80           0 :     }
      81             : 
      82           0 :     if( expected->data->size != actual->data->size ) {
      83           0 :       FD_LOG_WARNING(( "Account data size mismatch: expected=%u actual=%u", expected->data->size, actual->data->size ));
      84           0 :       return 0;
      85           0 :     }
      86             : 
      87           0 :     if( !fd_memeq( expected->data->bytes, actual->data->bytes, expected->data->size ) ) {
      88           0 :       FD_LOG_WARNING(( "Account data mismatch" ));
      89           0 :       return 0;
      90           0 :     }
      91           0 :   }
      92             : 
      93             :   /* AcctState -> executable */
      94           0 :   if( expected->executable != actual->executable ) {
      95           0 :     FD_LOG_WARNING(( "Executable mismatch: expected=%d actual=%d", expected->executable, actual->executable ));
      96           0 :     return 0;
      97           0 :   }
      98             : 
      99             :   /* AcctState -> owner */
     100           0 :   if( !fd_memeq( expected->owner, actual->owner, sizeof(fd_pubkey_t) ) ) {
     101           0 :     char a[ FD_BASE58_ENCODED_32_SZ ];
     102           0 :     char b[ FD_BASE58_ENCODED_32_SZ ];
     103           0 :     FD_LOG_WARNING(( "Owner mismatch: expected=%s, actual=%s", fd_acct_addr_cstr( a, expected->owner ), fd_acct_addr_cstr( b, actual->owner ) ));
     104           0 :     return 0;
     105           0 :   }
     106             : 
     107           0 :   return 1;
     108           0 : }
     109             : 
     110             : 
     111             : static int
     112             : _diff_resulting_states( fd_exec_test_resulting_state_t *  expected,
     113           0 :                         fd_exec_test_resulting_state_t *  actual ) {
     114             :   // Verify that the number of accounts are the same
     115           0 :   if( expected->acct_states_count != actual->acct_states_count ) {
     116           0 :     FD_LOG_WARNING(( "Account states count mismatch: expected=%u actual=%u", expected->acct_states_count, actual->acct_states_count ));
     117           0 :     return 0;
     118           0 :   }
     119             : 
     120             :   // Verify that the account states are the same
     121           0 :   for( ulong i = 0; i < expected->acct_states_count; ++i ) {
     122           0 :     for( ulong j = 0; j < actual->acct_states_count; ++j ) {
     123           0 :       if( fd_memeq( expected->acct_states[i].address, actual->acct_states[j].address, sizeof(fd_pubkey_t) ) ) {
     124           0 :         if( !_diff_txn_acct( &expected->acct_states[i], &actual->acct_states[j] ) ) {
     125           0 :           return 0;
     126           0 :         }
     127           0 :       }
     128           0 :     }
     129           0 :   }
     130             : 
     131             :   // TODO: resulting_state -> rent_debits, resulting_state->transaction_rent
     132           0 :   return 1;
     133           0 : }
     134             : 
     135             : static int
     136             : sol_compat_cmp_txn( fd_exec_test_txn_result_t *  expected,
     137           0 :                     fd_exec_test_txn_result_t *  actual ) {
     138             :   /* TxnResult -> executed */
     139           0 :   if( expected->executed != actual->executed ) {
     140           0 :     FD_LOG_WARNING(( "Executed mismatch: expected=%d actual=%d", expected->executed, actual->executed ));
     141           0 :     return 0;
     142           0 :   }
     143             : 
     144             :   /* TxnResult -> sanitization_error */
     145           0 :   if( expected->sanitization_error != actual->sanitization_error ) {
     146           0 :     FD_LOG_WARNING(( "Sanitization error mismatch: expected=%d actual=%d", expected->sanitization_error, actual->sanitization_error ));
     147           0 :     return 0;
     148           0 :   }
     149             : 
     150             :   /* TxnResult -> resulting_state */
     151           0 :   if( !_diff_resulting_states( &expected->resulting_state, &actual->resulting_state ) ) {
     152           0 :     return 0;
     153           0 :   }
     154             : 
     155             :   /* TxnResult -> rent */
     156           0 :   if( expected->rent != actual->rent ) {
     157           0 :     FD_LOG_WARNING(( "Rent mismatch: expected=%lu actual=%lu", expected->rent, actual->rent ));
     158           0 :     return 0;
     159           0 :   }
     160             : 
     161             :   /* TxnResult -> is_ok */
     162           0 :   if( expected->is_ok != actual->is_ok ) {
     163           0 :     FD_LOG_WARNING(( "Is ok mismatch: expected=%d actual=%d", expected->is_ok, actual->is_ok ));
     164           0 :     return 0;
     165           0 :   }
     166             : 
     167             :   /* TxnResult -> status */
     168           0 :   if( expected->status != actual->status ) {
     169           0 :     FD_LOG_WARNING(( "Status mismatch: expected=%u actual=%u", expected->status, actual->status ));
     170           0 :     return 0;
     171           0 :   }
     172             : 
     173             :   /* TxnResult -> instruction_error */
     174           0 :   if( expected->instruction_error != actual->instruction_error ) {
     175           0 :     FD_LOG_WARNING(( "Instruction error mismatch: expected=%u actual=%u", expected->instruction_error, actual->instruction_error ));
     176           0 :     return 0;
     177           0 :   }
     178             : 
     179           0 :   if( expected->instruction_error ) {
     180             :     /* TxnResult -> instruction_error_index */
     181           0 :     if( expected->instruction_error_index != actual->instruction_error_index ) {
     182           0 :       FD_LOG_WARNING(( "Instruction error index mismatch: expected=%u actual=%u", expected->instruction_error_index, actual->instruction_error_index ));
     183           0 :       return 0;
     184           0 :     }
     185             : 
     186             :     /* TxnResult -> custom_error */
     187           0 :     if( expected->instruction_error == (ulong) -FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && expected->custom_error != actual->custom_error ) {
     188           0 :       FD_LOG_WARNING(( "Custom error mismatch: expected=%u actual=%u", expected->custom_error, actual->custom_error ));
     189           0 :       return 0;
     190           0 :     }
     191           0 :   }
     192             : 
     193             :   /* TxnResult -> return_data */
     194           0 :   if( expected->return_data != NULL || actual->return_data != NULL ) {
     195           0 :     if( expected->return_data == NULL ) {
     196           0 :       FD_LOG_WARNING(( "Expected return data is NULL, actual is non-NULL" ));
     197           0 :       return 0;
     198           0 :     }
     199             : 
     200           0 :     if( actual->return_data == NULL ) {
     201           0 :       FD_LOG_WARNING(( "Expected return data is NULL, actual is non-NULL" ));
     202           0 :       return 0;
     203           0 :     }
     204             : 
     205           0 :     if( expected->return_data->size != actual->return_data->size ) {
     206           0 :       FD_LOG_WARNING(( "Return data size mismatch: expected=%u actual=%u", expected->return_data->size, actual->return_data->size ));
     207           0 :       return 0;
     208           0 :     }
     209             : 
     210           0 :     if( !fd_memeq( expected->return_data->bytes, actual->return_data->bytes, expected->return_data->size ) ) {
     211           0 :       FD_LOG_WARNING(( "Return data mismatch" ));
     212           0 :       return 0;
     213           0 :     }
     214           0 :   }
     215             : 
     216             :   /* TxnResult -> executed_units */
     217           0 :   if( expected->executed_units != actual->executed_units ) {
     218           0 :     FD_LOG_WARNING(( "Executed units mismatch: expected=%lu actual=%lu", expected->executed_units, actual->executed_units ));
     219           0 :     return 0;
     220           0 :   }
     221             : 
     222             :   /* TxnResult -> fee_details */
     223           0 :   if( expected->has_fee_details != actual->has_fee_details ) {
     224           0 :     FD_LOG_WARNING(( "Has fee details mismatch: expected=%d actual=%d", expected->has_fee_details, actual->has_fee_details ));
     225           0 :     return 0;
     226           0 :   }
     227             : 
     228           0 :   if( expected->has_fee_details ) {
     229           0 :     if( expected->fee_details.transaction_fee != actual->fee_details.transaction_fee ) {
     230           0 :       FD_LOG_WARNING(( "Transaction fee mismatch: expected=%lu actual=%lu", expected->fee_details.transaction_fee, actual->fee_details.transaction_fee ));
     231           0 :       return 0;
     232           0 :     }
     233             : 
     234           0 :     if( expected->fee_details.prioritization_fee != actual->fee_details.prioritization_fee ) {
     235           0 :       FD_LOG_WARNING(( "Priority fee mismatch: expected=%lu actual=%lu", expected->fee_details.prioritization_fee, actual->fee_details.prioritization_fee ));
     236           0 :       return 0;
     237           0 :     }
     238           0 :   }
     239             : 
     240             :   /* TxnResult -> loaded_accounts_data_size */
     241           0 :   if( expected->loaded_accounts_data_size != actual->loaded_accounts_data_size ) {
     242           0 :     FD_LOG_WARNING(( "Loaded accounts data size mismatch: expected=%lu actual=%lu", expected->loaded_accounts_data_size, actual->loaded_accounts_data_size ));
     243           0 :     return 0;
     244           0 :   }
     245             : 
     246           0 :   return 1;
     247           0 : }
     248             : 
     249             : int
     250             : fd_solfuzz_instr_fixture( fd_solfuzz_runner_t * runner,
     251             :                           uchar const *         in,
     252           0 :                           ulong                 in_sz ) {
     253             :   // Decode fixture
     254           0 :   fd_exec_test_instr_fixture_t fixture[1] = {0};
     255           0 :   void * res = sol_compat_decode_lenient( &fixture, in, in_sz, &fd_exec_test_instr_fixture_t_msg );
     256           0 :   if( !res ) {
     257           0 :     FD_LOG_WARNING(( "Invalid instr fixture." ));
     258           0 :     return 0;
     259           0 :   }
     260             : 
     261           0 :   int ok = 0;
     262             :   // Execute
     263           0 :   void * output = NULL;
     264           0 :   fd_solfuzz_execute_wrapper( runner, &fixture->input, &output, fd_solfuzz_instr_run );
     265             : 
     266             :   // Compare effects
     267           0 :   ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_instr_effects_t_msg, runner->spad );
     268             : 
     269             :   // Cleanup
     270           0 :   pb_release( &fd_exec_test_instr_fixture_t_msg, fixture );
     271           0 :   return ok;
     272           0 : }
     273             : 
     274             : int
     275             : fd_solfuzz_txn_fixture( fd_solfuzz_runner_t * runner,
     276             :                         uchar const *         in,
     277           0 :                         ulong                 in_sz ) {
     278             :   // Decode fixture
     279           0 :   fd_exec_test_txn_fixture_t fixture[1] = {0};
     280           0 :   void * res = sol_compat_decode_lenient( &fixture, in, in_sz, &fd_exec_test_txn_fixture_t_msg );
     281           0 :   if( !res ) {
     282           0 :     FD_LOG_WARNING(( "Invalid txn fixture." ));
     283           0 :     return 0;
     284           0 :   }
     285             : 
     286           0 :   fd_spad_push( runner->spad );
     287           0 :   int ok = 0;
     288           0 :   void * output = NULL;
     289           0 :   fd_solfuzz_execute_wrapper( runner, &fixture->input, &output, fd_solfuzz_txn_run );
     290           0 :   if( FD_LIKELY( output ) ) {
     291             :     // Compare effects
     292           0 :     fd_exec_test_txn_result_t * effects = output;
     293           0 :     ok = sol_compat_cmp_txn( &fixture->output, effects );
     294           0 :   }
     295           0 :   fd_spad_pop( runner->spad );
     296             : 
     297             :   // Cleanup
     298           0 :   pb_release( &fd_exec_test_txn_fixture_t_msg, fixture );
     299           0 :   return ok;
     300           0 : }
     301             : 
     302             : int
     303             : fd_solfuzz_block_fixture( fd_solfuzz_runner_t * runner,
     304             :                           uchar const *         in,
     305           0 :                           ulong                 in_sz ) {
     306             :   // Decode fixture
     307           0 :   fd_exec_test_block_fixture_t fixture[1] = {0};
     308           0 :   void * res = sol_compat_decode_lenient( &fixture, in, in_sz, &fd_exec_test_block_fixture_t_msg );
     309           0 :   if( !res ) {
     310           0 :     FD_LOG_WARNING(( "Invalid block fixture" ));
     311           0 :     return 0;
     312           0 :   }
     313             : 
     314           0 :   fd_spad_push( runner->spad );
     315           0 :   void * output = NULL;
     316           0 :   fd_solfuzz_execute_wrapper( runner, &fixture->input, &output, fd_solfuzz_block_run );
     317           0 :   int ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_block_effects_t_msg, runner->spad );
     318           0 :   fd_spad_pop( runner->spad );
     319             : 
     320             :   // Cleanup
     321           0 :   pb_release( &fd_exec_test_block_fixture_t_msg, fixture );
     322           0 :   return ok;
     323           0 : }
     324             : 
     325             : int
     326             : fd_solfuzz_elf_loader_fixture( fd_solfuzz_runner_t * runner,
     327             :                                uchar const *         in,
     328           0 :                                ulong                 in_sz ) {
     329             :   // Decode fixture
     330           0 :   fd_exec_test_elf_loader_fixture_t fixture[1] = {0};
     331           0 :   void * res = sol_compat_decode_lenient( &fixture, in, in_sz, &fd_exec_test_elf_loader_fixture_t_msg );
     332           0 :   if( !res ) {
     333           0 :     FD_LOG_WARNING(( "Invalid elf_loader fixture." ));
     334           0 :     return 0;
     335           0 :   }
     336             : 
     337           0 :   fd_spad_push( runner->spad );
     338           0 :   void * output = NULL;
     339           0 :   fd_solfuzz_execute_wrapper( runner, &fixture->input, &output, fd_solfuzz_elf_loader_run );
     340           0 :   int ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_elf_loader_effects_t_msg, runner->spad );
     341           0 :   fd_spad_pop( runner->spad );
     342             : 
     343             :   // Cleanup
     344           0 :   pb_release( &fd_exec_test_elf_loader_fixture_t_msg, fixture );
     345           0 :   return ok;
     346           0 : }
     347             : 
     348             : int
     349             : fd_solfuzz_syscall_fixture( fd_solfuzz_runner_t * runner,
     350             :                             uchar const *         in,
     351           0 :                             ulong                 in_sz ) {
     352             :   // Decode fixture
     353           0 :   fd_exec_test_syscall_fixture_t fixture[1] = {0};
     354           0 :   if( !sol_compat_decode_lenient( &fixture, in, in_sz, &fd_exec_test_syscall_fixture_t_msg ) ) {
     355           0 :     FD_LOG_WARNING(( "Invalid syscall fixture." ));
     356           0 :     return 0;
     357           0 :   }
     358             : 
     359           0 :   fd_spad_push( runner->spad );
     360           0 :   void * output = NULL;
     361           0 :   fd_solfuzz_execute_wrapper( runner, &fixture->input, &output, fd_solfuzz_syscall_run );
     362           0 :   int ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_syscall_effects_t_msg, runner->spad );
     363           0 :   fd_spad_pop( runner->spad );
     364             : 
     365             :   // Cleanup
     366           0 :   pb_release( &fd_exec_test_syscall_fixture_t_msg, fixture );
     367           0 :   return ok;
     368           0 : }
     369             : 
     370             : int
     371             : fd_solfuzz_vm_interp_fixture( fd_solfuzz_runner_t * runner,
     372             :                               uchar const *         in,
     373           0 :                               ulong                 in_sz ) {
     374             :   // Decode fixture
     375           0 :   fd_exec_test_syscall_fixture_t fixture[1] = {0};
     376           0 :   if( !sol_compat_decode_lenient( &fixture, in, in_sz, &fd_exec_test_syscall_fixture_t_msg ) ) {
     377           0 :     FD_LOG_WARNING(( "Invalid syscall fixture." ));
     378           0 :     return 0;
     379           0 :   }
     380             : 
     381           0 :   fd_spad_push( runner->spad );
     382           0 :   void * output = NULL;
     383           0 :   fd_solfuzz_execute_wrapper( runner, &fixture->input, &output, fd_solfuzz_vm_interp_run );
     384           0 :   int ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_syscall_effects_t_msg, runner->spad );
     385           0 :   fd_spad_pop( runner->spad );
     386             : 
     387             :   // Cleanup
     388           0 :   pb_release( &fd_exec_test_syscall_fixture_t_msg, fixture );
     389           0 :   return ok;
     390           0 : }

Generated by: LCOV version 1.14