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