LCOV - code coverage report
Current view: top level - flamenco/runtime/tests - fd_instr_harness.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 305 0.0 %
Date: 2025-10-27 04:40:00 Functions: 0 3 0.0 %

          Line data    Source code
       1             : #undef FD_SPAD_USE_HANDHOLDING
       2             : #define FD_SPAD_USE_HANDHOLDING 1
       3             : 
       4             : #include "fd_solfuzz_private.h"
       5             : #include "fd_instr_harness.h"
       6             : #include "../fd_executor.h"
       7             : #include "../context/fd_exec_txn_ctx.h"
       8             : #include "../program/fd_bpf_loader_program.h"
       9             : #include "../sysvar/fd_sysvar.h"
      10             : #include "../sysvar/fd_sysvar_clock.h"
      11             : #include "../sysvar/fd_sysvar_epoch_schedule.h"
      12             : #include "../sysvar/fd_sysvar_recent_hashes.h"
      13             : #include "../sysvar/fd_sysvar_rent.h"
      14             : #include "../sysvar/fd_sysvar_last_restart_slot.h"
      15             : #include "../fd_system_ids.h"
      16             : #include <assert.h>
      17             : 
      18             : int
      19             : fd_runtime_fuzz_instr_ctx_create( fd_solfuzz_runner_t *                runner,
      20             :                                   fd_exec_instr_ctx_t *                ctx,
      21             :                                   fd_exec_test_instr_context_t const * test_ctx,
      22           0 :                                   bool                                 is_syscall ) {
      23             : 
      24           0 :   memset( ctx, 0, sizeof(fd_exec_instr_ctx_t) );
      25             : 
      26           0 :   fd_funk_t * funk = runner->accdb->funk;
      27             : 
      28             :   /* Generate unique ID for funk txn */
      29             : 
      30           0 :   fd_funk_txn_xid_t xid[1] = {{ .ul={ LONG_MAX, LONG_MAX } }};
      31             : 
      32             :   /* Create temporary funk transaction and txn / slot / epoch contexts */
      33             : 
      34           0 :   fd_funk_txn_xid_t parent_xid; fd_funk_txn_xid_set_root( &parent_xid );
      35           0 :   fd_accdb_attach_child        ( runner->accdb_admin,     &parent_xid, xid );
      36           0 :   fd_progcache_txn_attach_child( runner->progcache_admin, &parent_xid, xid );
      37             : 
      38             :   /* Allocate contexts */
      39           0 :   uchar *             txn_ctx_mem = fd_spad_alloc( runner->spad,FD_EXEC_TXN_CTX_ALIGN,   FD_EXEC_TXN_CTX_FOOTPRINT   );
      40           0 :   fd_exec_txn_ctx_t * txn_ctx     = fd_exec_txn_ctx_join  ( fd_exec_txn_ctx_new  ( txn_ctx_mem ), runner->spad, fd_wksp_containing( runner->spad ) );
      41             : 
      42           0 :   ctx->txn_ctx = txn_ctx;
      43             : 
      44             :   /* Bank manager */
      45           0 :   fd_banks_clear_bank( runner->banks, runner->bank );
      46             : 
      47           0 :   fd_features_t * features = fd_bank_features_modify( runner->bank );
      48           0 :   fd_exec_test_feature_set_t const * feature_set = &test_ctx->epoch_context.features;
      49           0 :   if( !fd_runtime_fuzz_restore_features( features, feature_set ) ) {
      50           0 :     return 0;
      51           0 :   }
      52             : 
      53             :   /* Setup vote states accounts */
      54           0 :   fd_vote_states_t * vote_states = fd_vote_states_join( fd_vote_states_new( fd_bank_vote_states_locking_modify( runner->bank ), 4UL, 999UL ) );
      55           0 :   if( FD_UNLIKELY( !vote_states ) ) FD_LOG_ERR(( "fd_vote_states_new failed" ));
      56           0 :   fd_bank_vote_states_end_locking_modify( runner->bank );
      57             : 
      58           0 :   fd_vote_states_t * vote_states_prev = fd_vote_states_join( fd_vote_states_new( fd_bank_vote_states_prev_locking_modify( runner->bank ), 4UL, 999UL ) );
      59           0 :   if( FD_UNLIKELY( !vote_states_prev ) ) FD_LOG_ERR(( "fd_vote_states_new for prev failed" ));
      60           0 :   fd_bank_vote_states_prev_end_locking_modify( runner->bank );
      61             : 
      62           0 :   fd_vote_states_t * vote_states_prev_prev = fd_vote_states_join( fd_vote_states_new( fd_bank_vote_states_prev_prev_locking_modify( runner->bank ), 4UL, 999UL ) );
      63           0 :   if( FD_UNLIKELY( !vote_states_prev_prev ) ) FD_LOG_ERR(( "fd_vote_staets_new for prev2 failed" ));
      64           0 :   fd_bank_vote_states_prev_prev_end_locking_modify( runner->bank );
      65             : 
      66             :   /* Blockhash queue init */
      67             : 
      68           0 :   ulong blockhash_seed; FD_TEST( fd_rng_secure( &blockhash_seed, sizeof(ulong) ) );
      69           0 :   fd_blockhashes_t * blockhashes = fd_blockhashes_init( fd_bank_block_hash_queue_modify( runner->bank ), blockhash_seed );
      70           0 :   fd_memset( fd_blockhash_deq_push_tail_nocopy( blockhashes->d.deque ), 0, sizeof(fd_hash_t) );
      71             : 
      72             :   /* Set up mock txn descriptor */
      73           0 :   fd_txn_p_t * txn                    = fd_spad_alloc_check( runner->spad, fd_txn_align(), fd_txn_footprint( 1UL, 0UL ) );
      74           0 :   fd_txn_t *   txn_descriptor         = TXN( txn );
      75           0 :   txn_descriptor->transaction_version = FD_TXN_V0;
      76           0 :   txn_descriptor->acct_addr_cnt       = (ushort)test_ctx->accounts_count;
      77             : 
      78           0 :   uchar * progcache_scratch = fd_spad_alloc_check( runner->spad, FD_PROGCACHE_SCRATCH_ALIGN, FD_PROGCACHE_SCRATCH_FOOTPRINT );
      79             : 
      80           0 :   fd_exec_txn_ctx_setup( runner->bank,
      81           0 :                          runner->accdb->funk->shmem,
      82           0 :                          runner->progcache->funk->shmem,
      83           0 :                          xid,
      84           0 :                          NULL,
      85           0 :                          txn_ctx,
      86           0 :                          NULL,
      87           0 :                          progcache_scratch,
      88           0 :                          FD_PROGCACHE_SCRATCH_FOOTPRINT );
      89           0 :   fd_exec_txn_ctx_setup_basic( txn_ctx );
      90             : 
      91           0 :   txn_ctx->txn                                       = *txn;
      92           0 :   txn_ctx->compute_budget_details.compute_unit_limit = test_ctx->cu_avail;
      93           0 :   txn_ctx->compute_budget_details.compute_meter      = test_ctx->cu_avail;
      94           0 :   txn_ctx->spad                                      = runner->spad;
      95           0 :   txn_ctx->instr_info_cnt                            = 1UL;
      96           0 :   txn_ctx->fuzz_config.enable_vm_tracing             = runner->enable_vm_tracing;
      97             : 
      98             :   /* Set up instruction context */
      99             : 
     100           0 :   fd_instr_info_t * info = fd_spad_alloc( runner->spad, 8UL, sizeof(fd_instr_info_t) );
     101           0 :   assert( info );
     102           0 :   memset( info, 0, sizeof(fd_instr_info_t) );
     103             : 
     104           0 :   if( test_ctx->data ) {
     105           0 :     info->data_sz = (ushort)test_ctx->data->size;
     106           0 :     info->data    = test_ctx->data->bytes;
     107           0 :   }
     108             : 
     109           0 :   txn_ctx->instr_infos[ 0UL ] = *info;
     110             : 
     111             :   /* Prepare borrowed account table (correctly handles aliasing) */
     112             : 
     113           0 :   if( FD_UNLIKELY( test_ctx->accounts_count > MAX_TX_ACCOUNT_LOCKS ) ) {
     114           0 :     FD_LOG_NOTICE(( "too many accounts" ));
     115           0 :     return 0;
     116           0 :   }
     117             : 
     118             :   /* Load accounts into database */
     119             : 
     120           0 :   fd_txn_account_t * accts = txn_ctx->accounts;
     121           0 :   fd_memset( accts, 0, test_ctx->accounts_count * sizeof(fd_txn_account_t) );
     122           0 :   txn_ctx->accounts_cnt = test_ctx->accounts_count;
     123             : 
     124           0 :   int has_program_id = 0;
     125             : 
     126           0 :   for( ulong j=0UL; j < test_ctx->accounts_count; j++ ) {
     127           0 :     fd_pubkey_t * acc_key = (fd_pubkey_t *)test_ctx->accounts[j].address;
     128             : 
     129           0 :     memcpy(  &(txn_ctx->account_keys[j]), test_ctx->accounts[j].address, sizeof(fd_pubkey_t) );
     130           0 :     if( !fd_runtime_fuzz_load_account( &accts[j], funk, xid, &test_ctx->accounts[j], 0 ) ) {
     131           0 :       return 0;
     132           0 :     }
     133             : 
     134           0 :     fd_txn_account_t * acc = &accts[j];
     135           0 :     if( fd_txn_account_get_meta( acc ) ) {
     136           0 :       uchar *             data     = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, FD_ACC_TOT_SZ_MAX );
     137           0 :       ulong               dlen     = fd_txn_account_get_data_len( acc );
     138           0 :       fd_account_meta_t * meta     = (fd_account_meta_t *)data;
     139           0 :       fd_memcpy( data, fd_txn_account_get_meta( acc ), sizeof(fd_account_meta_t)+dlen );
     140           0 :       if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new( acc, acc_key, meta, 0 ), txn_ctx->spad_wksp ) ) ) {
     141           0 :         FD_LOG_CRIT(( "Failed to join and new a txn account" ));
     142           0 :       }
     143           0 :     }
     144             : 
     145           0 :     if( !memcmp( accts[j].pubkey, test_ctx->program_id, sizeof(fd_pubkey_t) ) ) {
     146           0 :       has_program_id = 1;
     147           0 :       info->program_id = (uchar)txn_ctx->accounts_cnt;
     148           0 :     }
     149             : 
     150             :     /* Since the instructions sysvar is set as mutable at the txn level, we need to make it mutable here as well. */
     151           0 :     if( !memcmp( accts[j].pubkey, &fd_sysvar_instructions_id, sizeof(fd_pubkey_t) ) ) {
     152           0 :       fd_txn_account_set_mutable( acc );
     153           0 :     }
     154           0 :   }
     155             : 
     156             :   /* If the program id is not in the set of accounts it must be added to the set of accounts. */
     157           0 :   if( FD_UNLIKELY( !has_program_id ) ) {
     158           0 :     fd_txn_account_t * program_acc = &accts[ test_ctx->accounts_count ];
     159           0 :     fd_pubkey_t *      program_key = &txn_ctx->account_keys[ txn_ctx->accounts_cnt ];
     160           0 :     memcpy( program_key, test_ctx->program_id, sizeof(fd_pubkey_t) );
     161             : 
     162           0 :     fd_account_meta_t * meta = fd_spad_alloc( txn_ctx->spad, alignof(fd_account_meta_t), sizeof(fd_account_meta_t) );
     163           0 :     fd_account_meta_init( meta );
     164             : 
     165           0 :     if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new(
     166           0 :           program_acc,
     167           0 :           program_key,
     168           0 :           meta,
     169           0 :           1 ), txn_ctx->spad_wksp ) ) ) {
     170           0 :       FD_LOG_CRIT(( "Failed to join and new a txn account" ));
     171           0 :     }
     172             : 
     173           0 :     info->program_id = (uchar)txn_ctx->accounts_cnt;
     174           0 :     txn_ctx->accounts_cnt++;
     175           0 :   }
     176             : 
     177             :   /* Load in executable accounts */
     178           0 :   for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) {
     179           0 :     fd_pubkey_t * acc_key = (fd_pubkey_t *)test_ctx->accounts[i].address;
     180             : 
     181           0 :     fd_txn_account_t * acc = &accts[i];
     182           0 :     if ( !fd_executor_pubkey_is_bpf_loader( fd_txn_account_get_owner( acc ) ) ) {
     183           0 :       continue;
     184           0 :     }
     185             : 
     186           0 :     fd_account_meta_t const * meta = fd_txn_account_get_meta( acc );
     187           0 :     if( meta == NULL ) {
     188           0 :       uchar * mem = fd_spad_alloc( txn_ctx->spad, FD_TXN_ACCOUNT_ALIGN, sizeof(fd_account_meta_t) );
     189           0 :       fd_account_meta_t * meta = (fd_account_meta_t *)mem;
     190           0 :       memset( meta, 0, sizeof(fd_account_meta_t) );
     191           0 :       if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new( acc, acc_key, meta, 0 ), txn_ctx->spad_wksp ) ) ) {
     192           0 :         FD_LOG_CRIT(( "Failed to join and new a txn account" ));
     193           0 :       }
     194           0 :       continue;
     195           0 :     }
     196             : 
     197           0 :     if( FD_UNLIKELY( !memcmp(meta->owner, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t)) ) ) {
     198           0 :       fd_bpf_upgradeable_loader_state_t * program_loader_state = fd_bpf_loader_program_get_state( acc,
     199           0 :                                                                                                   txn_ctx->spad,
     200           0 :                                                                                                   NULL );
     201             : 
     202           0 :       if( FD_UNLIKELY( !program_loader_state ) ) {
     203           0 :         continue;
     204           0 :       }
     205             : 
     206           0 :       if( !fd_bpf_upgradeable_loader_state_is_program( program_loader_state ) ) {
     207           0 :         continue;
     208           0 :       }
     209             : 
     210           0 :       fd_pubkey_t * programdata_acc = &program_loader_state->inner.program.programdata_address;
     211           0 :       if( FD_UNLIKELY( fd_txn_account_init_from_funk_readonly( &txn_ctx->executable_accounts[txn_ctx->executable_cnt],
     212           0 :                                                                programdata_acc,
     213           0 :                                                                txn_ctx->funk,
     214           0 :                                                                txn_ctx->xid ) ) ) {
     215           0 :         continue;
     216           0 :       }
     217           0 :       txn_ctx->executable_cnt++;
     218           0 :     }
     219           0 :   }
     220             : 
     221             :   /* Set slot bank variables and ensure all relevant sysvars are present */
     222           0 :   fd_sol_sysvar_last_restart_slot_t last_restart_slot_[1];
     223           0 :   FD_TEST( fd_sysvar_last_restart_slot_read( funk, xid, last_restart_slot_ ) );
     224             : 
     225           0 :   fd_sol_sysvar_clock_t clock_[1];
     226           0 :   fd_sol_sysvar_clock_t * clock = fd_sysvar_clock_read( funk, xid, clock_ );
     227           0 :   FD_TEST( clock );
     228           0 :   fd_bank_slot_set( runner->bank, clock->slot );
     229             : 
     230           0 :   fd_epoch_schedule_t epoch_schedule_[1];
     231           0 :   fd_epoch_schedule_t * epoch_schedule = fd_sysvar_epoch_schedule_read( funk, xid, epoch_schedule_ );
     232           0 :   FD_TEST( epoch_schedule );
     233           0 :   fd_bank_epoch_schedule_set( runner->bank, *epoch_schedule );
     234             : 
     235             :   /* Override epoch bank rent setting */
     236           0 :   fd_rent_t const * rent = fd_sysvar_rent_read( funk, xid, runner->spad );
     237           0 :   FD_TEST( rent );
     238           0 :   fd_bank_rent_set( runner->bank, *rent );
     239             : 
     240             :   /* Override most recent blockhash if given */
     241           0 :   fd_recent_block_hashes_t const * rbh = fd_sysvar_recent_hashes_read( funk, xid, runner->spad );
     242           0 :   FD_TEST( rbh );
     243           0 :   if( !deq_fd_block_block_hash_entry_t_empty( rbh->hashes ) ) {
     244           0 :     fd_block_block_hash_entry_t const * last = deq_fd_block_block_hash_entry_t_peek_tail_const( rbh->hashes );
     245           0 :     if( last ) {
     246           0 :       fd_blockhashes_t * blockhashes = fd_bank_block_hash_queue_modify( runner->bank );
     247           0 :       fd_blockhashes_pop_new( blockhashes );
     248           0 :       fd_blockhash_info_t * info = fd_blockhashes_push_new( blockhashes, &last->blockhash );
     249           0 :       info->fee_calculator = last->fee_calculator;
     250             : 
     251           0 :       fd_bank_lamports_per_signature_set( runner->bank, last->fee_calculator.lamports_per_signature );
     252             : 
     253           0 :       fd_bank_prev_lamports_per_signature_set( runner->bank, last->fee_calculator.lamports_per_signature );
     254           0 :     }
     255           0 :   }
     256             : 
     257             :   /* Load instruction accounts */
     258             : 
     259           0 :   if( FD_UNLIKELY( test_ctx->instr_accounts_count > MAX_TX_ACCOUNT_LOCKS ) ) {
     260           0 :     FD_LOG_NOTICE(( "too many instruction accounts" ));
     261           0 :     return 0;
     262           0 :   }
     263             : 
     264             :   /* Restore sysvar cache */
     265           0 :   fd_sysvar_cache_restore_fuzz( runner->bank, runner->accdb->funk, xid );
     266           0 :   ctx->sysvar_cache = fd_bank_sysvar_cache_modify( runner->bank );
     267             : 
     268           0 :   uchar acc_idx_seen[ FD_INSTR_ACCT_MAX ] = {0};
     269           0 :   for( ulong j=0UL; j < test_ctx->instr_accounts_count; j++ ) {
     270           0 :     uint index = test_ctx->instr_accounts[j].index;
     271           0 :     if( index >= test_ctx->accounts_count ) {
     272           0 :       FD_LOG_NOTICE( ( "instruction account index out of range (%u > %u)", index, test_ctx->instr_accounts_count ) );
     273           0 :       return 0;
     274           0 :     }
     275             : 
     276           0 :     fd_txn_account_t * acc = &accts[ index ];
     277             : 
     278             :     /* Setup instruction accounts */
     279           0 :     fd_instr_info_setup_instr_account( info,
     280           0 :                                        acc_idx_seen,
     281           0 :                                        (ushort)index,
     282           0 :                                        (ushort)j,
     283           0 :                                        (ushort)j,
     284           0 :                                        test_ctx->instr_accounts[j].is_writable,
     285           0 :                                        test_ctx->instr_accounts[j].is_signer );
     286             : 
     287           0 :     if( test_ctx->instr_accounts[j].is_writable ) {
     288           0 :       fd_txn_account_set_mutable( acc );
     289           0 :     }
     290           0 :   }
     291           0 :   info->acct_cnt = (uchar)test_ctx->instr_accounts_count;
     292             : 
     293             :   /* The remaining checks enforce that the program is in the accounts list. */
     294           0 :   bool found_program_id = false;
     295           0 :   for( uint i = 0; i < test_ctx->accounts_count; i++ ) {
     296           0 :     if( 0 == memcmp( test_ctx->accounts[i].address, test_ctx->program_id, sizeof(fd_pubkey_t) ) ) {
     297           0 :       info->program_id = (uchar) i;
     298           0 :       found_program_id = true;
     299           0 :       break;
     300           0 :     }
     301           0 :   }
     302             : 
     303             :   /* Early returning only happens in instruction execution. */
     304           0 :   if( !is_syscall && !found_program_id ) {
     305           0 :     FD_LOG_NOTICE(( " Unable to find program_id in accounts" ));
     306           0 :     return 0;
     307           0 :   }
     308             : 
     309           0 :   ctx->instr = info;
     310             : 
     311             :   /* Refresh the setup from the updated slot and epoch ctx. */
     312           0 :   fd_exec_txn_ctx_setup( runner->bank,
     313           0 :                          runner->accdb->funk->shmem,
     314           0 :                          runner->progcache->funk->shmem,
     315           0 :                          xid,
     316           0 :                          NULL,
     317           0 :                          txn_ctx,
     318           0 :                          NULL,
     319           0 :                          progcache_scratch,
     320           0 :                          FD_PROGCACHE_SCRATCH_FOOTPRINT );
     321             : 
     322           0 :   fd_log_collector_init( &ctx->txn_ctx->log_collector, 1 );
     323           0 :   fd_base58_encode_32( txn_ctx->account_keys[ ctx->instr->program_id ].uc, NULL, ctx->program_id_base58 );
     324             : 
     325           0 :   return 1;
     326           0 : }
     327             : 
     328             : void
     329             : fd_runtime_fuzz_instr_ctx_destroy( fd_solfuzz_runner_t * runner,
     330           0 :                                    fd_exec_instr_ctx_t * ctx ) {
     331           0 :   if( !ctx ) return;
     332           0 :   fd_accdb_clear( runner->accdb_admin );
     333           0 :   fd_progcache_clear( runner->progcache_admin );
     334           0 : }
     335             : 
     336             : ulong
     337             : fd_solfuzz_instr_run( fd_solfuzz_runner_t * runner,
     338             :                       void const *          input_,
     339             :                       void **               output_,
     340             :                       void *                output_buf,
     341           0 :                       ulong                 output_bufsz ) {
     342           0 :   fd_exec_test_instr_context_t const * input  = fd_type_pun_const( input_ );
     343           0 :   fd_exec_test_instr_effects_t **      output = fd_type_pun( output_ );
     344             : 
     345             :   /* Convert the Protobuf inputs to a fd_exec context */
     346           0 :   fd_exec_instr_ctx_t ctx[1];
     347           0 :   if( !fd_runtime_fuzz_instr_ctx_create( runner, ctx, input, false ) ) {
     348           0 :     fd_runtime_fuzz_instr_ctx_destroy( runner, ctx );
     349           0 :     return 0UL;
     350           0 :   }
     351             : 
     352           0 :   fd_instr_info_t * instr = (fd_instr_info_t *) ctx->instr;
     353             : 
     354             :   /* Execute the test */
     355           0 :   int exec_result = fd_execute_instr(ctx->txn_ctx, instr);
     356             : 
     357             :   /* Allocate space to capture outputs */
     358             : 
     359           0 :   ulong output_end = (ulong)output_buf + output_bufsz;
     360           0 :   FD_SCRATCH_ALLOC_INIT( l, output_buf );
     361             : 
     362           0 :   fd_exec_test_instr_effects_t * effects =
     363           0 :     FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_instr_effects_t),
     364           0 :                                 sizeof (fd_exec_test_instr_effects_t) );
     365           0 :   if( FD_UNLIKELY( _l > output_end ) ) {
     366           0 :     fd_runtime_fuzz_instr_ctx_destroy( runner, ctx );
     367           0 :     return 0UL;
     368           0 :   }
     369           0 :   fd_memset( effects, 0, sizeof(fd_exec_test_instr_effects_t) );
     370             : 
     371             :   /* Capture error code */
     372             : 
     373           0 :   effects->result   = -exec_result;
     374           0 :   effects->cu_avail = ctx->txn_ctx->compute_budget_details.compute_meter;
     375             : 
     376             :   /* Don't capture custom error codes if the program is a precompile */
     377           0 :   if( FD_LIKELY( effects->result ) ) {
     378           0 :     int program_id_idx = ctx->instr[ 0UL ].program_id;
     379           0 :     if( exec_result==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR &&
     380           0 :         fd_executor_lookup_native_precompile_program( &ctx->txn_ctx->accounts[ program_id_idx ] )==NULL ) {
     381           0 :       effects->custom_err = ctx->txn_ctx->custom_err;
     382           0 :     }
     383           0 :   }
     384             : 
     385             :   /* Allocate space for captured accounts */
     386           0 :   ulong modified_acct_cnt = ctx->txn_ctx->accounts_cnt;
     387             : 
     388           0 :   fd_exec_test_acct_state_t * modified_accts =
     389           0 :     FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_acct_state_t),
     390           0 :                                 sizeof (fd_exec_test_acct_state_t) * modified_acct_cnt );
     391           0 :   if( FD_UNLIKELY( _l > output_end ) ) {
     392           0 :     fd_runtime_fuzz_instr_ctx_destroy( runner, ctx );
     393           0 :     return 0;
     394           0 :   }
     395           0 :   effects->modified_accounts       = modified_accts;
     396           0 :   effects->modified_accounts_count = 0UL;
     397             : 
     398             :   /* Capture borrowed accounts */
     399             : 
     400           0 :   for( ulong j=0UL; j < ctx->txn_ctx->accounts_cnt; j++ ) {
     401           0 :     fd_txn_account_t * acc = &ctx->txn_ctx->accounts[j];
     402           0 :     if( !fd_txn_account_get_meta( acc ) ) {
     403           0 :       continue;
     404           0 :     }
     405             : 
     406           0 :     ulong modified_idx = effects->modified_accounts_count;
     407           0 :     assert( modified_idx < modified_acct_cnt );
     408             : 
     409           0 :     fd_exec_test_acct_state_t * out_acct = &effects->modified_accounts[ modified_idx ];
     410           0 :     memset( out_acct, 0, sizeof(fd_exec_test_acct_state_t) );
     411             :     /* Copy over account content */
     412             : 
     413           0 :     memcpy( out_acct->address, acc->pubkey, sizeof(fd_pubkey_t) );
     414           0 :     out_acct->lamports = fd_txn_account_get_lamports( acc );
     415           0 :     if( fd_txn_account_get_data_len( acc )>0UL ) {
     416           0 :       out_acct->data =
     417           0 :         FD_SCRATCH_ALLOC_APPEND( l, alignof(pb_bytes_array_t),
     418           0 :                                     PB_BYTES_ARRAY_T_ALLOCSIZE( fd_txn_account_get_data_len( acc ) ) );
     419           0 :       if( FD_UNLIKELY( _l > output_end ) ) {
     420           0 :         fd_runtime_fuzz_instr_ctx_destroy( runner, ctx );
     421           0 :         return 0UL;
     422           0 :       }
     423           0 :       out_acct->data->size = (pb_size_t)fd_txn_account_get_data_len( acc );
     424           0 :       fd_memcpy( out_acct->data->bytes, fd_txn_account_get_data( acc ), fd_txn_account_get_data_len( acc ) );
     425           0 :     }
     426             : 
     427           0 :     out_acct->executable = fd_txn_account_is_executable( acc );
     428           0 :     memcpy( out_acct->owner, fd_txn_account_get_owner( acc ), sizeof(fd_pubkey_t) );
     429             : 
     430           0 :     effects->modified_accounts_count++;
     431           0 :   }
     432             : 
     433             :   /* Capture return data */
     434           0 :   fd_txn_return_data_t * return_data = &ctx->txn_ctx->return_data;
     435           0 :   if( return_data->len>0UL ) {
     436           0 :     effects->return_data = FD_SCRATCH_ALLOC_APPEND(l, alignof(pb_bytes_array_t),
     437           0 :                                 PB_BYTES_ARRAY_T_ALLOCSIZE( return_data->len ) );
     438           0 :     if( FD_UNLIKELY( _l > output_end ) ) {
     439           0 :       fd_runtime_fuzz_instr_ctx_destroy( runner, ctx );
     440           0 :       return 0UL;
     441           0 :     }
     442           0 :     effects->return_data->size = (pb_size_t)return_data->len;
     443           0 :     fd_memcpy( effects->return_data->bytes, return_data->data, return_data->len );
     444           0 :   }
     445             : 
     446           0 :   ulong actual_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
     447           0 :   fd_runtime_fuzz_instr_ctx_destroy( runner, ctx );
     448             : 
     449           0 :   *output = effects;
     450           0 :   return actual_end - (ulong)output_buf;
     451             : 
     452           0 : }

Generated by: LCOV version 1.14