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