Line data Source code
1 : #define _GNU_SOURCE
2 : #include "fd_exec_sol_compat.h"
3 :
4 : #include "../../../../ballet/nanopb/pb_encode.h"
5 : #include "../../../../ballet/nanopb/pb_decode.h"
6 :
7 : #include "../../fd_executor_err.h"
8 : #include "../../../capture/fd_solcap_writer.h"
9 : #include "../../../features/fd_features.h"
10 : #include "../../../../ballet/shred/fd_shred.h"
11 :
12 : #include "fd_instr_harness.h"
13 : #include "fd_txn_harness.h"
14 : #include "fd_block_harness.h"
15 : #include "fd_types_harness.h"
16 : #include "fd_vm_harness.h"
17 : #include "fd_pack_harness.h"
18 : #include "fd_elf_harness.h"
19 :
20 : #include "generated/elf.pb.h"
21 : #include "generated/invoke.pb.h"
22 : #include "generated/shred.pb.h"
23 : #include "generated/vm.pb.h"
24 : #include "generated/type.pb.h"
25 :
26 : #include <errno.h>
27 : #include <stdio.h>
28 :
29 : /* FIXME: Spad isn't properly sized out or cleaned up */
30 :
31 : /* This file defines stable APIs for compatibility testing.
32 :
33 : For the "compat" shared library used by the differential fuzzer,
34 : ideally the symbols defined in this file would be the only visible
35 : globals. Unfortunately, we currently export all symbols, which leads
36 : to great symbol table bloat from fd_types.c. */
37 :
38 : typedef struct {
39 : ulong struct_size;
40 : ulong * hardcoded_features;
41 : ulong hardcoded_features_cnt;
42 : ulong * supported_features;
43 : ulong supported_feature_cnt;
44 : } sol_compat_features_t;
45 :
46 : static sol_compat_features_t features;
47 : static uchar * spad_mem;
48 : static fd_wksp_t * wksp = NULL;
49 : static fd_banks_t * banks = NULL;
50 : static fd_bank_t * bank = NULL;
51 :
52 0 : #define WKSP_EXECUTE_ALLOC_TAG (2UL)
53 0 : #define WKSP_INIT_ALLOC_TAG (3UL)
54 :
55 : void
56 0 : sol_compat_init( int log_level ) {
57 0 : int argc = 1;
58 0 : char * argv[2] = { (char *)"fd_exec_sol_compat", NULL };
59 0 : char ** argv_ = argv;
60 0 : if( !getenv( "FD_LOG_PATH" ) ) {
61 0 : setenv( "FD_LOG_PATH", "", 1 );
62 0 : }
63 0 : fd_log_enable_unclean_exit();
64 0 : fd_boot( &argc, &argv_ );
65 0 : fd_log_level_logfile_set( log_level );
66 0 : fd_log_level_core_set(4); /* abort on FD_LOG_ERR */
67 :
68 0 : sol_compat_wksp_init( FD_SHMEM_NORMAL_PAGE_SZ );
69 0 : }
70 :
71 : fd_wksp_t *
72 0 : sol_compat_wksp_init( ulong wksp_page_sz ) {
73 0 : ulong cpu_idx = fd_tile_cpu_id( fd_tile_idx() );
74 0 : if( cpu_idx>=fd_shmem_cpu_cnt() ) cpu_idx = 0UL;
75 0 : switch( wksp_page_sz )
76 0 : {
77 0 : case FD_SHMEM_GIGANTIC_PAGE_SZ:
78 0 : wksp = fd_wksp_new_anonymous( FD_SHMEM_GIGANTIC_PAGE_SZ, 6UL, fd_shmem_cpu_idx( fd_shmem_numa_idx( cpu_idx ) ), "wksp", 0UL );
79 0 : break;
80 0 : case FD_SHMEM_NORMAL_PAGE_SZ:
81 0 : wksp = fd_wksp_new_anonymous( FD_SHMEM_NORMAL_PAGE_SZ, 512UL * 512UL * 6UL, fd_shmem_cpu_idx( fd_shmem_numa_idx( cpu_idx ) ), "wksp", 0UL );
82 0 : break;
83 0 : default:
84 0 : FD_LOG_ERR(( "Unsupported page size %lu", wksp_page_sz ));
85 0 : }
86 0 : FD_TEST( wksp );
87 :
88 0 : spad_mem = fd_wksp_alloc_laddr( wksp, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ ), WKSP_INIT_ALLOC_TAG ); /* 4738713960 B */
89 0 : FD_TEST( spad_mem );
90 :
91 0 : ulong banks_footprint = fd_banks_footprint( 1UL, 1UL );
92 0 : uchar * banks_mem = fd_wksp_alloc_laddr( wksp, fd_banks_align(), banks_footprint, WKSP_INIT_ALLOC_TAG );
93 0 : if( FD_UNLIKELY( !banks_mem ) ) {
94 0 : FD_LOG_CRIT(( "Unable to allocate memory for banks" ));
95 0 : }
96 :
97 0 : banks = fd_banks_join( fd_banks_new( banks_mem, 1UL, 1UL ) );
98 0 : if( FD_UNLIKELY( !banks ) ) {
99 0 : FD_LOG_CRIT(( "Unable to create and join banks" ));
100 0 : }
101 0 : bank = fd_banks_init_bank( banks, 0UL );
102 0 : if( FD_UNLIKELY( !bank ) ) {
103 0 : FD_LOG_CRIT(( "Unable to initialize bank" ));
104 0 : }
105 :
106 0 : features.struct_size = sizeof(sol_compat_features_t);
107 0 : features.hardcoded_features = fd_wksp_alloc_laddr( wksp, 8UL, FD_FEATURE_ID_CNT * sizeof(ulong), WKSP_INIT_ALLOC_TAG );
108 0 : features.supported_features = fd_wksp_alloc_laddr( wksp, 8UL, FD_FEATURE_ID_CNT * sizeof(ulong), WKSP_INIT_ALLOC_TAG );
109 :
110 0 : for( const fd_feature_id_t * current_feature = fd_feature_iter_init(); !fd_feature_iter_done( current_feature ); current_feature = fd_feature_iter_next( current_feature ) ) {
111 : // Skip reverted features
112 0 : if( current_feature->reverted ) continue;
113 :
114 : // Only hardcode features that are activated on all clusters
115 0 : if( current_feature->activated_on_all_clusters ) {
116 0 : memcpy( &features.hardcoded_features[features.hardcoded_features_cnt++], ¤t_feature->id, sizeof(ulong) );
117 0 : } else {
118 0 : memcpy( &features.supported_features[features.supported_feature_cnt++], ¤t_feature->id, sizeof(ulong) );
119 0 : }
120 0 : }
121 :
122 0 : return wksp;
123 0 : }
124 :
125 : void
126 0 : sol_compat_fini( void ) {
127 0 : fd_wksp_free_laddr( spad_mem );
128 0 : fd_wksp_free_laddr( features.hardcoded_features );
129 0 : fd_wksp_free_laddr( features.supported_features );
130 0 : fd_wksp_delete_anonymous( wksp );
131 0 : wksp = NULL;
132 0 : spad_mem = NULL;
133 0 : }
134 :
135 : void
136 0 : sol_compat_check_wksp_usage( void ) {
137 0 : fd_wksp_usage_t usage[1];
138 0 : ulong tags[1] = { WKSP_EXECUTE_ALLOC_TAG };
139 0 : fd_wksp_usage( wksp, tags, 1, usage );
140 0 : if( usage->used_sz ) {
141 0 : FD_LOG_ERR(( "%lu bytes leaked in %lu allocations", usage->used_sz, usage->used_cnt ));
142 0 : }
143 0 : }
144 :
145 : sol_compat_features_t const *
146 0 : sol_compat_get_features_v1( void ) {
147 0 : return &features;
148 0 : }
149 :
150 : fd_runtime_fuzz_runner_t *
151 0 : sol_compat_setup_runner( void ) {
152 :
153 : // Setup test runner
154 0 : void * runner_mem = fd_wksp_alloc_laddr( wksp, fd_runtime_fuzz_runner_align(), fd_runtime_fuzz_runner_footprint(), WKSP_EXECUTE_ALLOC_TAG );
155 0 : fd_runtime_fuzz_runner_t * runner = fd_runtime_fuzz_runner_new( runner_mem, spad_mem, banks, bank, WKSP_EXECUTE_ALLOC_TAG );
156 :
157 0 : char const * solcap_path = getenv( "FD_SOLCAP" );
158 0 : if( solcap_path ) {
159 0 : runner->solcap_file = fopen( solcap_path, "w" );
160 0 : if( FD_UNLIKELY( !runner->solcap_file ) ) {
161 0 : FD_LOG_ERR(( "fopen($FD_SOLCAP=%s) failed (%i-%s)", solcap_path, errno, fd_io_strerror( errno ) ));
162 0 : }
163 0 : FD_LOG_NOTICE(( "Logging to solcap file %s", solcap_path ));
164 :
165 0 : void * solcap_mem = fd_wksp_alloc_laddr( runner->wksp, fd_solcap_writer_align(), fd_solcap_writer_footprint(), 1UL );
166 0 : runner->solcap = fd_solcap_writer_new( solcap_mem );
167 0 : FD_TEST( runner->solcap );
168 0 : FD_TEST( fd_solcap_writer_init( solcap_mem, runner->solcap_file ) );
169 0 : }
170 :
171 0 : return runner;
172 0 : }
173 :
174 : void
175 0 : sol_compat_cleanup_runner( fd_runtime_fuzz_runner_t * runner ) {
176 : /* Cleanup test runner */
177 0 : if( runner->solcap ) {
178 0 : fd_solcap_writer_flush( runner->solcap );
179 0 : fd_wksp_free_laddr( fd_solcap_writer_delete( runner->solcap ) );
180 0 : runner->solcap = NULL;
181 0 : fclose( runner->solcap_file );
182 0 : runner->solcap_file = NULL;
183 0 : }
184 0 : fd_wksp_free_laddr( fd_runtime_fuzz_runner_delete( runner ) );
185 0 : }
186 :
187 : void *
188 : sol_compat_decode( void * decoded,
189 : uchar const * in,
190 : ulong in_sz,
191 0 : pb_msgdesc_t const * decode_type ) {
192 0 : pb_istream_t istream = pb_istream_from_buffer( in, in_sz );
193 0 : int decode_ok = pb_decode_ex( &istream, decode_type, decoded, PB_DECODE_NOINIT );
194 0 : if( !decode_ok ) {
195 0 : pb_release( decode_type, decoded );
196 0 : return NULL;
197 0 : }
198 0 : return decoded;
199 0 : }
200 :
201 : void const *
202 : sol_compat_encode( uchar * out,
203 : ulong * out_sz,
204 : void const * to_encode,
205 0 : pb_msgdesc_t const * encode_type ) {
206 0 : pb_ostream_t ostream = pb_ostream_from_buffer( out, *out_sz );
207 0 : int encode_ok = pb_encode( &ostream, encode_type, to_encode );
208 0 : if( !encode_ok ) {
209 0 : return NULL;
210 0 : }
211 0 : *out_sz = ostream.bytes_written;
212 0 : return to_encode;
213 0 : }
214 :
215 : typedef ulong( exec_test_run_fn_t )( fd_runtime_fuzz_runner_t *,
216 : void const *,
217 : void **,
218 : void *,
219 : ulong );
220 :
221 : void
222 : sol_compat_execute_wrapper( fd_runtime_fuzz_runner_t * runner,
223 : void * input,
224 : void ** output,
225 0 : exec_test_run_fn_t * exec_test_run_fn ) {
226 :
227 0 : ulong out_bufsz = 100000000; /* 100 MB */
228 0 : void * out0 = fd_spad_alloc( runner->spad, 1UL, out_bufsz );
229 0 : FD_TEST( out_bufsz <= fd_spad_alloc_max( runner->spad, 1UL ) );
230 :
231 0 : ulong out_used = exec_test_run_fn( runner, input, output, out0, out_bufsz );
232 0 : if( FD_UNLIKELY( !out_used ) ) {
233 0 : *output = NULL;
234 0 : }
235 :
236 0 : }
237 :
238 : /*
239 : * fixtures
240 : */
241 :
242 : int
243 : sol_compat_cmp_binary_strict( void const * effects,
244 : void const * expected,
245 : pb_msgdesc_t const * encode_type,
246 0 : fd_spad_t * spad ) {
247 0 : #define MAX_SZ 32*1024*1024
248 0 : FD_SPAD_FRAME_BEGIN( spad ) {
249 0 : if( effects==NULL ) {
250 0 : FD_LOG_WARNING(( "No output effects" ));
251 0 : return 0;
252 0 : }
253 :
254 : /* Note: Most likely this spad allocation won't fail. If it does, you may need to bump
255 : the allocated spad memory amount in fd_exec_sol_compat.c. */
256 0 : ulong out_sz = MAX_SZ;
257 0 : uchar * out = fd_spad_alloc( spad, 1UL, out_sz );
258 0 : if( !sol_compat_encode( out, &out_sz, effects, encode_type ) ) {
259 0 : FD_LOG_WARNING(( "Error encoding effects" ));
260 0 : return 0;
261 0 : }
262 :
263 0 : ulong exp_sz = MAX_SZ;
264 0 : uchar * exp = fd_spad_alloc( spad, 1UL, exp_sz );
265 0 : if( !sol_compat_encode( exp, &exp_sz, expected, encode_type ) ) {
266 0 : FD_LOG_WARNING(( "Error encoding expected" ));
267 0 : return 0;
268 0 : }
269 :
270 0 : if( out_sz!=exp_sz ) {
271 0 : FD_LOG_WARNING(( "Binary cmp failed: different size. out_sz=%lu exp_sz=%lu", out_sz, exp_sz ));
272 0 : return 0;
273 0 : }
274 0 : if( !fd_memeq( out, exp, out_sz ) ) {
275 0 : FD_LOG_WARNING(( "Binary cmp failed: different values." ));
276 0 : return 0;
277 0 : }
278 :
279 0 : return 1;
280 0 : } FD_SPAD_FRAME_END;
281 0 : #undef MAX_SIZE
282 0 : }
283 :
284 : static int
285 : _diff_txn_acct( fd_exec_test_acct_state_t * expected,
286 0 : fd_exec_test_acct_state_t * actual ) {
287 : /* AcctState -> address (This must hold true when calling this function!) */
288 0 : assert( fd_memeq( expected->address, actual->address, sizeof(fd_pubkey_t) ) );
289 :
290 : /* AcctState -> lamports */
291 0 : if( expected->lamports != actual->lamports ) {
292 0 : FD_LOG_WARNING(( "Lamports mismatch: expected=%lu actual=%lu", expected->lamports, actual->lamports ));
293 0 : return 0;
294 0 : }
295 :
296 : /* AcctState -> data */
297 0 : if( expected->data != NULL || actual->data != NULL ) {
298 0 : if( expected->data == NULL ) {
299 0 : FD_LOG_WARNING(( "Expected account data is NULL, actual is non-NULL" ));
300 0 : return 0;
301 0 : }
302 :
303 0 : if( actual->data == NULL ) {
304 0 : FD_LOG_WARNING(( "Expected account data is NULL, actual is non-NULL" ));
305 0 : return 0;
306 0 : }
307 :
308 0 : if( expected->data->size != actual->data->size ) {
309 0 : FD_LOG_WARNING(( "Account data size mismatch: expected=%u actual=%u", expected->data->size, actual->data->size ));
310 0 : return 0;
311 0 : }
312 :
313 0 : if( !fd_memeq( expected->data->bytes, actual->data->bytes, expected->data->size ) ) {
314 0 : FD_LOG_WARNING(( "Account data mismatch" ));
315 0 : return 0;
316 0 : }
317 0 : }
318 :
319 : /* AcctState -> executable */
320 0 : if( expected->executable != actual->executable ) {
321 0 : FD_LOG_WARNING(( "Executable mismatch: expected=%d actual=%d", expected->executable, actual->executable ));
322 0 : return 0;
323 0 : }
324 :
325 : /* AcctState -> rent_epoch */
326 0 : if( expected->rent_epoch != actual->rent_epoch ) {
327 0 : FD_LOG_WARNING(( "Rent epoch mismatch: expected=%lu actual=%lu", expected->rent_epoch, actual->rent_epoch ));
328 0 : return 0;
329 0 : }
330 :
331 : /* AcctState -> owner */
332 0 : if( !fd_memeq( expected->owner, actual->owner, sizeof(fd_pubkey_t) ) ) {
333 0 : char a[ FD_BASE58_ENCODED_32_SZ ];
334 0 : char b[ FD_BASE58_ENCODED_32_SZ ];
335 0 : FD_LOG_WARNING(( "Owner mismatch: expected=%s, actual=%s", fd_acct_addr_cstr( a, expected->owner ), fd_acct_addr_cstr( b, actual->owner ) ));
336 0 : return 0;
337 0 : }
338 :
339 0 : return 1;
340 0 : }
341 :
342 :
343 : static int
344 : _diff_resulting_states( fd_exec_test_resulting_state_t * expected,
345 0 : fd_exec_test_resulting_state_t * actual ) {
346 : // Verify that the number of accounts are the same
347 0 : if( expected->acct_states_count != actual->acct_states_count ) {
348 0 : FD_LOG_WARNING(( "Account states count mismatch: expected=%u actual=%u", expected->acct_states_count, actual->acct_states_count ));
349 0 : return 0;
350 0 : }
351 :
352 : // Verify that the account states are the same
353 0 : for( ulong i = 0; i < expected->acct_states_count; ++i ) {
354 0 : for( ulong j = 0; j < actual->acct_states_count; ++j ) {
355 0 : if( fd_memeq( expected->acct_states[i].address, actual->acct_states[j].address, sizeof(fd_pubkey_t) ) ) {
356 0 : if( !_diff_txn_acct( &expected->acct_states[i], &actual->acct_states[j] ) ) {
357 0 : return 0;
358 0 : }
359 0 : }
360 0 : }
361 0 : }
362 :
363 : // TODO: resulting_state -> rent_debits, resulting_state->transaction_rent
364 0 : return 1;
365 0 : }
366 :
367 : int
368 : sol_compat_cmp_txn( fd_exec_test_txn_result_t * expected,
369 0 : fd_exec_test_txn_result_t * actual ) {
370 : /* TxnResult -> executed */
371 0 : if( expected->executed != actual->executed ) {
372 0 : FD_LOG_WARNING(( "Executed mismatch: expected=%d actual=%d", expected->executed, actual->executed ));
373 0 : return 0;
374 0 : }
375 :
376 : /* TxnResult -> sanitization_error */
377 0 : if( expected->sanitization_error != actual->sanitization_error ) {
378 0 : FD_LOG_WARNING(( "Sanitization error mismatch: expected=%d actual=%d", expected->sanitization_error, actual->sanitization_error ));
379 0 : return 0;
380 0 : }
381 :
382 : /* TxnResult -> resulting_state */
383 0 : if( !_diff_resulting_states( &expected->resulting_state, &actual->resulting_state ) ) {
384 0 : return 0;
385 0 : }
386 :
387 : /* TxnResult -> rent */
388 0 : if( expected->rent != actual->rent ) {
389 0 : FD_LOG_WARNING(( "Rent mismatch: expected=%lu actual=%lu", expected->rent, actual->rent ));
390 0 : return 0;
391 0 : }
392 :
393 : /* TxnResult -> is_ok */
394 0 : if( expected->is_ok != actual->is_ok ) {
395 0 : FD_LOG_WARNING(( "Is ok mismatch: expected=%d actual=%d", expected->is_ok, actual->is_ok ));
396 0 : return 0;
397 0 : }
398 :
399 : /* TxnResult -> status */
400 0 : if( expected->status != actual->status ) {
401 0 : FD_LOG_WARNING(( "Status mismatch: expected=%u actual=%u", expected->status, actual->status ));
402 0 : return 0;
403 0 : }
404 :
405 : /* TxnResult -> instruction_error */
406 0 : if( expected->instruction_error != actual->instruction_error ) {
407 0 : FD_LOG_WARNING(( "Instruction error mismatch: expected=%u actual=%u", expected->instruction_error, actual->instruction_error ));
408 0 : return 0;
409 0 : }
410 :
411 0 : if( expected->instruction_error ) {
412 : /* TxnResult -> instruction_error_index */
413 0 : if( expected->instruction_error_index != actual->instruction_error_index ) {
414 0 : FD_LOG_WARNING(( "Instruction error index mismatch: expected=%u actual=%u", expected->instruction_error_index, actual->instruction_error_index ));
415 0 : return 0;
416 0 : }
417 :
418 : /* TxnResult -> custom_error */
419 0 : if( expected->instruction_error == (ulong) -FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && expected->custom_error != actual->custom_error ) {
420 0 : FD_LOG_WARNING(( "Custom error mismatch: expected=%u actual=%u", expected->custom_error, actual->custom_error ));
421 0 : return 0;
422 0 : }
423 0 : }
424 :
425 : /* TxnResult -> return_data */
426 0 : if( expected->return_data != NULL || actual->return_data != NULL ) {
427 0 : if( expected->return_data == NULL ) {
428 0 : FD_LOG_WARNING(( "Expected return data is NULL, actual is non-NULL" ));
429 0 : return 0;
430 0 : }
431 :
432 0 : if( actual->return_data == NULL ) {
433 0 : FD_LOG_WARNING(( "Expected return data is NULL, actual is non-NULL" ));
434 0 : return 0;
435 0 : }
436 :
437 0 : if( expected->return_data->size != actual->return_data->size ) {
438 0 : FD_LOG_WARNING(( "Return data size mismatch: expected=%u actual=%u", expected->return_data->size, actual->return_data->size ));
439 0 : return 0;
440 0 : }
441 :
442 0 : if( !fd_memeq( expected->return_data->bytes, actual->return_data->bytes, expected->return_data->size ) ) {
443 0 : FD_LOG_WARNING(( "Return data mismatch" ));
444 0 : return 0;
445 0 : }
446 0 : }
447 :
448 : /* TxnResult -> executed_units */
449 0 : if( expected->executed_units != actual->executed_units ) {
450 0 : FD_LOG_WARNING(( "Executed units mismatch: expected=%lu actual=%lu", expected->executed_units, actual->executed_units ));
451 0 : return 0;
452 0 : }
453 :
454 : /* TxnResult -> fee_details */
455 0 : if( expected->has_fee_details != actual->has_fee_details ) {
456 0 : FD_LOG_WARNING(( "Has fee details mismatch: expected=%d actual=%d", expected->has_fee_details, actual->has_fee_details ));
457 0 : return 0;
458 0 : }
459 :
460 0 : if( expected->has_fee_details ) {
461 0 : if( expected->fee_details.transaction_fee != actual->fee_details.transaction_fee ) {
462 0 : FD_LOG_WARNING(( "Transaction fee mismatch: expected=%lu actual=%lu", expected->fee_details.transaction_fee, actual->fee_details.transaction_fee ));
463 0 : return 0;
464 0 : }
465 :
466 0 : if( expected->fee_details.prioritization_fee != actual->fee_details.prioritization_fee ) {
467 0 : FD_LOG_WARNING(( "Priority fee mismatch: expected=%lu actual=%lu", expected->fee_details.prioritization_fee, actual->fee_details.prioritization_fee ));
468 0 : return 0;
469 0 : }
470 0 : }
471 :
472 : /* TxnResult -> loaded_accounts_data_size */
473 0 : if( expected->loaded_accounts_data_size != actual->loaded_accounts_data_size ) {
474 0 : FD_LOG_WARNING(( "Loaded accounts data size mismatch: expected=%lu actual=%lu", expected->loaded_accounts_data_size, actual->loaded_accounts_data_size ));
475 0 : return 0;
476 0 : }
477 :
478 0 : return 1;
479 0 : }
480 :
481 : int
482 : sol_compat_instr_fixture( fd_runtime_fuzz_runner_t * runner,
483 : uchar const * in,
484 0 : ulong in_sz ) {
485 : // Decode fixture
486 0 : fd_exec_test_instr_fixture_t fixture[1] = {0};
487 0 : void * res = sol_compat_decode( &fixture, in, in_sz, &fd_exec_test_instr_fixture_t_msg );
488 0 : if ( res==NULL ) {
489 0 : FD_LOG_WARNING(( "Invalid instr fixture." ));
490 0 : return 0;
491 0 : }
492 :
493 0 : int ok = 0;
494 : // Execute
495 0 : void * output = NULL;
496 0 : sol_compat_execute_wrapper( runner, &fixture->input, &output, fd_runtime_fuzz_instr_run );
497 :
498 : // Compare effects
499 0 : ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_instr_effects_t_msg, runner->spad );
500 :
501 : // Cleanup
502 0 : pb_release( &fd_exec_test_instr_fixture_t_msg, fixture );
503 0 : return ok;
504 0 : }
505 :
506 : int
507 : sol_compat_txn_fixture( fd_runtime_fuzz_runner_t * runner,
508 : uchar const * in,
509 0 : ulong in_sz ) {
510 : // Decode fixture
511 0 : fd_exec_test_txn_fixture_t fixture[1] = {0};
512 0 : void * res = sol_compat_decode( &fixture, in, in_sz, &fd_exec_test_txn_fixture_t_msg );
513 0 : if ( res==NULL ) {
514 0 : FD_LOG_WARNING(( "Invalid txn fixture." ));
515 0 : return 0;
516 0 : }
517 :
518 0 : int ok = 0;
519 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
520 : // Execute
521 0 : void * output = NULL;
522 0 : sol_compat_execute_wrapper( runner, &fixture->input, &output, fd_runtime_fuzz_txn_run );
523 0 : if( FD_LIKELY( output ) ) {
524 : // Compare effects
525 0 : fd_exec_test_txn_result_t * effects = output;
526 0 : ok = sol_compat_cmp_txn( &fixture->output, effects );
527 0 : }
528 0 : } FD_SPAD_FRAME_END;
529 :
530 : // Cleanup
531 0 : pb_release( &fd_exec_test_txn_fixture_t_msg, fixture );
532 0 : return ok;
533 0 : }
534 :
535 : int
536 : sol_compat_block_fixture( fd_runtime_fuzz_runner_t * runner,
537 : uchar const * in,
538 0 : ulong in_sz ) {
539 : // Decode fixture
540 0 : fd_exec_test_block_fixture_t fixture[1] = {0};
541 0 : void * res = sol_compat_decode( &fixture, in, in_sz, &fd_exec_test_block_fixture_t_msg );
542 0 : if ( res==NULL ) {
543 0 : FD_LOG_WARNING(( "Invalid block fixture." ));
544 0 : return 0;
545 0 : }
546 :
547 0 : int ok = 0;
548 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
549 : // Execute
550 0 : void * output = NULL;
551 0 : sol_compat_execute_wrapper( runner, &fixture->input, &output, fd_runtime_fuzz_block_run );
552 :
553 : // Compare effects
554 0 : ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_block_effects_t_msg, runner->spad );
555 0 : } FD_SPAD_FRAME_END;
556 :
557 : // Cleanup
558 0 : pb_release( &fd_exec_test_block_fixture_t_msg, fixture );
559 0 : return ok;
560 0 : }
561 :
562 : int
563 : sol_compat_elf_loader_fixture( fd_runtime_fuzz_runner_t * runner,
564 : uchar const * in,
565 0 : ulong in_sz ) {
566 : // Decode fixture
567 0 : fd_exec_test_elf_loader_fixture_t fixture[1] = {0};
568 0 : void * res = sol_compat_decode( &fixture, in, in_sz, &fd_exec_test_elf_loader_fixture_t_msg );
569 0 : if ( res==NULL ) {
570 0 : FD_LOG_WARNING(( "Invalid elf_loader fixture." ));
571 0 : return 0;
572 0 : }
573 0 : int ok = 0;
574 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
575 : // Execute
576 0 : void * output = NULL;
577 0 : sol_compat_execute_wrapper( runner, &fixture->input, &output, fd_runtime_fuzz_sbpf_load_run );
578 :
579 : // Compare effects
580 0 : ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_elf_loader_effects_t_msg, runner->spad );
581 0 : } FD_SPAD_FRAME_END;
582 :
583 : // Cleanup
584 0 : pb_release( &fd_exec_test_elf_loader_fixture_t_msg, fixture );
585 0 : return ok;
586 0 : }
587 :
588 : int
589 : sol_compat_syscall_fixture( fd_runtime_fuzz_runner_t * runner,
590 : uchar const * in,
591 0 : ulong in_sz ) {
592 : // Decode fixture
593 0 : fd_exec_test_syscall_fixture_t fixture[1] = {0};
594 0 : if ( !sol_compat_decode( &fixture, in, in_sz, &fd_exec_test_syscall_fixture_t_msg ) ) {
595 0 : FD_LOG_WARNING(( "Invalid syscall fixture." ));
596 0 : return 0;
597 0 : }
598 :
599 0 : int ok = 0;
600 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
601 : // Execute
602 0 : void * output = NULL;
603 0 : sol_compat_execute_wrapper( runner, &fixture->input, &output, fd_runtime_fuzz_vm_syscall_run );
604 :
605 : // Compare effects
606 0 : ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_syscall_effects_t_msg, runner->spad );
607 0 : } FD_SPAD_FRAME_END;
608 :
609 : // Cleanup
610 0 : pb_release( &fd_exec_test_syscall_fixture_t_msg, fixture );
611 0 : return ok;
612 0 : }
613 :
614 : int
615 : sol_compat_vm_interp_fixture( fd_runtime_fuzz_runner_t * runner,
616 : uchar const * in,
617 0 : ulong in_sz ) {
618 : // Decode fixture
619 0 : fd_exec_test_syscall_fixture_t fixture[1] = {0};
620 0 : if ( !sol_compat_decode( &fixture, in, in_sz, &fd_exec_test_syscall_fixture_t_msg ) ) {
621 0 : FD_LOG_WARNING(( "Invalid syscall fixture." ));
622 0 : return 0;
623 0 : }
624 :
625 0 : int ok = 0;
626 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
627 : // Execute
628 0 : void * output = NULL;
629 0 : sol_compat_execute_wrapper( runner, &fixture->input, &output, (exec_test_run_fn_t *)fd_runtime_fuzz_vm_interp_run );
630 :
631 : // Compare effects
632 0 : ok = sol_compat_cmp_binary_strict( output, &fixture->output, &fd_exec_test_syscall_effects_t_msg, runner->spad );
633 0 : } FD_SPAD_FRAME_END;
634 :
635 : // Cleanup
636 0 : pb_release( &fd_exec_test_syscall_fixture_t_msg, fixture );
637 0 : return ok;
638 0 : }
639 :
640 : /*
641 : * execute_v1
642 : */
643 :
644 : int
645 : sol_compat_instr_execute_v1( uchar * out,
646 : ulong * out_sz,
647 : uchar const * in,
648 0 : ulong in_sz ) {
649 : // Setup
650 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
651 :
652 : // Decode context
653 0 : fd_exec_test_instr_context_t input[1] = {0};
654 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_instr_context_t_msg );
655 0 : if ( res==NULL ) {
656 0 : sol_compat_cleanup_runner( runner );
657 0 : return 0;
658 0 : }
659 :
660 0 : int ok = 0;
661 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
662 : // Execute
663 0 : void * output = NULL;
664 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_instr_run );
665 :
666 : // Encode effects
667 0 : if( output ) {
668 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_instr_effects_t_msg );
669 0 : }
670 0 : } FD_SPAD_FRAME_END;
671 :
672 : // Cleanup
673 0 : pb_release( &fd_exec_test_instr_context_t_msg, input );
674 0 : sol_compat_cleanup_runner( runner );
675 :
676 : // Check wksp usage is 0
677 0 : sol_compat_check_wksp_usage();
678 :
679 0 : return ok;
680 0 : }
681 :
682 : int
683 : sol_compat_txn_execute_v1( uchar * out,
684 : ulong * out_sz,
685 : uchar const * in,
686 0 : ulong in_sz ) {
687 : // Setup
688 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
689 :
690 : // Decode context
691 0 : fd_exec_test_txn_context_t input[1] = {0};
692 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_txn_context_t_msg );
693 0 : if ( res==NULL ) {
694 0 : sol_compat_cleanup_runner( runner );
695 0 : return 0;
696 0 : }
697 :
698 0 : int ok = 0;
699 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
700 : // Execute
701 0 : void * output = NULL;
702 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_txn_run );
703 :
704 : // Encode effects
705 0 : if( output ) {
706 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_txn_result_t_msg );
707 0 : }
708 0 : } FD_SPAD_FRAME_END;
709 :
710 : // Cleanup
711 0 : pb_release( &fd_exec_test_txn_context_t_msg, input );
712 0 : sol_compat_cleanup_runner( runner );
713 :
714 : // Check wksp usage is 0
715 0 : sol_compat_check_wksp_usage();
716 0 : return ok;
717 0 : }
718 :
719 : int
720 : sol_compat_block_execute_v1( uchar * out,
721 : ulong * out_sz,
722 : uchar const * in,
723 0 : ulong in_sz ) {
724 : // Setup
725 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
726 :
727 : // Decode context
728 0 : fd_exec_test_block_context_t input[1] = {0};
729 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_block_context_t_msg );
730 0 : if ( res==NULL ) {
731 0 : sol_compat_cleanup_runner( runner );
732 0 : return 0;
733 0 : }
734 :
735 0 : int ok = 0;
736 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
737 0 : void * output = NULL;
738 :
739 : // Execute
740 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_block_run );
741 :
742 : // Encode effects
743 0 : if( output ) {
744 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_block_effects_t_msg );
745 0 : }
746 0 : } FD_SPAD_FRAME_END;
747 :
748 : // Cleanup
749 0 : pb_release( &fd_exec_test_block_context_t_msg, input );
750 0 : sol_compat_cleanup_runner( runner );
751 :
752 : // Check wksp usage is 0
753 0 : sol_compat_check_wksp_usage();
754 :
755 0 : return ok;
756 0 : }
757 :
758 : int
759 : sol_compat_elf_loader_v1( uchar * out,
760 : ulong * out_sz,
761 : uchar const * in,
762 0 : ulong in_sz ) {
763 : // Setup
764 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
765 :
766 : // Decode context
767 0 : fd_exec_test_elf_loader_ctx_t input[1] = {0};
768 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_elf_loader_ctx_t_msg );
769 0 : if ( res==NULL ) {
770 0 : sol_compat_cleanup_runner( runner );
771 0 : return 0;
772 0 : }
773 :
774 0 : int ok = 0;
775 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
776 0 : void * output = NULL;
777 :
778 : // Execute
779 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_sbpf_load_run );
780 :
781 : // Encode effects
782 0 : if( output ) {
783 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_elf_loader_effects_t_msg );
784 0 : }
785 0 : } FD_SPAD_FRAME_END;
786 :
787 : // Cleanup
788 0 : pb_release( &fd_exec_test_elf_loader_ctx_t_msg, input );
789 0 : sol_compat_cleanup_runner( runner );
790 :
791 : // Check wksp usage is 0
792 0 : sol_compat_check_wksp_usage();
793 :
794 0 : return ok;
795 0 : }
796 :
797 : int
798 : sol_compat_vm_syscall_execute_v1( uchar * out,
799 : ulong * out_sz,
800 : uchar const * in,
801 0 : ulong in_sz ) {
802 : // Setup
803 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
804 :
805 : // Decode context
806 0 : fd_exec_test_syscall_context_t input[1] = {0};
807 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_syscall_context_t_msg );
808 0 : if ( res==NULL ) {
809 0 : sol_compat_cleanup_runner( runner );
810 0 : return 0;
811 0 : }
812 :
813 0 : int ok = 0;
814 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
815 : // Execute
816 0 : void * output = NULL;
817 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_vm_syscall_run );
818 :
819 : // Encode effects
820 0 : if( output ) {
821 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_syscall_effects_t_msg );
822 0 : }
823 0 : } FD_SPAD_FRAME_END;
824 :
825 : // Cleanup
826 0 : pb_release( &fd_exec_test_syscall_context_t_msg, input );
827 0 : sol_compat_cleanup_runner( runner );
828 :
829 : // Check wksp usage is 0
830 0 : sol_compat_check_wksp_usage();
831 :
832 0 : return ok;
833 0 : }
834 :
835 : int
836 : sol_compat_vm_interp_v1( uchar * out,
837 : ulong * out_sz,
838 : uchar const * in,
839 0 : ulong in_sz ) {
840 : // Setup
841 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
842 :
843 : // Decode context
844 0 : fd_exec_test_syscall_context_t input[1] = {0};
845 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_syscall_context_t_msg );
846 0 : if ( res==NULL ) {
847 0 : sol_compat_cleanup_runner( runner );
848 0 : return 0;
849 0 : }
850 :
851 0 : int ok = 0;
852 :
853 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
854 : // Execute
855 0 : void * output = NULL;
856 0 : sol_compat_execute_wrapper( runner, input, &output, (exec_test_run_fn_t *)fd_runtime_fuzz_vm_interp_run );
857 :
858 : // Encode effects
859 0 : if( output ) {
860 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_syscall_effects_t_msg );
861 0 : }
862 0 : } FD_SPAD_FRAME_END;
863 :
864 : // Cleanup
865 0 : pb_release( &fd_exec_test_syscall_context_t_msg, input );
866 0 : sol_compat_cleanup_runner( runner );
867 :
868 : // Check wksp usage is 0
869 0 : sol_compat_check_wksp_usage();
870 :
871 0 : return ok;
872 0 : }
873 :
874 : int sol_compat_shred_parse_v1( uchar * out,
875 : ulong * out_sz,
876 : uchar const * in,
877 0 : ulong in_sz ) {
878 0 : fd_exec_test_shred_binary_t input[1] = {0};
879 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_shred_binary_t_msg );
880 0 : if( FD_UNLIKELY( res==NULL ) ) {
881 0 : return 0;
882 0 : }
883 0 : if( FD_UNLIKELY( input[0].data==NULL ) ) {
884 0 : pb_release( &fd_exec_test_shred_binary_t_msg, input );
885 0 : return 0;
886 0 : }
887 0 : fd_exec_test_accepts_shred_t output[1] = {0};
888 0 : output[0].valid = !!fd_shred_parse( input[0].data->bytes, input[0].data->size );
889 0 : pb_release( &fd_exec_test_shred_binary_t_msg, input );
890 0 : return !!sol_compat_encode( out, out_sz, output, &fd_exec_test_accepts_shred_t_msg );
891 0 : }
892 :
893 : int
894 : sol_compat_pack_compute_budget_v1( uchar * out,
895 : ulong * out_sz,
896 : uchar const * in,
897 0 : ulong in_sz ) {
898 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner( );
899 :
900 0 : fd_exec_test_pack_compute_budget_context_t input[1] = {0};
901 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_pack_compute_budget_context_t_msg );
902 0 : if( res==NULL ) {
903 0 : sol_compat_cleanup_runner( runner );
904 0 : return 0;
905 0 : }
906 :
907 0 : int ok = 0;
908 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
909 0 : void * output = NULL;
910 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_pack_cpb_run );
911 :
912 0 : if( output ) {
913 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_pack_compute_budget_effects_t_msg );
914 0 : }
915 0 : } FD_SPAD_FRAME_END;
916 :
917 0 : pb_release( &fd_exec_test_pack_compute_budget_context_t_msg, input );
918 0 : sol_compat_cleanup_runner( runner );
919 :
920 : // Check wksp usage is 0
921 0 : sol_compat_check_wksp_usage();
922 0 : return ok;
923 0 : }
924 :
925 : int
926 : sol_compat_type_execute_v1( uchar * out,
927 : ulong * out_sz,
928 : uchar const * in,
929 0 : ulong in_sz ) {
930 : // Setup
931 0 : fd_runtime_fuzz_runner_t * runner = sol_compat_setup_runner();
932 : // Decode context
933 0 : fd_exec_test_type_context_t input[1] = {0};
934 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_type_context_t_msg );
935 0 : if( res==NULL ) {
936 0 : sol_compat_cleanup_runner( runner );
937 0 : return 0;
938 0 : }
939 :
940 0 : int ok = 0;
941 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
942 :
943 0 : void * output = NULL;
944 0 : sol_compat_execute_wrapper( runner, input, &output, fd_runtime_fuzz_type_run );
945 0 : if( output ) {
946 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_type_effects_t_msg );
947 0 : }
948 :
949 0 : } FD_SPAD_FRAME_END;
950 :
951 0 : pb_release( &fd_exec_test_type_context_t_msg, input );
952 0 : sol_compat_cleanup_runner( runner );
953 :
954 0 : sol_compat_check_wksp_usage();
955 :
956 0 : return ok;
957 0 : }
|