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