diff --git a/src/app/fdctl/run/tiles/fd_replay.c b/src/app/fdctl/run/tiles/fd_replay.c index a7f8f248db..27d1485d42 100644 --- a/src/app/fdctl/run/tiles/fd_replay.c +++ b/src/app/fdctl/run/tiles/fd_replay.c @@ -280,7 +280,7 @@ scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) { l = FD_LAYOUT_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT(0) ); } l = FD_LAYOUT_APPEND( l, FD_SCRATCH_ALIGN_DEFAULT, tile->replay.tpool_thread_count * TPOOL_WORKER_MEM_SZ ); - l = FD_LAYOUT_APPEND( l, fd_spad_align(), tile->replay.tpool_thread_count * fd_spad_footprint( MAX_TX_ACCOUNT_LOCKS * fd_ulong_align_up( FD_ACC_TOT_SZ_MAX, FD_ACCOUNT_REC_ALIGN ) ) ); + l = FD_LAYOUT_APPEND( l, fd_spad_align(), tile->replay.tpool_thread_count * FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ); l = FD_LAYOUT_APPEND( l, fd_scratch_smem_align(), fd_scratch_smem_footprint( SCRATCH_MAX ) ); l = FD_LAYOUT_APPEND( l, fd_scratch_fmem_align(), fd_scratch_fmem_footprint( SCRATCH_DEPTH ) ); l = FD_LAYOUT_FINI ( l, scratch_align() ); @@ -1595,7 +1595,7 @@ unprivileged_init( fd_topo_t * topo, ctx->bmtree[i] = FD_SCRATCH_ALLOC_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT(0) ); } void * tpool_worker_mem = FD_SCRATCH_ALLOC_APPEND( l, FD_SCRATCH_ALIGN_DEFAULT, tile->replay.tpool_thread_count * TPOOL_WORKER_MEM_SZ ); - ulong thread_spad_size = fd_spad_footprint( MAX_TX_ACCOUNT_LOCKS * fd_ulong_align_up( FD_ACC_TOT_SZ_MAX, FD_ACCOUNT_REC_ALIGN ) ); + ulong thread_spad_size = FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT; void * spad_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), tile->replay.tpool_thread_count * thread_spad_size ); void * scratch_smem = FD_SCRATCH_ALLOC_APPEND( l, fd_scratch_smem_align(), fd_scratch_smem_footprint( SCRATCH_MAX ) ); void * scratch_fmem = FD_SCRATCH_ALLOC_APPEND( l, fd_scratch_fmem_align(), fd_scratch_fmem_footprint( SCRATCH_DEPTH ) ); diff --git a/src/app/ledger/main.c b/src/app/ledger/main.c index e951883c2b..2926dc5eb0 100644 --- a/src/app/ledger/main.c +++ b/src/app/ledger/main.c @@ -442,7 +442,7 @@ fd_ledger_main_setup( fd_ledger_args_t * args ) { args->spad_cnt = fd_tpool_worker_cnt( args->tpool ); for( ulong i=0UL; ispad_cnt; i++ ) { - ulong total_mem_sz = fd_spad_footprint( MAX_TX_ACCOUNT_LOCKS * fd_ulong_align_up( FD_ACC_TOT_SZ_MAX, FD_ACCOUNT_REC_ALIGN ) ); + ulong total_mem_sz = FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ; uchar * mem = fd_wksp_alloc_laddr( args->wksp, FD_SPAD_ALIGN, total_mem_sz, 999UL ); fd_spad_t * spad = fd_spad_join( fd_spad_new( mem, total_mem_sz ) ); if( FD_UNLIKELY( !spad ) ) { diff --git a/src/flamenco/runtime/context/fd_exec_instr_ctx.h b/src/flamenco/runtime/context/fd_exec_instr_ctx.h index ad05548e50..5ca074d626 100644 --- a/src/flamenco/runtime/context/fd_exec_instr_ctx.h +++ b/src/flamenco/runtime/context/fd_exec_instr_ctx.h @@ -25,7 +25,7 @@ struct __attribute__((aligned(8UL))) fd_exec_instr_ctx { fd_funk_txn_t * funk_txn; fd_acc_mgr_t * acc_mgr; - fd_valloc_t valloc; + fd_valloc_t valloc; /* Scratch-backed valloc TODO: migrate to transaction spad */ /* Most instructions log the base58 program id multiple times, so it's convenient to compute it once and reuse it. */ diff --git a/src/flamenco/runtime/context/fd_exec_txn_ctx.h b/src/flamenco/runtime/context/fd_exec_txn_ctx.h index 4f36e9e381..ce8edbea66 100644 --- a/src/flamenco/runtime/context/fd_exec_txn_ctx.h +++ b/src/flamenco/runtime/context/fd_exec_txn_ctx.h @@ -64,7 +64,8 @@ struct __attribute__((aligned(8UL))) fd_exec_txn_ctx { fd_funk_txn_t * funk_txn; fd_acc_mgr_t * acc_mgr; - fd_valloc_t valloc; + fd_valloc_t valloc; /* Workspace-backed valloc TODO: migrate to spad */ + fd_spad_t * spad; /* Sized out to handle the worst case footprint of single transaction execution. */ ulong paid_fees; ulong compute_unit_limit; /* Compute unit limit for this transaction. */ @@ -126,8 +127,6 @@ struct __attribute__((aligned(8UL))) fd_exec_txn_ctx { int exec_err; int exec_err_kind; - fd_spad_t * spad; - /* The has_program_id flag is used to indicate if the current transaction has valid program indices or not. It will be set in fd_executor_load_transaction_accounts similar to how program_indices is used in load_transaction_accounts on the agave side */ diff --git a/src/flamenco/runtime/fd_executor.c b/src/flamenco/runtime/fd_executor.c index 57c6e43c01..5efcfc6d3d 100644 --- a/src/flamenco/runtime/fd_executor.c +++ b/src/flamenco/runtime/fd_executor.c @@ -1129,6 +1129,7 @@ fd_instr_stack_pop( fd_exec_txn_ctx_t * txn_ctx, int fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, fd_instr_info_t * instr ) { + FD_RUNTIME_SPAD_FRAME_BEGIN( txn_ctx->spad, txn_ctx ) { FD_SCRATCH_SCOPE_BEGIN { fd_exec_instr_ctx_t * parent = NULL; if( txn_ctx->instr_stack_sz ) { @@ -1211,6 +1212,7 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, return exec_result; } FD_SCRATCH_SCOPE_END; + } FD_RUNTIME_SPAD_FRAME_END; } void diff --git a/src/flamenco/runtime/fd_runtime.c b/src/flamenco/runtime/fd_runtime.c index a9d7027dbe..f339660156 100644 --- a/src/flamenco/runtime/fd_runtime.c +++ b/src/flamenco/runtime/fd_runtime.c @@ -1123,7 +1123,7 @@ fd_runtime_prepare_execute_finalize_txn( fd_exec_slot_ctx_t * slot_ctx, fd_capture_ctx_t * capture_ctx, fd_txn_p_t * txn, fd_execute_txn_task_info_t * task_info ) { - + FD_SPAD_FRAME_BEGIN( spad ) { FD_SCRATCH_SCOPE_BEGIN { int res = 0; @@ -1191,6 +1191,7 @@ fd_runtime_prepare_execute_finalize_txn( fd_exec_slot_ctx_t * slot_ctx, return res; } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } @@ -1776,7 +1777,7 @@ fd_runtime_finalize_txns_tpool( fd_exec_slot_ctx_t * slot_ctx, results = fd_scratch_alloc( alignof(uchar), txn_cnt * sizeof(uchar) ); } - fd_borrowed_account_t * * accounts_to_save = fd_scratch_alloc( 8UL, 128UL * txn_cnt * sizeof(fd_borrowed_account_t *) ); + fd_borrowed_account_t * * accounts_to_save = fd_scratch_alloc( 8UL, MAX_TX_ACCOUNT_LOCKS * txn_cnt * sizeof(fd_borrowed_account_t *) ); ulong acc_idx = 0UL; for( ulong txn_idx=0UL; txn_idx=FD_ACCOUNT_REC_DATA_ALIGN, account_rec_d FD_STATIC_ASSERT( (offsetof(fd_account_rec_t, meta)%FD_ACCOUNT_META_ALIGN)==0, account_rec_meta_offset ); FD_STATIC_ASSERT( (offsetof(fd_account_rec_t, data)%FD_ACCOUNT_REC_DATA_ALIGN)==0, account_rec_data_offset ); +#define MAX_PERMITTED_DATA_INCREASE (10240UL) // 10KB +#define FD_BPF_ALIGN_OF_U128 (8UL ) +FD_STATIC_ASSERT( FD_BPF_ALIGN_OF_U128==FD_ACCOUNT_REC_DATA_ALIGN, input_data_align ); +#define FD_RUNTIME_INPUT_REGION_ALLOC_ALIGN_UP (16UL) + +/******** These macros try to bound out memory footprint ********/ + +/* The tight upper bound on borrowed account footprint over the + execution of a single transaction. */ +#define FD_RUNTIME_BORROWED_ACCOUNT_FOOTPRINT (fd_spad_footprint( MAX_TX_ACCOUNT_LOCKS * fd_ulong_align_up( FD_ACC_TOT_SZ_MAX, FD_ACCOUNT_REC_ALIGN ) )) +/* The tight-ish upper bound on input region footprint over the + execution of a single transaction. See input serialization code for + reference: fd_bpf_loader_serialization.c + + This bound is based off of the transaction MTU. We consider the + question of what kind of transaction one would construct to + maximally bloat the input region. + The worst case scenario is when every nested instruction references + all unique accounts in the transaction. A transaction can lock a max + of MAX_TX_ACCOUNT_LOCKS accounts. Then all remaining input account + references are going to be duplicates, which cost 1 byte to specify + offset in payload, and which cost 8 bytes during serialization. Then + there would be 0 bytes of instruction data, because they exist byte + for byte in the raw payload, which is not a worthwhile bloat factor. + */ +#define FD_RUNTIME_INPUT_REGION_UNIQUE_ACCOUNT_FOOTPRINT(direct_mapping) \ + (1UL /* dup byte */ + \ + sizeof(uchar) /* is_signer */ + \ + sizeof(uchar) /* is_writable */ + \ + sizeof(uchar) /* executable */ + \ + sizeof(uint) /* original_data_len */ + \ + sizeof(fd_pubkey_t) /* key */ + \ + sizeof(fd_pubkey_t) /* owner */ + \ + sizeof(ulong) /* lamports */ + \ + sizeof(ulong) /* data len */ + \ + (direct_mapping ? FD_BPF_ALIGN_OF_U128 : fd_ulong_align_up( FD_ACC_SZ_MAX, FD_BPF_ALIGN_OF_U128 )) + \ + MAX_PERMITTED_DATA_INCREASE + \ + sizeof(ulong)) /* rent_epoch */ +#define FD_RUNTIME_INPUT_REGION_INSN_FOOTPRINT(account_lock_limit, direct_mapping) \ + (fd_ulong_align_up( (sizeof(ulong) /* acct_cnt */ + \ + account_lock_limit*FD_RUNTIME_INPUT_REGION_UNIQUE_ACCOUNT_FOOTPRINT(direct_mapping) + \ + sizeof(ulong) /* instr data len */ + \ + /* No instr data */ \ + sizeof(fd_pubkey_t)), /* program id */ \ + FD_RUNTIME_INPUT_REGION_ALLOC_ALIGN_UP ) + FD_BPF_ALIGN_OF_U128) +#define FD_RUNTIME_INPUT_REGION_TXN_FOOTPRINT(account_lock_limit, direct_mapping) \ + (FD_MAX_INSTRUCTION_STACK_DEPTH*FD_RUNTIME_INPUT_REGION_INSN_FOOTPRINT(account_lock_limit, direct_mapping)) + \ + ((FD_TXN_MTU-FD_TXN_MIN_SERIALIZED_SZ-account_lock_limit)*8UL) /* We can have roughly this much duplicate offsets */ +/* Now finally, we bound out the footprint of transaction execution. */ +#define FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT(account_lock_limit, direct_mapping) \ + (FD_RUNTIME_BORROWED_ACCOUNT_FOOTPRINT + \ + FD_RUNTIME_INPUT_REGION_TXN_FOOTPRINT(account_lock_limit, direct_mapping)) +/* Convenience macros for common use cases. */ +#define FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ FD_RUNTIME_BORROWED_ACCOUNT_FOOTPRINT +#define FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT(64UL, 0) + +/* Helpers for runtime spad frame management. */ +struct fd_runtime_spad_handle { + fd_spad_t * spad; + fd_exec_txn_ctx_t * txn_ctx; +}; +typedef struct fd_runtime_spad_handle fd_runtime_spad_handle_t; + +static inline void +fd_runtime_spad_private_frame_end( fd_runtime_spad_handle_t * _spad_handle ) { + /* fd_spad_verify() returns 0 if everything looks good, and non-zero + otherwise. + Since the fast spad alloc API doesn't check for or indicate an OOM + situation and is going to happily permit an OOB alloc, we need + some way of detecting that. Moreover, we would also like to detect + unbalanced frame push/pop or usage of more frames than allowed. + While surrounding the spad with guard regions will help detect the + former, it won't necessarily catch the latter. + On compliant transactions, fd_spad_verify() isn't all that + expensive. Nonetheless, We invoke fd_spad_verify() only at the + peak of memory usage, and not gratuitously everywhere. One peak + would be right before we do the most deeply nested spad frame pop. + However, we do pops through compiler-inserted cleanup functions + that take only a single pointer, so we define this helper function + to access the needed context info. The end result is that we do + super fast spad calls everywhere in the runtime, and every now and + then we invoke verify to check things. */ + /* -1UL because spad pop is called after instr stack pop. */ + if( FD_UNLIKELY( _spad_handle->txn_ctx->instr_stack_sz>=FD_MAX_INSTRUCTION_STACK_DEPTH-1UL && fd_spad_verify( _spad_handle->txn_ctx->spad ) ) ) { + FD_LOG_ERR(( "spad corrupted or overflown" )); + } + fd_spad_pop( _spad_handle->spad ); +} + +#define FD_RUNTIME_SPAD_FRAME_BEGIN(_spad, _txn_ctx) do { \ + fd_runtime_spad_handle_t _spad_handle __attribute__((cleanup(fd_runtime_spad_private_frame_end))) = \ + (fd_runtime_spad_handle_t) { .spad = _spad, .txn_ctx = _txn_ctx }; \ + fd_spad_push( _spad_handle.spad ); \ + do + +#define FD_RUNTIME_SPAD_FRAME_END while(0); } while(0) + FD_PROTOTYPES_BEGIN ulong diff --git a/src/flamenco/runtime/info/fd_instr_info.h b/src/flamenco/runtime/info/fd_instr_info.h index ff312c5801..0eb963d40b 100644 --- a/src/flamenco/runtime/info/fd_instr_info.h +++ b/src/flamenco/runtime/info/fd_instr_info.h @@ -24,6 +24,7 @@ struct fd_instr_info { fd_pubkey_t acct_pubkeys[FD_INSTR_ACCT_MAX]; uchar is_duplicate[FD_INSTR_ACCT_MAX]; + /* Indexed by index in instruction, not by index in transaction. */ fd_borrowed_account_t * borrowed_accounts[FD_INSTR_ACCT_MAX]; /* fd_uwide representation of uint_128 */ diff --git a/src/flamenco/runtime/program/fd_bpf_loader_program.c b/src/flamenco/runtime/program/fd_bpf_loader_program.c index 93e7d7e1c3..b727f639d9 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_program.c +++ b/src/flamenco/runtime/program/fd_bpf_loader_program.c @@ -453,7 +453,7 @@ common_close_account( fd_pubkey_t * authority_address, /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1332-L1501 */ -int +static int execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * prog, uchar is_deprecated ) { fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_valloc_malloc( instr_ctx->valloc, @@ -574,8 +574,6 @@ execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * prog, uc /* Handles instr + EBPF errors */ if( FD_UNLIKELY( exec_err!=FD_VM_SUCCESS ) ) { - fd_valloc_free( instr_ctx->valloc, input ); - /* Instr error case */ if( instr_ctx->txn_ctx->exec_err_kind==FD_EXECUTOR_ERR_KIND_INSTR ) { return instr_ctx->txn_ctx->exec_err; @@ -623,8 +621,6 @@ execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * prog, uc TODO: vm should report */ ulong syscall_err = vm->reg[0]; if( FD_UNLIKELY( syscall_err ) ) { - fd_valloc_free( instr_ctx->valloc, input ); - /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/bpf_loader/src/lib.rs#L1431-L1434 */ instr_ctx->txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_INSTR; return program_error_to_instr_error( syscall_err, &instr_ctx->txn_ctx->custom_err ); @@ -634,16 +630,13 @@ execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * prog, uc if( FD_UNLIKELY( is_deprecated ) ) { err = fd_bpf_loader_input_deserialize_unaligned( *instr_ctx, pre_lens, input, input_sz, !direct_mapping ); if( FD_UNLIKELY( err!=0 ) ) { - fd_valloc_free( instr_ctx->valloc, input ); return err; } } else { err = fd_bpf_loader_input_deserialize_aligned( *instr_ctx, pre_lens, input, input_sz, !direct_mapping ); if( FD_UNLIKELY( err!=0 ) ) { - fd_valloc_free( instr_ctx->valloc, input ); return err; } - } return FD_EXECUTOR_INSTR_SUCCESS; diff --git a/src/flamenco/runtime/program/fd_bpf_loader_serialization.c b/src/flamenco/runtime/program/fd_bpf_loader_serialization.c index fa9a5f44cf..e615a976f5 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_serialization.c +++ b/src/flamenco/runtime/program/fd_bpf_loader_serialization.c @@ -157,7 +157,7 @@ fd_bpf_loader_input_serialize_aligned( fd_exec_instr_ctx_t ctx, /* https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/programs/bpf_loader/src/serialization.rs#L429-L459 */ ulong serialized_size = 0UL; - serialized_size += sizeof(ulong); + serialized_size += sizeof(ulong); // acct_cnt /* First pass is to calculate size of buffer to allocate */ for( ushort i=0; iacct_cnt; i++ ) { uchar acc_idx = instr_acc_idxs[i]; @@ -204,7 +204,7 @@ fd_bpf_loader_input_serialize_aligned( fd_exec_instr_ctx_t ctx, + ctx.instr->data_sz + sizeof(fd_pubkey_t); // program id - uchar * serialized_params = fd_valloc_malloc( ctx.valloc, FD_BPF_ALIGN_OF_U128, fd_ulong_align_up( serialized_size, 16UL ) ); + uchar * serialized_params = fd_spad_alloc( ctx.txn_ctx->spad, FD_BPF_ALIGN_OF_U128, fd_ulong_align_up( serialized_size, FD_RUNTIME_INPUT_REGION_ALLOC_ALIGN_UP ) ); uchar * serialized_params_start = serialized_params; uchar * curr_serialized_params_start = serialized_params; @@ -473,8 +473,6 @@ fd_bpf_loader_input_deserialize_aligned( fd_exec_instr_ctx_t ctx, } } - fd_valloc_free( ctx.valloc, buffer ); - return FD_EXECUTOR_INSTR_SUCCESS; } @@ -538,8 +536,8 @@ fd_bpf_loader_input_serialize_unaligned( fd_exec_instr_ctx_t ctx, + ctx.instr->data_sz // instruction data + sizeof(fd_pubkey_t); // program id - uchar * serialized_params = fd_valloc_malloc( ctx.valloc, 1UL, serialized_size ); - uchar * serialized_params_start = serialized_params; + uchar * serialized_params = fd_spad_alloc( ctx.txn_ctx->spad, 1UL, serialized_size ); + uchar * serialized_params_start = serialized_params; uchar * curr_serialized_params_start = serialized_params; FD_STORE( ulong, serialized_params, ctx.instr->acct_cnt ); @@ -724,7 +722,5 @@ fd_bpf_loader_input_deserialize_unaligned( fd_exec_instr_ctx_t ctx, return FD_EXECUTOR_INSTR_ERR_INVALID_ARG; } - fd_valloc_free( ctx.valloc, input ); - return 0; } diff --git a/src/flamenco/runtime/program/fd_bpf_loader_serialization.h b/src/flamenco/runtime/program/fd_bpf_loader_serialization.h index ba7e2bd49e..a92c705295 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_serialization.h +++ b/src/flamenco/runtime/program/fd_bpf_loader_serialization.h @@ -3,9 +3,8 @@ #include "../../fd_flamenco_base.h" #include "../../vm/fd_vm.h" +#include "../fd_runtime.h" -#define MAX_PERMITTED_DATA_INCREASE (10240UL) -#define FD_BPF_ALIGN_OF_U128 (8UL ) #define FD_NON_DUP_MARKER (0xFF ) FD_PROTOTYPES_BEGIN diff --git a/src/flamenco/runtime/tests/fd_exec_instr_test.c b/src/flamenco/runtime/tests/fd_exec_instr_test.c index 2c7a5fc003..39ce8f405c 100644 --- a/src/flamenco/runtime/tests/fd_exec_instr_test.c +++ b/src/flamenco/runtime/tests/fd_exec_instr_test.c @@ -100,7 +100,8 @@ fd_exec_instr_test_runner_new( void * mem, runner->funk = funk; /* Create spad */ - runner->spad = fd_spad_join( fd_spad_new( spad_mem, fd_spad_footprint( MAX_TX_ACCOUNT_LOCKS * fd_ulong_align_up( FD_ACC_TOT_SZ_MAX, FD_ACCOUNT_REC_ALIGN ) ) ) ); + runner->spad = fd_spad_join( fd_spad_new( spad_mem, FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ ) ); + fd_spad_push( runner->spad ); return runner; } @@ -109,10 +110,18 @@ fd_exec_instr_test_runner_delete( fd_exec_instr_test_runner_t * runner ) { if( FD_UNLIKELY( !runner ) ) return NULL; fd_funk_delete( fd_funk_leave( runner->funk ) ); runner->funk = NULL; + FD_TEST( !fd_spad_verify( runner->spad ) ); + fd_spad_pop( runner->spad ); + FD_TEST( fd_spad_frame_used( runner->spad )==0 ); runner->spad = NULL; return runner; } +fd_spad_t * +fd_exec_instr_test_runner_get_spad( fd_exec_instr_test_runner_t * runner ) { + return runner->spad; +} + static int fd_double_is_normal( double dbl ) { ulong x = fd_dblbits( dbl ); @@ -1707,6 +1716,7 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner, if( !fd_exec_test_instr_context_create( runner, ctx, input_instr_ctx, alloc, skip_extra_checks ) ) goto error; fd_valloc_t valloc = fd_scratch_virtual(); + fd_spad_t * spad = fd_exec_instr_test_runner_get_spad( runner ); /* Capture outputs */ ulong output_end = (ulong)output_buf + output_bufsz; @@ -1750,8 +1760,8 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner, fd_vm_input_region_t * input_regions = NULL; uint input_regions_count = 0U; if( !!(input->vm_ctx.input_data_regions_count) ) { - input_regions = fd_valloc_malloc( valloc, alignof(fd_vm_input_region_t), sizeof(fd_vm_input_region_t) * input->vm_ctx.input_data_regions_count ); - input_regions_count = setup_vm_input_regions( input_regions, input->vm_ctx.input_data_regions, input->vm_ctx.input_data_regions_count, valloc ); + input_regions = fd_spad_alloc( spad, alignof(fd_vm_input_region_t), sizeof(fd_vm_input_region_t) * input->vm_ctx.input_data_regions_count ); + input_regions_count = setup_vm_input_regions( input_regions, input->vm_ctx.input_data_regions, input->vm_ctx.input_data_regions_count, spad ); if ( !input_regions_count ) { goto error; } diff --git a/src/flamenco/runtime/tests/fd_exec_instr_test.h b/src/flamenco/runtime/tests/fd_exec_instr_test.h index d201ec07e5..88f4554c60 100644 --- a/src/flamenco/runtime/tests/fd_exec_instr_test.h +++ b/src/flamenco/runtime/tests/fd_exec_instr_test.h @@ -49,6 +49,9 @@ fd_exec_instr_test_runner_new( void * mem, void * fd_exec_instr_test_runner_delete( fd_exec_instr_test_runner_t * runner ); +fd_spad_t * +fd_exec_instr_test_runner_get_spad( fd_exec_instr_test_runner_t * runner ); + /* fd_exec_test_instr_context_create takes in a test runner and InstrCtx protobuf and creates an fd_exec_instr_ctx_t that can be used in runtime. diff --git a/src/flamenco/runtime/tests/fd_exec_sol_compat.c b/src/flamenco/runtime/tests/fd_exec_sol_compat.c index 59238e8b15..96f183ce0b 100644 --- a/src/flamenco/runtime/tests/fd_exec_sol_compat.c +++ b/src/flamenco/runtime/tests/fd_exec_sol_compat.c @@ -63,7 +63,12 @@ sol_compat_wksp_init( void ) { wksp = fd_wksp_new_anonymous( FD_SHMEM_NORMAL_PAGE_SZ, 65536UL * 8UL, fd_shmem_cpu_idx( fd_shmem_numa_idx( cpu_idx ) ), "wksp", 0UL ); assert( wksp ); - 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 */ + // FD_LOG_WARNING(( "footprint min %lu max %lu default %lu fuzz %lu", + // FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT(64UL,1), + // FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT(MAX_TX_ACCOUNT_LOCKS,0), + // FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT, + // FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ )); + spad_mem = fd_wksp_alloc_laddr( wksp, FD_SPAD_ALIGN, FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ, 3 ); /* 1342191744 B */ assert( spad_mem ); smem = malloc( smax ); /* 1 GiB */ diff --git a/src/flamenco/runtime/tests/fd_vm_test.c b/src/flamenco/runtime/tests/fd_vm_test.c index 6dcd5f4dcb..3f2e2ec4e1 100644 --- a/src/flamenco/runtime/tests/fd_vm_test.c +++ b/src/flamenco/runtime/tests/fd_vm_test.c @@ -155,6 +155,7 @@ fd_exec_vm_interp_test_run( fd_exec_instr_test_runner_t * runner, } fd_valloc_t valloc = fd_scratch_virtual(); + fd_spad_t * spad = fd_exec_instr_test_runner_get_spad( runner ); /* Create effects */ ulong output_end = (ulong) output_buf + output_bufsz; @@ -178,8 +179,8 @@ do{ ulong rodata_sz = input->vm_ctx.rodata->size; /* Load input data regions */ - fd_vm_input_region_t * input_regions = fd_valloc_malloc( valloc, alignof(fd_vm_input_region_t), sizeof(fd_vm_input_region_t) * input->vm_ctx.input_data_regions_count ); - uint input_regions_cnt = setup_vm_input_regions( input_regions, input->vm_ctx.input_data_regions, input->vm_ctx.input_data_regions_count, valloc ); + fd_vm_input_region_t * input_regions = fd_spad_alloc( spad, alignof(fd_vm_input_region_t), sizeof(fd_vm_input_region_t) * input->vm_ctx.input_data_regions_count ); + uint input_regions_cnt = setup_vm_input_regions( input_regions, input->vm_ctx.input_data_regions, input->vm_ctx.input_data_regions_count, spad ); if (input->vm_ctx.heap_max > FD_VM_HEAP_DEFAULT) { break; @@ -341,7 +342,7 @@ uint setup_vm_input_regions( fd_vm_input_region_t * input, fd_exec_test_input_data_region_t const * test_input, ulong test_input_count, - fd_valloc_t valloc ) { + fd_spad_t * spad ) { ulong offset = 0UL; uint input_idx = 0UL; for( ulong i=0; isize ); + uchar * haddr = fd_spad_alloc( spad, 8UL, array->size ); fd_memcpy( haddr, array->bytes, array->size ); input[input_idx].vaddr_offset = offset; input[input_idx].haddr = (ulong)haddr; diff --git a/src/flamenco/runtime/tests/fd_vm_test.h b/src/flamenco/runtime/tests/fd_vm_test.h index f4e80f941c..1c08e1b4a4 100644 --- a/src/flamenco/runtime/tests/fd_vm_test.h +++ b/src/flamenco/runtime/tests/fd_vm_test.h @@ -46,9 +46,9 @@ setup_vm_acc_region_metas( fd_vm_acc_region_meta_t * acc_regions_meta, Empty regions are skipped, so we return the true size of the populated array. */ uint setup_vm_input_regions( fd_vm_input_region_t * input, - fd_exec_test_input_data_region_t const * test_input, - ulong test_input_count, - fd_valloc_t valloc ); + fd_exec_test_input_data_region_t const * test_input, + ulong test_input_count, + fd_spad_t * spad ); ulong load_from_vm_input_regions( fd_vm_input_region_t const * input, diff --git a/src/flamenco/runtime/tests/test_exec_instr.c b/src/flamenco/runtime/tests/test_exec_instr.c index 7a03dd9349..60a778490c 100644 --- a/src/flamenco/runtime/tests/test_exec_instr.c +++ b/src/flamenco/runtime/tests/test_exec_instr.c @@ -69,9 +69,9 @@ main( int argc, ulong scratch_fmem[ 64UL ] __attribute((aligned(FD_SCRATCH_FMEM_ALIGN))); uchar * scratch_smem = malloc( 1 << 30 ); // 1 GB - ulong spad_mem_max = fd_spad_footprint( MAX_TX_ACCOUNT_LOCKS * fd_ulong_align_up( FD_ACC_TOT_SZ_MAX, FD_ACCOUNT_REC_ALIGN ) ); + ulong spad_mem_max = FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ; uchar * spad_mem = fd_wksp_alloc_laddr( wksp, FD_SPAD_ALIGN, spad_mem_max, 3 ); /* 1342191744 B */ - + fd_scratch_attach( scratch_smem, scratch_fmem, 1UL<<30, 64UL ); // Setup usage tracking