diff --git a/src/app/fdctl/run/tiles/fd_replay.c b/src/app/fdctl/run/tiles/fd_replay.c index df06783a27..3db2257385 100644 --- a/src/app/fdctl/run/tiles/fd_replay.c +++ b/src/app/fdctl/run/tiles/fd_replay.c @@ -294,7 +294,8 @@ 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 ) ) ); + ulong thread_spad_size = fd_spad_footprint( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ); + l = FD_LAYOUT_APPEND( l, fd_spad_align(), tile->replay.tpool_thread_count * fd_ulong_align_up( thread_spad_size, fd_spad_align() ) ); 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() ); @@ -1723,8 +1724,8 @@ 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 ) ); - void * spad_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), tile->replay.tpool_thread_count * thread_spad_size ); + ulong thread_spad_size = fd_spad_footprint( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ); + void * spad_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), tile->replay.tpool_thread_count * fd_ulong_align_up( thread_spad_size, fd_spad_align() ) ); 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 ) ); ulong scratch_alloc_mem = FD_SCRATCH_ALLOC_FINI ( l, scratch_align() ); @@ -1950,7 +1951,7 @@ unprivileged_init( fd_topo_t * topo, for( ulong i=0UL; ireplay.tpool_thread_count; i++ ) { fd_spad_t * spad = fd_spad_join( fd_spad_new( spad_mem_cur, thread_spad_size ) ); ctx->spads[ ctx->spad_cnt++ ] = spad; - spad_mem_cur += thread_spad_size; + spad_mem_cur += fd_ulong_align_up( thread_spad_size, fd_spad_align() ); } /**********************************************************************/ diff --git a/src/app/ledger/main.c b/src/app/ledger/main.c index ce0e5c11a4..4ffd3a85d1 100644 --- a/src/app/ledger/main.c +++ b/src/app/ledger/main.c @@ -467,7 +467,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..968f0bae26 100644 --- a/src/flamenco/runtime/context/fd_exec_instr_ctx.h +++ b/src/flamenco/runtime/context/fd_exec_instr_ctx.h @@ -25,7 +25,6 @@ struct __attribute__((aligned(8UL))) fd_exec_instr_ctx { fd_funk_txn_t * funk_txn; fd_acc_mgr_t * acc_mgr; - fd_valloc_t valloc; /* 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_slot_ctx.c b/src/flamenco/runtime/context/fd_exec_slot_ctx.c index 70b31320bc..6fd96974df 100644 --- a/src/flamenco/runtime/context/fd_exec_slot_ctx.c +++ b/src/flamenco/runtime/context/fd_exec_slot_ctx.c @@ -127,7 +127,7 @@ recover_clock( fd_exec_slot_ctx_t * slot_ctx ) { /* Record timestamp */ if( vote_state_timestamp.slot != 0 || n->elem.stake != 0 ) { - fd_vote_record_timestamp_vote_with_slot(slot_ctx, &n->elem.key, vote_state_timestamp.timestamp, vote_state_timestamp.slot); + fd_vote_record_timestamp_vote_with_slot( slot_ctx, &n->elem.key, vote_state_timestamp.timestamp, vote_state_timestamp.slot, slot_ctx->valloc ); } } diff --git a/src/flamenco/runtime/context/fd_exec_txn_ctx.c b/src/flamenco/runtime/context/fd_exec_txn_ctx.c index 7da9f56b83..dd71436cc6 100644 --- a/src/flamenco/runtime/context/fd_exec_txn_ctx.c +++ b/src/flamenco/runtime/context/fd_exec_txn_ctx.c @@ -266,7 +266,6 @@ fd_exec_txn_ctx_from_exec_slot_ctx( fd_exec_slot_ctx_t * slot_ctx, fd_exec_txn_ctx_t * txn_ctx ) { txn_ctx->slot_ctx = slot_ctx; txn_ctx->epoch_ctx = slot_ctx->epoch_ctx; - txn_ctx->valloc = slot_ctx->valloc; txn_ctx->funk_txn = NULL; txn_ctx->acc_mgr = slot_ctx->acc_mgr; } diff --git a/src/flamenco/runtime/context/fd_exec_txn_ctx.h b/src/flamenco/runtime/context/fd_exec_txn_ctx.h index f803c2fc0a..dc6a2e3b44 100644 --- a/src/flamenco/runtime/context/fd_exec_txn_ctx.h +++ b/src/flamenco/runtime/context/fd_exec_txn_ctx.h @@ -64,7 +64,7 @@ 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_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 +126,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 a08e9f74aa..f60e2a624f 100644 --- a/src/flamenco/runtime/fd_executor.c +++ b/src/flamenco/runtime/fd_executor.c @@ -1185,6 +1185,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_TXN_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 ) { @@ -1203,7 +1204,6 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, .txn_ctx = txn_ctx, .epoch_ctx = txn_ctx->epoch_ctx, .slot_ctx = txn_ctx->slot_ctx, - .valloc = fd_scratch_virtual(), .acc_mgr = txn_ctx->acc_mgr, .funk_txn = txn_ctx->funk_txn, .parent = parent, @@ -1267,6 +1267,7 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, return exec_result; } FD_SCRATCH_SCOPE_END; + } FD_RUNTIME_TXN_SPAD_FRAME_END; } void @@ -1477,45 +1478,6 @@ fd_execute_txn_prepare_phase3( fd_exec_slot_ctx_t * slot_ctx, return 0; } -/* Stuff to be done after multithreading ends */ -int -fd_execute_txn_finalize( fd_exec_txn_ctx_t * txn_ctx, - int exec_txn_err ) { - if( exec_txn_err != 0 ) { - for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) { - fd_borrowed_account_t * acc_rec = &txn_ctx->borrowed_accounts[i]; - void * acc_rec_data = fd_borrowed_account_destroy( acc_rec ); - if( acc_rec_data != NULL ) { - fd_valloc_free( txn_ctx->valloc, acc_rec_data ); - } - } - - // fd_funk_txn_cancel( slot_ctx->acc_mgr->funk, txn_ctx->funk_txn, 0 ); - return 0; - } - - for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) { - if( !fd_txn_account_is_writable_idx( txn_ctx, (int)i ) ) { - continue; - } - - fd_borrowed_account_t * acc_rec = &txn_ctx->borrowed_accounts[i]; - - int ret = fd_acc_mgr_save_non_tpool( txn_ctx->acc_mgr, txn_ctx->funk_txn, acc_rec ); - if( ret != FD_ACC_MGR_SUCCESS ) { - FD_LOG_ERR(( "failed to save edits to accounts" )); - return -1; - } - - void * borrow_account_data = fd_borrowed_account_destroy( acc_rec ); - if( borrow_account_data != NULL ) { - fd_valloc_free( txn_ctx->valloc, borrow_account_data ); - } - } - - return 0; -} - /* Creates a TxnContext Protobuf message from a provided txn_ctx. - The transaction is assumed to have just finished phase 1 of preparation - Caller of this function should have a scratch frame ready @@ -1851,10 +1813,8 @@ fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t *txn_ctx, fd_spad_t * spad ) { fd_base58_encode_64( signature, &out_size, encoded_signature ); if( txn_ctx->capture_ctx->dump_proto_sig_filter ) { - ulong filter_strlen = (ulong) strlen(txn_ctx->capture_ctx->dump_proto_sig_filter); - // Terminate early if the signature does not match - if( memcmp( txn_ctx->capture_ctx->dump_proto_sig_filter, encoded_signature, filter_strlen < out_size ? filter_strlen : out_size ) ) { + if( strcmp( txn_ctx->capture_ctx->dump_proto_sig_filter, encoded_signature ) ) { return; } } diff --git a/src/flamenco/runtime/fd_executor.h b/src/flamenco/runtime/fd_executor.h index 0e594708a4..6db4c38bf7 100644 --- a/src/flamenco/runtime/fd_executor.h +++ b/src/flamenco/runtime/fd_executor.h @@ -91,10 +91,6 @@ fd_execute_txn_prepare_phase3( fd_exec_slot_ctx_t * slot_ctx, fd_exec_txn_ctx_t * txn_ctx, fd_txn_p_t * txn ); -int -fd_execute_txn_finalize( fd_exec_txn_ctx_t * txn_ctx, - int exec_txn_err ); - /* Execute the given transaction. diff --git a/src/flamenco/runtime/fd_runtime.c b/src/flamenco/runtime/fd_runtime.c index 7e76f81d5d..75a0533fe0 100644 --- a/src/flamenco/runtime/fd_runtime.c +++ b/src/flamenco/runtime/fd_runtime.c @@ -296,7 +296,9 @@ fd_runtime_init_bank_from_genesis( fd_exec_slot_ctx_t * slot_ctx, .unused = 0, .vote_accounts = (fd_vote_accounts_t){ .vote_accounts_pool = vacc_pool, - .vote_accounts_root = vacc_root}}; + .vote_accounts_root = vacc_root}, + .stake_history = {0} + }; slot_ctx->slot_bank.capitalization = capitalization; @@ -1100,7 +1102,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; @@ -1121,8 +1123,6 @@ fd_runtime_prepare_execute_finalize_txn( fd_exec_slot_ctx_t * slot_ctx, return -1; } - txn_ctx->valloc = fd_scratch_virtual(); - /* NOTE: This intentionally does not have sigverify */ fd_runtime_pre_execute_check( task_info ); @@ -1148,6 +1148,7 @@ fd_runtime_prepare_execute_finalize_txn( fd_exec_slot_ctx_t * slot_ctx, return res; } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } @@ -1441,13 +1442,13 @@ fd_runtime_finalize_txn( fd_exec_slot_ctx_t * slot_ctx, if( dirty_vote_acc && 0==memcmp( acc_rec->const_meta->info.owner, &fd_solana_vote_program_id, sizeof(fd_pubkey_t) ) ) { /* lock for inserting/modifying vote accounts in slot ctx. */ fd_funk_start_write( slot_ctx->acc_mgr->funk ); - fd_vote_store_account( slot_ctx, acc_rec ); - FD_SCRATCH_SCOPE_BEGIN { + fd_vote_store_account( slot_ctx, acc_rec, txn_ctx->spad ); + FD_SPAD_FRAME_BEGIN( txn_ctx->spad ) { fd_vote_state_versioned_t vsv[1]; fd_bincode_decode_ctx_t decode_vsv = { .data = acc_rec->const_data, .dataend = acc_rec->const_data + acc_rec->const_meta->dlen, - .valloc = fd_scratch_virtual() }; + .valloc = fd_spad_virtual( txn_ctx->spad ) }; int err = fd_vote_state_versioned_decode( vsv, &decode_vsv ); if( err ) break; /* out of scratch scope */ @@ -1467,9 +1468,9 @@ fd_runtime_finalize_txn( fd_exec_slot_ctx_t * slot_ctx, __builtin_unreachable(); } - fd_vote_record_timestamp_vote_with_slot( slot_ctx, acc_rec->pubkey, ts->timestamp, ts->slot ); - } - FD_SCRATCH_SCOPE_END; + fd_valloc_t valloc = fd_spad_virtual( txn_ctx->spad ); + fd_vote_record_timestamp_vote_with_slot( slot_ctx, acc_rec->pubkey, ts->timestamp, ts->slot, valloc ); + } FD_SPAD_FRAME_END; fd_funk_end_write( slot_ctx->acc_mgr->funk ); } @@ -1730,7 +1731,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; ulong nonvote_txn_count = 0; ulong failed_txn_count = 0; @@ -1833,13 +1834,13 @@ fd_runtime_finalize_txns_tpool( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * acc_rec = &txn_ctx->borrowed_accounts[i]; if( dirty_vote_acc && !memcmp( acc_rec->const_meta->info.owner, &fd_solana_vote_program_id, sizeof(fd_pubkey_t) ) ) { - fd_vote_store_account( slot_ctx, acc_rec ); - FD_SCRATCH_SCOPE_BEGIN { + fd_vote_store_account( slot_ctx, acc_rec, txn_ctx->spad ); + FD_SPAD_FRAME_BEGIN( txn_ctx->spad ) { fd_vote_state_versioned_t vsv[1]; fd_bincode_decode_ctx_t decode_vsv = { .data = acc_rec->const_data, .dataend = acc_rec->const_data + acc_rec->const_meta->dlen, - .valloc = fd_scratch_virtual() }; + .valloc = fd_spad_virtual( txn_ctx->spad ) }; int err = fd_vote_state_versioned_decode( vsv, &decode_vsv ); if( err ) break; /* out of scratch scope */ @@ -1859,9 +1860,9 @@ fd_runtime_finalize_txns_tpool( fd_exec_slot_ctx_t * slot_ctx, __builtin_unreachable(); } - fd_vote_record_timestamp_vote_with_slot( slot_ctx, acc_rec->pubkey, ts->timestamp, ts->slot ); - } - FD_SCRATCH_SCOPE_END; + fd_valloc_t valloc = fd_spad_virtual( txn_ctx->spad ); + fd_vote_record_timestamp_vote_with_slot( slot_ctx, acc_rec->pubkey, ts->timestamp, ts->slot, valloc ); + } FD_SPAD_FRAME_END; } if( dirty_stake_acc && !memcmp( acc_rec->const_meta->info.owner, &fd_solana_stake_program_id, sizeof(fd_pubkey_t) ) ) { @@ -2116,11 +2117,11 @@ fd_runtime_execute_txns_in_waves_tpool( fd_exec_slot_ctx_t * slot_ctx, next_incomplete_txn_idxs = temp_incomplete_txn_idxs; incomplete_txn_idxs_cnt = next_incomplete_txn_idxs_cnt; - // Dump txns in waves - if( dump_txn ) { - for( ulong i = 0; i < wave_task_infos_cnt; ++i ) { - fd_dump_txn_to_protobuf( wave_task_infos[i].txn_ctx, spads[0] ); - } + for( ulong i=0UL; ivalloc, &err)) { + FD_SPAD_FRAME_BEGIN( txn_ctx->spad ) { + if ((NULL != txn_descriptor) && fd_load_nonce_account(txn_ctx, &state, fd_spad_virtual( txn_ctx->spad ), &err)) { if (state.inner.current.discriminant == fd_nonce_state_enum_initialized) return state.inner.current.inner.initialized.fee_calculator.lamports_per_signature; } + } FD_SPAD_FRAME_END; // lamports_per_signature = (transaction has a DurableNonce, use the lamports_per_signature from that nonce instead of looking up the recent_block_hash and using the lamports_per_signature associated with that hash // let TransactionExecutionDetails { diff --git a/src/flamenco/runtime/fd_runtime.h b/src/flamenco/runtime/fd_runtime.h index b70dfb8bfe..1156bc5a24 100644 --- a/src/flamenco/runtime/fd_runtime.h +++ b/src/flamenco/runtime/fd_runtime.h @@ -13,6 +13,7 @@ #include "context/fd_exec_epoch_ctx.h" #include "context/fd_exec_slot_ctx.h" #include "context/fd_capture_ctx.h" +#include "context/fd_exec_txn_ctx.h" #include "info/fd_block_info.h" #include "info/fd_instr_info.h" #include "../gossip/fd_gossip.h" @@ -95,6 +96,170 @@ FD_STATIC_ASSERT( FD_ACCOUNT_REC_ALIGN>=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 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 (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 */ + +/* Bincode valloc footprint over the execution of a single transaction. + As well as other footprint specific to each native program type. + + N.B. We know that bincode valloc footprint is bounded, because + whenever we alloc something, we advance our pointer into the binary + buffer, so eventually we are gonna reach the end of the buffer. + This buffer is usually backed by and ultimately bounded in size by + either accounts data or the transaction MTU. + + That being said, it's not obvious what the tight upper bound would + be for allocations across all possible execution paths of all native + programs, including possible CPIs from native programs. The + footprint estimate here is based on a manual review of our native + program implementation. Note that even if the possible paths remain + steady at the Solana protocol level, the footprint is subject to + change when we change our implementation. + + ### Native programs + ALUT (migrated to BPF) + Loader + - rodata for bpf program relocation and validation + Compute budget (0 allocations) + Config (migrated to BPF) + Precompile (0 allocations) + Stake + - The instruction with the largest footprint is deactivate_delinquent + - During instruction decode, no allocations + - During execution, this is (vote account get_state() + vote convert_to_current()) times 2, once for delinquent_vote_account, and once for reference_vote_account + System + - system_program_instruction_decode seed + Vote + - The instruction with the largest footprint is compact vote state update + - During instruction decode, this is 9*lockouts_len bytes, MTU bounded + - During execution, this is vote account get_state() + vote convert_to_current() + 12*lockouts_len bytes + lockouts_len ulong + deq_fd_landed_vote_t_alloc(lockouts_len) + Zk Elgamal (0 allocations) + + The largest footprint is hence deactivate_delinquent, in which the + two get_state() calls dominate the footprint. In particular, the + authorized_voters treaps bloat 40 bytes (epoch+pubkey) in a vote + account to 72 bytes (sizeof(fd_vote_authorized_voter_t)) in memory. + */ +#define FD_RUNTIME_BINCODE_AND_NATIVE_FOOTPRINT (2UL*FD_ACC_SZ_MAX*72UL/40UL) + +/* Misc other footprint. */ +#define FD_RUNTIME_SYSCALL_TABLE_FOOTPRINT (FD_MAX_INSTRUCTION_STACK_DEPTH*fd_ulong_align_up( fd_sbpf_syscalls_footprint(), fd_sbpf_syscalls_align() )) + +#ifdef FD_DEBUG_SBPF_TRACES +#define FD_RUNTIME_VM_TRACE_EVENT_MAX (1UL<<30) +#define FD_RUNTIME_VM_TRACE_EVENT_DATA_MAX (2048UL) +#define FD_RUNTIME_VM_TRACE_FOOTPRINT (FD_MAX_INSTRUCTION_STACK_DEPTH*fd_ulong_align_up( fd_vm_trace_footprint( FD_RUNTIME_VM_TRACE_EVENT_MAX, FD_RUNTIME_VM_TRACE_EVENT_DATA_MAX ), fd_vm_trace_align() )) +#else +#define FD_RUNTIME_VM_TRACE_FOOTPRINT (0UL) +#endif + +#define FD_RUNTIME_MISC_FOOTPRINT (FD_RUNTIME_SYSCALL_TABLE_FOOTPRINT+FD_RUNTIME_VM_TRACE_FOOTPRINT) + +/* 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) + \ + FD_RUNTIME_BINCODE_AND_NATIVE_FOOTPRINT + \ + FD_RUNTIME_MISC_FOOTPRINT) + +/* 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_verify_handle_private { + fd_spad_t * spad; + fd_exec_txn_ctx_t * txn_ctx; +}; +typedef struct fd_runtime_spad_verify_handle_private fd_runtime_spad_verify_handle_private_t; + +static inline void +fd_runtime_spad_private_frame_end( fd_runtime_spad_verify_handle_private_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 ) ) ) { + uchar const * txn_signature = (uchar const *)fd_txn_get_signatures( _spad_handle->txn_ctx->txn_descriptor, _spad_handle->txn_ctx->_txn_raw->raw ); + FD_BASE58_ENCODE_64_BYTES( txn_signature, sig ); + FD_LOG_ERR(( "spad corrupted or overflown on transaction %s", sig )); + } + fd_spad_pop( _spad_handle->spad ); +} + +#define FD_RUNTIME_TXN_SPAD_FRAME_BEGIN(_spad, _txn_ctx) do { \ + fd_runtime_spad_verify_handle_private_t _spad_handle __attribute__((cleanup(fd_runtime_spad_private_frame_end))) = \ + (fd_runtime_spad_verify_handle_private_t) { .spad = _spad, .txn_ctx = _txn_ctx }; \ + fd_spad_push( _spad_handle.spad ); \ + do + +#define FD_RUNTIME_TXN_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 d01a669401..d7a2239c40 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_address_lookup_table_program.c b/src/flamenco/runtime/program/fd_address_lookup_table_program.c index 22dfc4e868..012c457f60 100644 --- a/src/flamenco/runtime/program/fd_address_lookup_table_program.c +++ b/src/flamenco/runtime/program/fd_address_lookup_table_program.c @@ -292,9 +292,9 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx, /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L144-L149 */ if( required_lamports>0UL ) { // Create account metas - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t *) - fd_scratch_alloc( FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t) ); + fd_spad_alloc( ctx->txn_ctx->spad, FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t) ); fd_native_cpi_create_account_meta( payer_key, 1, 1, &acct_metas[0] ); fd_native_cpi_create_account_meta( lut_key, 0, 1, &acct_metas[1] ); @@ -319,12 +319,12 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx, if( FD_UNLIKELY( err ) ) { return err; } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { fd_vm_rust_account_meta_t * acct_metas = ( fd_vm_rust_account_meta_t * ) - fd_scratch_alloc( FD_VM_RUST_ACCOUNT_META_ALIGN, sizeof(fd_vm_rust_account_meta_t) ); + fd_spad_alloc( ctx->txn_ctx->spad, FD_VM_RUST_ACCOUNT_META_ALIGN, sizeof(fd_vm_rust_account_meta_t) ); fd_native_cpi_create_account_meta( lut_key, 1, 1, &acct_metas[0] ); // Create signers list @@ -365,7 +365,7 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx, if( FD_UNLIKELY( err ) ) { return err; } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, ACC_IDX_LUT, lut_acct ) { @@ -662,10 +662,10 @@ extend_lookup_table( fd_exec_instr_ctx_t * ctx, } FD_BORROWED_ACCOUNT_DROP( payer_acct ); - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { // Create account metas fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t *) - fd_scratch_alloc( FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t) ); + fd_spad_alloc( ctx->txn_ctx->spad, FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t) ); fd_native_cpi_create_account_meta( payer_key, 1, 1, &acct_metas[0] ); fd_native_cpi_create_account_meta( lut_key, 0, 1, &acct_metas[1] ); @@ -688,7 +688,7 @@ extend_lookup_table( fd_exec_instr_ctx_t * ctx, if( FD_UNLIKELY( err ) ) { return err; } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } return FD_EXECUTOR_INSTR_SUCCESS; @@ -955,10 +955,10 @@ fd_address_lookup_table_program_execute( fd_exec_instr_ctx_t * ctx ) { return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA; } - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { fd_bincode_decode_ctx_t decode = { - .valloc = fd_scratch_virtual(), + .valloc = fd_spad_virtual( ctx->txn_ctx->spad ), .data = instr_data, .dataend = instr_data + instr_data_sz }; @@ -983,7 +983,7 @@ fd_address_lookup_table_program_execute( fd_exec_instr_ctx_t * ctx ) { default: break; } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; return FD_EXECUTOR_INSTR_SUCCESS; } diff --git a/src/flamenco/runtime/program/fd_bpf_loader_program.c b/src/flamenco/runtime/program/fd_bpf_loader_program.c index 883d3f68f3..0ca7a0fcf8 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_program.c +++ b/src/flamenco/runtime/program/fd_bpf_loader_program.c @@ -127,8 +127,9 @@ fd_bpf_loader_v2_is_executable( fd_exec_slot_ctx_t * slot_ctx, /* This is literally called before every single instruction execution */ int -fd_bpf_loader_v3_is_executable( fd_exec_slot_ctx_t * slot_ctx, - fd_pubkey_t const * pubkey ) { +fd_bpf_loader_v3_is_executable( fd_exec_slot_ctx_t * slot_ctx, + fd_pubkey_t const * pubkey, + fd_exec_instr_ctx_t const * instr_ctx ) { int err = 0; fd_account_meta_t const * meta = fd_acc_mgr_view_raw( slot_ctx->acc_mgr, slot_ctx->funk_txn, (fd_pubkey_t *) pubkey, NULL, &err, NULL ); @@ -147,7 +148,7 @@ fd_bpf_loader_v3_is_executable( fd_exec_slot_ctx_t * slot_ctx, fd_bincode_decode_ctx_t ctx = { .data = (uchar *)meta + meta->hlen, .dataend = (char *) ctx.data + meta->dlen, - .valloc = fd_scratch_virtual(), + .valloc = fd_spad_virtual( instr_ctx->txn_ctx->spad ), }; fd_bpf_upgradeable_loader_state_t loader_state = {0}; @@ -186,7 +187,7 @@ read_bpf_upgradeable_loader_state_for_program( fd_exec_txn_ctx_t * fd_bincode_decode_ctx_t ctx = { .data = rec->const_data, .dataend = rec->const_data + rec->const_meta->dlen, - .valloc = fd_scratch_virtual(), + .valloc = fd_spad_virtual( txn_ctx->spad ), }; if( FD_UNLIKELY( fd_bpf_upgradeable_loader_state_decode( result, &ctx ) ) ) { @@ -236,11 +237,13 @@ calculate_heap_cost( ulong heap_size, ulong heap_cost, int * err ) { int fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, uchar const * programdata, - ulong programdata_size ) { + ulong programdata_size, + fd_valloc_t valloc /* Majority of use cases this is a txn ctx spad under the hood; for native to bpf migration this is scratch backed since it's an epoch level event. */ + ) { int deploy_mode = 1; int direct_mapping = FD_FEATURE_ACTIVE( instr_ctx->slot_ctx, bpf_account_data_direct_mapping ); - - fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_scratch_alloc( fd_sbpf_syscalls_align(), + fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_valloc_malloc( valloc, + fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() ) ); if( FD_UNLIKELY( !syscalls ) ) { //TODO: full log including err @@ -261,7 +264,7 @@ fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, } /* Allocate rodata segment */ - void * rodata = fd_scratch_alloc( FD_SBPF_PROG_RODATA_ALIGN, elf_info->rodata_footprint ); + void * rodata = fd_valloc_malloc( valloc, FD_SBPF_PROG_RODATA_ALIGN, elf_info->rodata_footprint ); if( FD_UNLIKELY( !rodata ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; } @@ -269,7 +272,7 @@ fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, /* Allocate program buffer */ ulong prog_align = fd_sbpf_program_align(); ulong prog_footprint = fd_sbpf_program_footprint( elf_info ); - fd_sbpf_program_t * prog = fd_sbpf_program_new( fd_scratch_alloc( prog_align, prog_footprint ), elf_info, rodata ); + fd_sbpf_program_t * prog = fd_sbpf_program_new( fd_valloc_malloc( valloc, prog_align, prog_footprint ), elf_info, rodata ); if( FD_UNLIKELY( !prog ) ) { FD_LOG_ERR(( "fd_sbpf_program_new() failed: %s", fd_sbpf_strerror() )); } @@ -360,14 +363,14 @@ write_program_data( fd_exec_instr_ctx_t * instr_ctx, /* get_state() */ /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/sdk/src/transaction_context.rs#L968-L972 */ int -fd_bpf_loader_v3_program_get_state( fd_exec_instr_ctx_t * instr_ctx, - fd_borrowed_account_t * borrowed_acc, - fd_bpf_upgradeable_loader_state_t * state ) { +fd_bpf_loader_v3_program_get_state( fd_exec_instr_ctx_t const * instr_ctx, + fd_borrowed_account_t const * borrowed_acc, + fd_bpf_upgradeable_loader_state_t * state ) { /* Check to see if the buffer account is already initialized */ fd_bincode_decode_ctx_t ctx = { .data = borrowed_acc->const_data, .dataend = borrowed_acc->const_data + borrowed_acc->const_meta->dlen, - .valloc = instr_ctx->valloc, + .valloc = fd_spad_virtual( instr_ctx->txn_ctx->spad ), }; int err = fd_bpf_upgradeable_loader_state_decode( state, &ctx ); @@ -460,11 +463,12 @@ common_close_account( fd_pubkey_t * authority_address, int fd_bpf_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, - fd_sbpf_syscalls_align(), - fd_sbpf_syscalls_footprint() ) ); + fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc( instr_ctx->txn_ctx->spad, + fd_sbpf_syscalls_align(), + fd_sbpf_syscalls_footprint() ) ); FD_TEST( syscalls ); + /* TODO do we really need to re-do this on every instruction? */ fd_vm_syscall_register_slot( syscalls, instr_ctx->slot_ctx, 0 ); /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1362-L1368 */ @@ -531,17 +535,19 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * p return FD_EXECUTOR_INSTR_ERR_PROGRAM_ENVIRONMENT_SETUP_FAILURE; } + fd_valloc_t valloc = fd_spad_virtual( instr_ctx->txn_ctx->spad ); + #ifdef FD_DEBUG_SBPF_TRACES uchar * signature = (uchar*)vm->instr_ctx->txn_ctx->_txn_raw->raw + vm->instr_ctx->txn_ctx->txn_descriptor->signature_off; uchar sig[64]; /* TODO (topointon): make this run-time configurable, no need for this ifdef */ fd_base58_decode_64( "tkacc4VCh2z9cLsQowCnKqX14DmUUxpRyES755FhUzrFxSFvo8kVk444kNTL7kJxYnnANYwRWAdHCgBJupftZrz", sig ); if( FD_UNLIKELY( !memcmp( signature, sig, 64UL ) ) ) { - ulong event_max = 1UL<<30; - ulong event_data_max = 2048UL; + ulong event_max = FD_RUNTIME_VM_TRACE_EVENT_MAX; + ulong event_data_max = FD_RUNTIME_VM_TRACE_EVENT_DATA_MAX; vm->trace = fd_vm_trace_join( fd_vm_trace_new( fd_valloc_malloc( - instr_ctx->txn_ctx->valloc, fd_vm_trace_align(), fd_vm_trace_footprint( event_max, event_data_max ) ), event_max, event_data_max ) ); - if( FD_UNLIKELY( !vm->trace ) ) FD_LOG_ERR(( "unable to create trace" )); + valloc, fd_vm_trace_align(), fd_vm_trace_footprint( event_max, event_data_max ) ), event_max, event_data_max ) ); + if( FD_UNLIKELY( !vm->trace ) ) FD_LOG_ERR(( "unable to create trace; make sure you've compiled with sufficient spad size " )); } #endif @@ -567,7 +573,7 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * p if( FD_UNLIKELY( err ) ) { FD_LOG_WARNING(( "fd_vm_trace_printf failed (%i-%s)", err, fd_vm_strerror( err ) )); } - fd_valloc_free( instr_ctx->txn_ctx->valloc, fd_vm_trace_delete( fd_vm_trace_leave( vm->trace ) ) ); + fd_valloc_free( valloc, fd_vm_trace_delete( fd_vm_trace_leave( vm->trace ) ) ); } /* Log consumed compute units and return data. @@ -579,8 +585,6 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * p /* 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; @@ -629,8 +633,6 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * p 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 ); @@ -640,16 +642,13 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * p 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; @@ -659,12 +658,13 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * p static int process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { uchar const * data = instr_ctx->instr->data; + fd_valloc_t valloc = fd_spad_virtual( instr_ctx->txn_ctx->spad ); fd_bpf_upgradeable_loader_program_instruction_t instruction = {0}; fd_bincode_decode_ctx_t decode_ctx = {0}; decode_ctx.data = data; decode_ctx.dataend = &data[ instr_ctx->instr->data_sz > 1232UL ? 1232UL : instr_ctx->instr->data_sz ]; - decode_ctx.valloc = instr_ctx->valloc; + decode_ctx.valloc = valloc; int err = fd_bpf_upgradeable_loader_program_instruction_decode( &instruction, &decode_ctx ); if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) { @@ -934,7 +934,8 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { instr.inner.create_account = create_acct; fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t*) - fd_scratch_alloc( FD_VM_RUST_ACCOUNT_META_ALIGN, + fd_valloc_malloc( valloc, + FD_VM_RUST_ACCOUNT_META_ALIGN, 3UL * sizeof(fd_vm_rust_account_meta_t) ); fd_native_cpi_create_account_meta( payer_key, 1U, 1U, &acct_metas[ 0UL ] ); fd_native_cpi_create_account_meta( programdata_key, 1U, 1U, &acct_metas[ 1UL ] ); @@ -961,7 +962,7 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { const uchar * buffer_data = buffer->const_data + buffer_data_offset; - err = fd_deploy_program( instr_ctx, buffer_data, buffer_data_len ); + err = fd_deploy_program( instr_ctx, buffer_data, buffer_data_len, fd_spad_virtual( instr_ctx->txn_ctx->spad ) ); if( FD_UNLIKELY( err ) ) { FD_LOG_WARNING(( "Failed to deploy program" )); // custom log return err; @@ -1217,7 +1218,7 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { } const uchar * buffer_data = buffer->const_data + buffer_data_offset; - err = fd_deploy_program( instr_ctx, buffer_data, buffer_data_len ); + err = fd_deploy_program( instr_ctx, buffer_data, buffer_data_len, fd_spad_virtual( instr_ctx->txn_ctx->spad ) ); if( FD_UNLIKELY( err ) ) { FD_LOG_WARNING(( "Failed to deploy program" )); return err; @@ -1718,9 +1719,10 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { .inner.transfer = required_payment }; - fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t *)fd_scratch_alloc( - FD_VM_RUST_ACCOUNT_META_ALIGN, - 2UL * sizeof(fd_vm_rust_account_meta_t) ); + fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t *) + fd_valloc_malloc( valloc, + FD_VM_RUST_ACCOUNT_META_ALIGN, + 2UL * sizeof(fd_vm_rust_account_meta_t) ); fd_native_cpi_create_account_meta( payer_key, 1UL, 1UL, &acct_metas[ 0UL ] ); fd_native_cpi_create_account_meta( programdata_key, 0UL, 1UL, &acct_metas[ 1UL ] ); @@ -1748,7 +1750,7 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { uchar * programdata_data = programdata_account->data + PROGRAMDATA_METADATA_SIZE; ulong programdata_size = new_len - PROGRAMDATA_METADATA_SIZE; - err = fd_deploy_program( instr_ctx, programdata_data, programdata_size ); + err = fd_deploy_program( instr_ctx, programdata_data, programdata_size, fd_spad_virtual( instr_ctx->txn_ctx->spad ) ); if( FD_UNLIKELY( err ) ) { FD_LOG_WARNING(( "Failed to deploy program" )); return err; @@ -1794,7 +1796,7 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L394-L564 */ int fd_bpf_loader_program_execute( fd_exec_instr_ctx_t * ctx ) { - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L491-L529 */ fd_borrowed_account_t * program_account = NULL; @@ -1967,7 +1969,7 @@ fd_bpf_loader_program_execute( fd_exec_instr_ctx_t * ctx ) { } return fd_bpf_execute( ctx, prog, is_deprecated ); - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } @@ -1988,7 +1990,6 @@ fd_directly_invoke_loader_v3_deploy( fd_exec_slot_ctx_t * slot_ctx, .txn_ctx = txn_ctx, .epoch_ctx = txn_ctx->epoch_ctx, .slot_ctx = txn_ctx->slot_ctx, - .valloc = fd_scratch_virtual(), .acc_mgr = txn_ctx->acc_mgr, .funk_txn = txn_ctx->funk_txn, .parent = NULL, @@ -1997,5 +1998,5 @@ fd_directly_invoke_loader_v3_deploy( fd_exec_slot_ctx_t * slot_ctx, .child_cnt = 0U, }; - return fd_deploy_program( instr_ctx, elf, elf_sz ); + return fd_deploy_program( instr_ctx, elf, elf_sz, fd_scratch_virtual() ); } diff --git a/src/flamenco/runtime/program/fd_bpf_loader_program.h b/src/flamenco/runtime/program/fd_bpf_loader_program.h index 7c2c3afaa2..65fb5f5b63 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_program.h +++ b/src/flamenco/runtime/program/fd_bpf_loader_program.h @@ -51,14 +51,15 @@ FD_PROTOTYPES_BEGIN int -fd_bpf_loader_v3_program_get_state( fd_exec_instr_ctx_t * instr_ctx, - fd_borrowed_account_t * borrowed_acc, - fd_bpf_upgradeable_loader_state_t * state ); +fd_bpf_loader_v3_program_get_state( fd_exec_instr_ctx_t const * instr_ctx, + fd_borrowed_account_t const * borrowed_acc, + fd_bpf_upgradeable_loader_state_t * state ); int fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, uchar const * programdata, - ulong programdata_size ); + ulong programdata_size, + fd_valloc_t valloc ); int fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_sbpf_validated_program_t * prog, uchar is_deprecated ); diff --git a/src/flamenco/runtime/program/fd_bpf_loader_serialization.c b/src/flamenco/runtime/program/fd_bpf_loader_serialization.c index c276e067ff..d188e8a576 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_serialization.c +++ b/src/flamenco/runtime/program/fd_bpf_loader_serialization.c @@ -1,5 +1,6 @@ #include "fd_bpf_loader_serialization.h" #include "../fd_account.h" +#include "../fd_runtime.h" /* As a general note, copy_account_data implies that direct mapping is not being used/is inactive. This file is responsible for serializing and deserializing @@ -157,7 +158,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]; @@ -194,7 +195,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; @@ -415,8 +416,6 @@ fd_bpf_loader_input_deserialize_aligned( fd_exec_instr_ctx_t ctx, } } - fd_valloc_free( ctx.valloc, buffer ); - return FD_EXECUTOR_INSTR_SUCCESS; } @@ -469,8 +468,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 ); @@ -615,7 +614,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..9d16210178 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_serialization.h +++ b/src/flamenco/runtime/program/fd_bpf_loader_serialization.h @@ -4,8 +4,6 @@ #include "../../fd_flamenco_base.h" #include "../../vm/fd_vm.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/program/fd_compute_budget_program.c b/src/flamenco/runtime/program/fd_compute_budget_program.c index 36afdec8a9..89879247e5 100644 --- a/src/flamenco/runtime/program/fd_compute_budget_program.c +++ b/src/flamenco/runtime/program/fd_compute_budget_program.c @@ -58,7 +58,7 @@ fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx fd_bincode_decode_ctx_t decode_ctx = { .data = data, .dataend = &data[ instr->data_sz ], - .valloc = ctx->valloc, + .valloc = fd_spad_virtual( ctx->spad ), }; int ret = fd_compute_budget_program_instruction_decode( &instruction, &decode_ctx ); diff --git a/src/flamenco/runtime/program/fd_config_program.c b/src/flamenco/runtime/program/fd_config_program.c index f967ed5abe..39919d3c76 100644 --- a/src/flamenco/runtime/program/fd_config_program.c +++ b/src/flamenco/runtime/program/fd_config_program.c @@ -28,7 +28,7 @@ _process_config_instr( fd_exec_instr_ctx_t * ctx ) { } fd_bincode_decode_ctx_t decode = - { .valloc = ctx->valloc, + { .valloc = fd_spad_virtual( ctx->txn_ctx->spad ), .data = ctx->instr->data, .dataend = ctx->instr->data + ctx->instr->data_sz }; @@ -63,7 +63,7 @@ _process_config_instr( fd_exec_instr_ctx_t * ctx ) { /* https://github.com/solana-labs/solana/blob/v1.17.17/programs/config/src/config_processor.rs#L33-L40 */ fd_bincode_decode_ctx_t config_acc_state_decode_context = { - .valloc = ctx->valloc, + .valloc = fd_spad_virtual( ctx->txn_ctx->spad ), .data = config_acc_rec->const_data, .dataend = config_acc_rec->const_data + config_acc_rec->const_meta->dlen, }; @@ -253,10 +253,12 @@ fd_config_program_execute( fd_exec_instr_ctx_t * ctx ) { See DEFAULT_COMPUTE_UNITS */ FD_EXEC_CU_UPDATE( ctx, DEFAULT_COMPUTE_UNITS ); + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { FD_SCRATCH_SCOPE_BEGIN { int ret = _process_config_instr( ctx ); return ret; } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } diff --git a/src/flamenco/runtime/program/fd_loader_v4_program.c b/src/flamenco/runtime/program/fd_loader_v4_program.c index 2946f9d46c..c34b2dd3d6 100644 --- a/src/flamenco/runtime/program/fd_loader_v4_program.c +++ b/src/flamenco/runtime/program/fd_loader_v4_program.c @@ -418,7 +418,7 @@ fd_loader_v4_program_instruction_deploy( fd_exec_instr_ctx_t * instr_ctx ) { end of the slot. Since programs cannot be invoked until the next slot anyways, doing this is okay. https://github.com/anza-xyz/agave/blob/09ef71223b24e30e59eaeaf5eb95e85f222c7de1/programs/loader-v4/src/lib.rs#L262-L269 */ - err = fd_deploy_program( instr_ctx, programdata, buffer->const_meta->dlen - LOADER_V4_PROGRAM_DATA_OFFSET ); + err = fd_deploy_program( instr_ctx, programdata, buffer->const_meta->dlen - LOADER_V4_PROGRAM_DATA_OFFSET, fd_spad_virtual( instr_ctx->txn_ctx->spad ) ); if( FD_UNLIKELY( err ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; } @@ -686,7 +686,7 @@ fd_loader_v4_program_execute( fd_exec_instr_ctx_t * instr_ctx ) { return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID; } - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( instr_ctx->txn_ctx->spad ) { /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/loader-v4/src/lib.rs#L470 */ fd_pubkey_t const * program_id = &instr_ctx->instr->program_id_pubkey; @@ -704,7 +704,7 @@ fd_loader_v4_program_execute( fd_exec_instr_ctx_t * instr_ctx ) { fd_bincode_decode_ctx_t decode_ctx = { .data = data, .dataend = &data[ instr_ctx->instr->data_sz > 1232UL ? 1232UL : instr_ctx->instr->data_sz ], - .valloc = instr_ctx->valloc, + .valloc = fd_spad_virtual( instr_ctx->txn_ctx->spad ), }; if( FD_UNLIKELY( fd_loader_v4_program_instruction_decode( &instruction, &decode_ctx ) ) ) { @@ -796,5 +796,5 @@ fd_loader_v4_program_execute( fd_exec_instr_ctx_t * instr_ctx ) { } return rc; - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } diff --git a/src/flamenco/runtime/program/fd_stake_program.c b/src/flamenco/runtime/program/fd_stake_program.c index 82725031a9..605446a541 100644 --- a/src/flamenco/runtime/program/fd_stake_program.c +++ b/src/flamenco/runtime/program/fd_stake_program.c @@ -136,7 +136,7 @@ get_state( fd_borrowed_account_t const * self, fd_bincode_decode_ctx_t bincode_ctx; bincode_ctx.data = self->const_data; bincode_ctx.dataend = self->const_data + self->const_meta->dlen; - bincode_ctx.valloc = valloc; + bincode_ctx.valloc = valloc; /* No real allocation from this valloc. */ rc = fd_stake_state_v2_decode( out, &bincode_ctx ); if( FD_UNLIKELY( rc!=FD_BINCODE_SUCCESS ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; @@ -1218,7 +1218,7 @@ initialize( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L224 fd_stake_state_v2_t stake_state = {0}; do { - int rc = get_state( stake_account, fd_scratch_virtual(), &stake_state ); + int rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_state ); if( FD_UNLIKELY( rc ) ) return rc; } while(0); @@ -1261,7 +1261,7 @@ authorize( fd_exec_instr_ctx_t const * ctx, int rc; fd_stake_state_v2_t stake_state = {0}; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L251 - rc = get_state( stake_account, fd_scratch_virtual(), &stake_state ); + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_state ); if( FD_UNLIKELY( rc ) ) return rc; switch( stake_state.discriminant ) { /* FIXME check if the compiler can optimize away branching (given the layout of `meta` in both @@ -1360,7 +1360,7 @@ delegate( fd_exec_instr_ctx_t const * ctx, fd_pubkey_t const * signers[static FD_TXN_SIG_MAX] ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); fd_pubkey_t const * vote_pubkey; fd_vote_state_versioned_t vote_state = {0}; @@ -1374,15 +1374,15 @@ delegate( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L3326 vote_pubkey = vote_account->pubkey; // https://github.com/anza-xyz/agave/blob/a60fbc2288d626a4f1846052c8fcb98d3f9ea58d/programs/stake/src/stake_state.rs#L327 - vote_get_state_rc = fd_vote_get_state( vote_account, scratch_valloc, &vote_state ); + vote_get_state_rc = fd_vote_get_state( vote_account, valloc, &vote_state ); } FD_BORROWED_ACCOUNT_DROP( vote_account ); fd_stake_state_v2_t stake_state = {0}; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L330 FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) { - - rc = get_state( stake_account, fd_scratch_virtual(), &stake_state ); + + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_state ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L332 @@ -1404,7 +1404,7 @@ delegate( fd_exec_instr_ctx_t const * ctx, ulong stake_amount = validated_delegated_info.stake_amount; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L340 if( FD_UNLIKELY( vote_get_state_rc ) ) return vote_get_state_rc; - fd_vote_convert_to_current( &vote_state, scratch_valloc ); // FIXME + fd_vote_convert_to_current( &vote_state, valloc ); // FIXME fd_stake_t stake = new_stake( stake_amount, vote_pubkey, &vote_state.inner.current, clock->epoch ); // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L343 @@ -1434,7 +1434,7 @@ delegate( fd_exec_instr_ctx_t const * ctx, ulong stake_amount = validated_delegated_info.stake_amount; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L354 if( FD_UNLIKELY( vote_get_state_rc ) ) return vote_get_state_rc; - fd_vote_convert_to_current( &vote_state, scratch_valloc ); + fd_vote_convert_to_current( &vote_state, valloc ); // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L349 rc = redelegate_stake( ctx, &stake, @@ -1472,7 +1472,7 @@ deactivate( fd_exec_instr_ctx_t const * ctx, int rc; fd_stake_state_v2_t state = {0}; - rc = get_state( stake_account, fd_scratch_virtual(), &state ); + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &state ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L370 @@ -1506,7 +1506,7 @@ set_lockup( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L385 fd_stake_state_v2_t state = {0}; - rc = get_state( stake_account, fd_scratch_virtual(), &state ); + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &state ); if( FD_UNLIKELY( rc ) ) return rc; switch( state.discriminant ) { @@ -1553,7 +1553,7 @@ split( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L415 fd_stake_state_v2_t split_get_state = {0}; - rc = get_state( split, fd_scratch_virtual(), &split_get_state ); + rc = get_state( split, fd_spad_virtual( ctx->txn_ctx->spad ), &split_get_state ); if( FD_UNLIKELY( rc ) ) return rc; if( FD_UNLIKELY( split_get_state.discriminant!=fd_stake_state_v2_enum_uninitialized ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; @@ -1570,8 +1570,8 @@ split( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L422 if( FD_UNLIKELY( lamports>stake_account->const_meta->info.lamports ) ) return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS; - - rc = get_state( stake_account, fd_scratch_virtual(), &stake_state ); + + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_state ); if( FD_UNLIKELY( rc ) ) return rc; } FD_BORROWED_ACCOUNT_DROP( stake_account ); @@ -1791,7 +1791,7 @@ merge( fd_exec_instr_ctx_t * ctx, // not const to log FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) { fd_stake_state_v2_t stake_account_state = {0}; - rc = get_state( stake_account, fd_scratch_virtual(), &stake_account_state ); + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_account_state ); if( FD_UNLIKELY( rc ) ) return rc; merge_kind_t stake_merge_kind = {0}; @@ -1813,7 +1813,7 @@ merge( fd_exec_instr_ctx_t * ctx, // not const to log return rc; fd_stake_state_v2_t source_account_state = {0}; - rc = get_state( source_account, fd_scratch_virtual(), &source_account_state ); + rc = get_state( source_account, fd_spad_virtual( ctx->txn_ctx->spad ), &source_account_state ); if( FD_UNLIKELY( rc ) ) return rc; merge_kind_t source_merge_kind = {0}; @@ -1914,7 +1914,7 @@ move_stake_or_lamports_shared_checks( fd_exec_instr_ctx_t * invoke_context, // // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L182 fd_stake_state_v2_t source_account_state = {0}; - rc = get_state( source_account, fd_scratch_virtual(), &source_account_state ); + rc = get_state( source_account, fd_spad_virtual( invoke_context->txn_ctx->spad ), &source_account_state ); if( FD_UNLIKELY( rc ) ) return rc; rc = get_if_mergeable( invoke_context, @@ -1932,7 +1932,7 @@ move_stake_or_lamports_shared_checks( fd_exec_instr_ctx_t * invoke_context, // // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L197 fd_stake_state_v2_t destination_account_state = {0}; - rc = get_state( destination_account, fd_scratch_virtual(), &destination_account_state ); + rc = get_state( destination_account, fd_spad_virtual( invoke_context->txn_ctx->spad ), &destination_account_state ); if( FD_UNLIKELY( rc ) ) return rc; rc = get_if_mergeable( invoke_context, @@ -2199,7 +2199,7 @@ withdraw( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L821 fd_stake_state_v2_t stake_state = {0}; - rc = get_state( stake_account, fd_scratch_virtual(), &stake_state ); + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_state ); if( FD_UNLIKELY( rc ) ) return rc; fd_stake_lockup_t lockup; @@ -2340,7 +2340,7 @@ deactivate_delinquent( fd_exec_instr_ctx_t * ctx, uint * custom_err ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L911 fd_pubkey_t const * delinquent_vote_account_pubkey = @@ -2355,9 +2355,9 @@ deactivate_delinquent( fd_exec_instr_ctx_t * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L920-L922 fd_vote_state_versioned_t delinquent_vote_state_versioned = {0}; - rc = fd_vote_get_state( delinquent_vote_account, scratch_valloc, &delinquent_vote_state_versioned ); + rc = fd_vote_get_state( delinquent_vote_account, valloc, &delinquent_vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - fd_vote_convert_to_current( &delinquent_vote_state_versioned, scratch_valloc ); + fd_vote_convert_to_current( &delinquent_vote_state_versioned, valloc ); fd_vote_state_t delinquent_vote_state = delinquent_vote_state_versioned.inner.current; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L924 @@ -2369,9 +2369,9 @@ deactivate_delinquent( fd_exec_instr_ctx_t * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L929-L932 fd_vote_state_versioned_t reference_vote_state_versioned = {0}; - rc = fd_vote_get_state( reference_vote_account, scratch_valloc, &reference_vote_state_versioned ); + rc = fd_vote_get_state( reference_vote_account, valloc, &reference_vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - fd_vote_convert_to_current( &reference_vote_state_versioned, scratch_valloc ); + fd_vote_convert_to_current( &reference_vote_state_versioned, valloc ); fd_vote_state_t reference_vote_state = reference_vote_state_versioned.inner.current; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L933 @@ -2381,7 +2381,7 @@ deactivate_delinquent( fd_exec_instr_ctx_t * ctx, } fd_stake_state_v2_t stake_state = {0}; - rc = get_state( stake_account, fd_scratch_virtual(), &stake_state ); + rc = get_state( stake_account, fd_spad_virtual( ctx->txn_ctx->spad ), &stake_state ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L937 if( FD_LIKELY( stake_state.discriminant==fd_stake_state_v2_enum_stake ) ) { @@ -2481,7 +2481,8 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { } // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L79 - fd_valloc_t valloc = fd_scratch_virtual(); + fd_spad_t * spad = ctx->txn_ctx->spad; + fd_valloc_t valloc = fd_spad_virtual( spad ); fd_bincode_decode_ctx_t decode = { .valloc = valloc, .data = ctx->instr->data, @@ -2730,7 +2731,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { * Processor: * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L188 */ - case fd_stake_instruction_enum_withdraw: FD_SCRATCH_SCOPE_BEGIN { + case fd_stake_instruction_enum_withdraw: FD_SPAD_FRAME_BEGIN( spad ) { ulong lamports = instruction->inner.withdraw; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L189 @@ -2771,7 +2772,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { fd_ptr_if( ctx->instr->acct_cnt>=6, &custodian_index, NULL ), fd_ptr_if( is_some, &new_rate_activation_epoch, NULL ) ); - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; /* No real allocations. Just logically whatever alloc there is, this is where their life ends. */ break; /* Deactivate diff --git a/src/flamenco/runtime/program/fd_system_program.c b/src/flamenco/runtime/program/fd_system_program.c index fd1a2987bf..fd7c380747 100644 --- a/src/flamenco/runtime/program/fd_system_program.c +++ b/src/flamenco/runtime/program/fd_system_program.c @@ -616,7 +616,7 @@ fd_system_program_execute( fd_exec_instr_ctx_t * ctx ) { fd_bincode_decode_ctx_t decode = { .data = data, .dataend = data + ctx->instr->data_sz, - .valloc = fd_scratch_virtual() }; + .valloc = fd_spad_virtual( ctx->txn_ctx->spad ) }; /* Fail if the number of bytes consumed by deserialize exceeds 1232 */ if( fd_system_program_instruction_decode( &instruction, &decode ) || (ulong)data + 1232UL < (ulong)decode.data ) @@ -693,7 +693,7 @@ fd_system_program_execute( fd_exec_instr_ctx_t * ctx ) { } } - fd_bincode_destroy_ctx_t destroy = { .valloc = ctx->valloc }; + fd_bincode_destroy_ctx_t destroy = { .valloc = fd_spad_virtual( ctx->txn_ctx->spad ) }; fd_system_program_instruction_destroy( &instruction, &destroy ); return result; } diff --git a/src/flamenco/runtime/program/fd_vote_program.c b/src/flamenco/runtime/program/fd_vote_program.c index 09eb79fec6..f5a496700a 100644 --- a/src/flamenco/runtime/program/fd_vote_program.c +++ b/src/flamenco/runtime/program/fd_vote_program.c @@ -244,12 +244,13 @@ authorized_voters_last( fd_vote_authorized_voters_t * self ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L43 static void authorized_voters_purge_authorized_voters( fd_vote_authorized_voters_t * self, - ulong current_epoch ) { + ulong current_epoch, + fd_exec_instr_ctx_t const * ctx /* spad */ ) { - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L46 - ulong *expired_keys = fd_scratch_alloc( alignof(ulong), fd_vote_authorized_voters_treap_ele_cnt(self->treap) * sizeof(ulong) ); + ulong *expired_keys = fd_spad_alloc( ctx->txn_ctx->spad, alignof(ulong), fd_vote_authorized_voters_treap_ele_cnt(self->treap) * sizeof(ulong) ); ulong key_cnt = 0; for( fd_vote_authorized_voters_treap_fwd_iter_t iter = fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool ); @@ -272,8 +273,7 @@ authorized_voters_purge_authorized_voters( fd_vote_authorized_voters_t * self, // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L60 FD_TEST( !authorized_voters_is_empty( self ) ); - } - FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } @@ -671,7 +671,8 @@ process_next_vote_slot( fd_vote_state_t * self, static int get_and_update_authorized_voter( fd_vote_state_t * self, ulong current_epoch, - fd_pubkey_t ** pubkey /* out */ ) { + fd_pubkey_t ** pubkey /* out */, + fd_exec_instr_ctx_t const * ctx /* spad */ ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L832 fd_vote_authorized_voter_t * authorized_voter = authorized_voters_get_and_cache_authorized_voter_for_epoch( &self->authorized_voters, @@ -680,7 +681,7 @@ get_and_update_authorized_voter( fd_vote_state_t * self, if( FD_UNLIKELY( !authorized_voter ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; *pubkey = &authorized_voter->pubkey; // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L837 - authorized_voters_purge_authorized_voters( &self->authorized_voters, current_epoch ); + authorized_voters_purge_authorized_voters( &self->authorized_voters, current_epoch, ctx ); return FD_EXECUTOR_INSTR_SUCCESS; } @@ -697,7 +698,7 @@ set_new_authorized_voter( fd_vote_state_t * self, fd_pubkey_t * epoch_authorized_voter = NULL; // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L778 - rc = get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter ); + rc = get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter, ctx ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L779 @@ -813,7 +814,7 @@ set_vote_account_state( ulong vote_acct_idx, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L184 fd_vote_state_versioned_t v1_14_11; fd_vote_state_versioned_new_disc( &v1_14_11, fd_vote_state_versioned_enum_v1_14_11 ); - from_vote_state_1_14_11( vote_state, &v1_14_11.inner.v1_14_11, fd_scratch_virtual() ); + from_vote_state_1_14_11( vote_state, &v1_14_11.inner.v1_14_11, fd_spad_virtual( ctx->txn_ctx->spad ) ); return set_state( vote_acct_idx, vote_account, &v1_14_11, ctx ); } @@ -827,7 +828,7 @@ set_vote_account_state( ulong vote_acct_idx, fd_vote_state_versioned_t v1_14_11; fd_vote_state_versioned_new_disc( &v1_14_11, fd_vote_state_versioned_enum_v1_14_11 ); - from_vote_state_1_14_11( vote_state, &v1_14_11.inner.v1_14_11, fd_scratch_virtual() ); + from_vote_state_1_14_11( vote_state, &v1_14_11.inner.v1_14_11, fd_spad_virtual( ctx->txn_ctx->spad ) ); return set_state( vote_acct_idx, vote_account, &v1_14_11, ctx ); } } @@ -945,7 +946,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, } } - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { /* Index into the new proposed vote state's slots, starting with the root if it exists then we use this mutable root to fold checking the root slot into the below loop for performance */ @@ -958,7 +959,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, /* Index into the slot_hashes, starting at the oldest known slot hash */ // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L264 ulong slot_hashes_index = deq_fd_slot_hash_t_cnt( slot_hashes->hashes ); - ulong * proposed_lockouts_indexes_to_filter = fd_scratch_alloc( alignof(ulong), lockouts_len * sizeof(ulong) ); + ulong * proposed_lockouts_indexes_to_filter = fd_spad_alloc( ctx->txn_ctx->spad, alignof(ulong), lockouts_len * sizeof(ulong) ); ulong filter_index = 0UL; @@ -1134,7 +1135,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, deq_fd_vote_lockout_t_pop_idx_tail( proposed_lockouts, proposed_lockouts_indexes_to_filter[ proposed_lockouts_index ] ); filter_votes_index--; } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; return FD_EXECUTOR_INSTR_SUCCESS; } @@ -1457,13 +1458,13 @@ authorize( ulong vote_acct_idx, fd_exec_instr_ctx_t const * ctx /* feature_set */ ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L857 fd_vote_state_versioned_t vote_state_versioned; - rc = get_state( vote_account, scratch_valloc, &vote_state_versioned ); + rc = get_state( vote_account, valloc, &vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - convert_to_current( &vote_state_versioned, scratch_valloc ); + convert_to_current( &vote_state_versioned, valloc ); fd_vote_state_t * vote_state = &vote_state_versioned.inner.current; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L861 @@ -1513,13 +1514,13 @@ update_validator_identity( ulong vote_acct_idx, fd_exec_instr_ctx_t const * ctx /* feature_set */ ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L900 fd_vote_state_versioned_t vote_state_versioned; - rc = get_state( vote_account, scratch_valloc, &vote_state_versioned ); + rc = get_state( vote_account, valloc, &vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - convert_to_current( &vote_state_versioned, scratch_valloc ); + convert_to_current( &vote_state_versioned, valloc ); fd_vote_state_t * vote_state = &vote_state_versioned.inner.current; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L905 @@ -1561,7 +1562,7 @@ update_commission( ulong vote_acct_idx, fd_exec_instr_ctx_t const * ctx /* feature_set */ ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L925 fd_vote_state_versioned_t vote_state_versioned; fd_vote_state_t * vote_state = NULL; @@ -1569,9 +1570,9 @@ update_commission( ulong vote_acct_idx, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L927 int enforce_commission_update_rule = 1; if (FD_FEATURE_ACTIVE( ctx->slot_ctx, allow_commission_decrease_at_any_time )) { - rc = get_state( vote_account, scratch_valloc, &vote_state_versioned ); + rc = get_state( vote_account, valloc, &vote_state_versioned ); if ( FD_LIKELY( rc==FD_EXECUTOR_INSTR_SUCCESS ) ) { - convert_to_current( &vote_state_versioned, scratch_valloc ); + convert_to_current( &vote_state_versioned, valloc ); vote_state = &vote_state_versioned.inner.current; enforce_commission_update_rule = commission > vote_state->commission; } @@ -1588,9 +1589,9 @@ update_commission( ulong vote_acct_idx, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L949 if (NULL == vote_state) { - rc = get_state( vote_account, scratch_valloc, &vote_state_versioned ); + rc = get_state( vote_account, valloc, &vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - convert_to_current( &vote_state_versioned, scratch_valloc ); + convert_to_current( &vote_state_versioned, valloc ); vote_state = &vote_state_versioned.inner.current; } @@ -1621,13 +1622,13 @@ withdraw( ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1010 fd_vote_state_versioned_t vote_state_versioned; - rc = get_state( vote_account, scratch_valloc, &vote_state_versioned ); + rc = get_state( vote_account, valloc, &vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - convert_to_current( &vote_state_versioned, scratch_valloc ); + convert_to_current( &vote_state_versioned, valloc ); fd_vote_state_t * vote_state = &vote_state_versioned.inner.current; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1014 @@ -1738,7 +1739,7 @@ process_vote( fd_vote_state_t * vote_state, } ulong vote_slots_cnt = deq_ulong_cnt( vote->slots ); - uchar * vote_slots_mem = fd_scratch_alloc( deq_ulong_align(), deq_ulong_footprint( vote_slots_cnt ) ); + uchar * vote_slots_mem = fd_spad_alloc( ctx->txn_ctx->spad, deq_ulong_align(), deq_ulong_footprint( vote_slots_cnt ) ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L796 ulong * vote_slots = deq_ulong_join( deq_ulong_new( vote_slots_mem, vote_slots_cnt ) ); for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots ); @@ -1772,7 +1773,7 @@ initialize_account( ulong vote_acct_idx, fd_exec_instr_ctx_t const * ctx /* feature_set */ ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1067 ulong data_len = vote_account->const_meta->dlen; @@ -1783,7 +1784,7 @@ initialize_account( ulong vote_acct_idx, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1074 fd_vote_state_versioned_t versioned; - rc = get_state( vote_account, scratch_valloc, &versioned ); + rc = get_state( vote_account, valloc, &versioned ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1076 @@ -1794,11 +1795,18 @@ initialize_account( ulong vote_acct_idx, rc = verify_authorized_signer( &vote_init->node_pubkey, signers ); if( FD_UNLIKELY( rc ) ) return rc; + /* + * N.B. Technically we should destroy() to release memory before + * newing, otherwise the pointers are wiped and memory is leaked. + * We are probably fine for now since we are bump allocating + * everything and the enclosing frame will free everything when + * popped. + */ // reset the object fd_vote_state_versioned_new( &versioned ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1083 - vote_state_new( vote_init, clock, scratch_valloc, &versioned.inner.current ); + vote_state_new( vote_init, clock, valloc, &versioned.inner.current ); return set_vote_account_state( vote_acct_idx, vote_account, &versioned.inner.current, ctx ); } @@ -1807,14 +1815,15 @@ static int verify_and_get_vote_state( fd_borrowed_account_t * vote_account, fd_sol_sysvar_clock_t const * clock, fd_pubkey_t const * signers[FD_TXN_SIG_MAX], - fd_vote_state_t * vote_state /* out */ ) { + fd_vote_state_t * vote_state /* out */, + fd_exec_instr_ctx_t const * ctx /* spad */ ) { int rc; fd_vote_state_versioned_t versioned; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1091 - rc = get_state( vote_account, scratch_valloc, &versioned ); + rc = get_state( vote_account, valloc, &versioned ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1093 @@ -1822,12 +1831,12 @@ verify_and_get_vote_state( fd_borrowed_account_t * vote_account, return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1097 - convert_to_current( &versioned, scratch_valloc ); + convert_to_current( &versioned, valloc ); memcpy( vote_state, &versioned.inner.current, sizeof( fd_vote_state_t ) ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1098 fd_pubkey_t * authorized_voter = NULL; - rc = get_and_update_authorized_voter( vote_state, clock->epoch, &authorized_voter ); + rc = get_and_update_authorized_voter( vote_state, clock->epoch, &authorized_voter, ctx ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1099 @@ -1850,7 +1859,7 @@ process_vote_with_account( ulong vote_acct_idx, int rc; fd_vote_state_t vote_state; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1112 - rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state ); + rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state, ctx ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1114 @@ -1899,7 +1908,7 @@ do_process_vote_state_update( fd_vote_state_t * vote_state, fd_exec_instr_ctx_t const * ctx /* feature_set */ ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1164 rc = check_and_filter_proposed_vote_state( @@ -1909,7 +1918,7 @@ do_process_vote_state_update( fd_vote_state_t * vote_state, if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1177 - fd_landed_vote_t * landed_votes = deq_fd_landed_vote_t_alloc( scratch_valloc, deq_fd_vote_lockout_t_cnt( vote_state_update->lockouts ) ); + fd_landed_vote_t * landed_votes = deq_fd_landed_vote_t_alloc( valloc, deq_fd_vote_lockout_t_cnt( vote_state_update->lockouts ) ); for( deq_fd_vote_lockout_t_iter_t iter = deq_fd_vote_lockout_t_iter_init( vote_state_update->lockouts ); !deq_fd_vote_lockout_t_iter_done( vote_state_update->lockouts, iter ); @@ -1980,7 +1989,7 @@ process_vote_state_update( ulong vote_acct_idx, fd_vote_state_t vote_state; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1144 - rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state ); + rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state, ctx ); if( FD_UNLIKELY( rc ) ) return rc; @@ -2015,11 +2024,12 @@ do_process_tower_sync( fd_vote_state_t * vote_state, if( FD_UNLIKELY( err ) ) return err; } while(0); - fd_scratch_push(); + int err; + FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1221 - int err = process_new_vote_state( + err = process_new_vote_state( vote_state, - landed_votes_from_lockouts( tower_sync->lockouts, fd_scratch_virtual() ), + landed_votes_from_lockouts( tower_sync->lockouts, fd_spad_virtual( ctx->txn_ctx->spad ) ), tower_sync->has_root, tower_sync->root, tower_sync->has_timestamp, @@ -2027,7 +2037,7 @@ do_process_tower_sync( fd_vote_state_t * vote_state, epoch, slot, ctx ); - fd_scratch_pop(); + } FD_SPAD_FRAME_END; return err; } @@ -2068,7 +2078,7 @@ process_tower_sync( ulong vote_acct_idx, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1194 fd_vote_state_t vote_state; do { - int err = verify_and_get_vote_state( vote_account, clock, signers, &vote_state ); + int err = verify_and_get_vote_state( vote_account, clock, signers, &vote_state, ctx ); if( FD_UNLIKELY( err ) ) return err; } while(0); @@ -2088,7 +2098,8 @@ process_tower_sync( ulong vote_acct_idx, int fd_vote_decode_compact_update( fd_compact_vote_state_update_t * compact_update, - fd_vote_state_update_t * vote_update ) { + fd_vote_state_update_t * vote_update, + fd_exec_instr_ctx_t const * ctx /* spad */ ) { // Taken from: // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L954 if( compact_update->root != ULONG_MAX ) { @@ -2099,7 +2110,7 @@ fd_vote_decode_compact_update( fd_compact_vote_state_update_t * compact_update, vote_update->root = ULONG_MAX; } - fd_valloc_t valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); ulong lockouts_len = compact_update->lockouts_len; ulong lockouts_max = fd_ulong_max( lockouts_len, MAX_LOCKOUT_HISTORY ); @@ -2131,21 +2142,23 @@ fd_vote_decode_compact_update( fd_compact_vote_state_update_t * compact_update, void fd_vote_record_timestamp_vote( fd_exec_slot_ctx_t * slot_ctx, fd_pubkey_t const * vote_acc, - long timestamp ) { + long timestamp, + fd_valloc_t valloc ) { fd_vote_record_timestamp_vote_with_slot( - slot_ctx, vote_acc, timestamp, slot_ctx->slot_bank.slot ); + slot_ctx, vote_acc, timestamp, slot_ctx->slot_bank.slot, valloc ); } void fd_vote_record_timestamp_vote_with_slot( fd_exec_slot_ctx_t * slot_ctx, fd_pubkey_t const * vote_acc, long timestamp, - ulong slot ) { + ulong slot, + fd_valloc_t valloc ) { fd_clock_timestamp_vote_t_mapnode_t * root = slot_ctx->slot_bank.timestamp_votes.votes_root; fd_clock_timestamp_vote_t_mapnode_t * pool = slot_ctx->slot_bank.timestamp_votes.votes_pool; if( NULL == pool ) pool = slot_ctx->slot_bank.timestamp_votes.votes_pool = - fd_clock_timestamp_vote_t_map_alloc( slot_ctx->valloc, 15000 ); + fd_clock_timestamp_vote_t_map_alloc( valloc, 15000 ); fd_clock_timestamp_vote_t timestamp_vote = { .pubkey = *vote_acc, @@ -2174,7 +2187,7 @@ fd_vote_acc_credits( fd_exec_instr_ctx_t const * ctx, ulong * result ) { int rc; - fd_valloc_t scratch_valloc = fd_scratch_virtual(); + fd_valloc_t valloc = fd_spad_virtual( ctx->txn_ctx->spad ); fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache ); if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR; @@ -2188,9 +2201,9 @@ fd_vote_acc_credits( fd_exec_instr_ctx_t const * ctx, rc = 0; fd_vote_state_versioned_t vote_state_versioned; - rc = get_state( &vote_account, scratch_valloc, &vote_state_versioned ); + rc = get_state( &vote_account, valloc, &vote_state_versioned ); if( FD_UNLIKELY( rc ) ) return rc; - convert_to_current( &vote_state_versioned, scratch_valloc ); + convert_to_current( &vote_state_versioned, valloc ); fd_vote_state_t * state = &vote_state_versioned.inner.current; if( deq_fd_vote_epoch_credits_t_empty( state->epoch_credits ) ) { *result = 0; @@ -2391,7 +2404,7 @@ fd_vote_program_execute( fd_exec_instr_ctx_t * ctx ) { fd_bincode_decode_ctx_t decode = { .data = ctx->instr->data, .dataend = ctx->instr->data + ctx->instr->data_sz, - .valloc = fd_scratch_virtual() + .valloc = fd_spad_virtual( ctx->txn_ctx->spad ) }; int decode_result = fd_vote_instruction_decode( &instruction, &decode ); if( decode_result != FD_BINCODE_SUCCESS || @@ -2705,7 +2718,7 @@ fd_vote_program_execute( fd_exec_instr_ctx_t * ctx ) { fd_vote_state_update_t vote_update; fd_vote_state_update_new( &vote_update ); - if( FD_UNLIKELY( !fd_vote_decode_compact_update( vote_state_update, &vote_update ) ) ) + if( FD_UNLIKELY( !fd_vote_decode_compact_update( vote_state_update, &vote_update, ctx ) ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA; // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L185 @@ -2863,16 +2876,18 @@ remove_vote_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote } static void -upsert_vote_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote_account ) { - FD_SCRATCH_SCOPE_BEGIN { +upsert_vote_account( fd_exec_slot_ctx_t * slot_ctx, + fd_borrowed_account_t * vote_account, + fd_spad_t * spad ) { + FD_SPAD_FRAME_BEGIN( spad ) { fd_bincode_decode_ctx_t decode = { .data = vote_account->const_data, .dataend = vote_account->const_data + vote_account->const_meta->dlen, - .valloc = slot_ctx->valloc, + .valloc = fd_spad_virtual( spad ), }; fd_bincode_destroy_ctx_t destroy = { - .valloc = slot_ctx->valloc, + .valloc = fd_spad_virtual( spad ), }; fd_vote_state_versioned_t vote_state[1] = {0}; if( FD_UNLIKELY( 0!=fd_vote_state_versioned_decode( vote_state, &decode ) ) ) { @@ -2948,11 +2963,13 @@ upsert_vote_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote } fd_vote_state_versioned_destroy( vote_state, &destroy ); - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } void -fd_vote_store_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote_account ) { +fd_vote_store_account( fd_exec_slot_ctx_t * slot_ctx, + fd_borrowed_account_t * vote_account, + fd_spad_t * spad ) { fd_pubkey_t const * owner = (fd_pubkey_t const *)vote_account->const_meta->info.owner; if (memcmp(owner->uc, fd_solana_vote_program_id.key, sizeof(fd_pubkey_t)) != 0) { @@ -2961,6 +2978,6 @@ fd_vote_store_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vo if (vote_account->const_meta->info.lamports == 0) { remove_vote_account( slot_ctx, vote_account ); } else { - upsert_vote_account( slot_ctx, vote_account ); + upsert_vote_account( slot_ctx, vote_account, spad ); } } diff --git a/src/flamenco/runtime/program/fd_vote_program.h b/src/flamenco/runtime/program/fd_vote_program.h index 219e8765ee..decae8ed82 100644 --- a/src/flamenco/runtime/program/fd_vote_program.h +++ b/src/flamenco/runtime/program/fd_vote_program.h @@ -64,7 +64,8 @@ void fd_vote_record_timestamp_vote_with_slot( fd_exec_slot_ctx_t * slot_ctx, fd_pubkey_t const * vote_acc, long timestamp, - ulong slot ); + ulong slot, + fd_valloc_t valloc ); struct fd_commission_split { ulong voter_portion; @@ -80,7 +81,8 @@ fd_vote_commission_split( fd_vote_state_versioned_t * vote_state_versioned, void fd_vote_store_account( fd_exec_slot_ctx_t * slot_ctx, - fd_borrowed_account_t * vote_account ); + fd_borrowed_account_t * vote_account, + fd_spad_t * spad ); FD_PROTOTYPES_END diff --git a/src/flamenco/runtime/tests/fd_exec_instr_test.c b/src/flamenco/runtime/tests/fd_exec_instr_test.c index f305fbb9ec..3758aca12d 100644 --- a/src/flamenco/runtime/tests/fd_exec_instr_test.c +++ b/src/flamenco/runtime/tests/fd_exec_instr_test.c @@ -101,7 +101,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; } @@ -110,10 +111,22 @@ 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; + if( FD_UNLIKELY( fd_spad_verify( runner->spad ) ) ) { + FD_LOG_ERR(( "fd_spad_verify() failed" )); + } + fd_spad_pop( runner->spad ); + if( FD_UNLIKELY( fd_spad_frame_used( runner->spad )!=0 ) ) { + FD_LOG_ERR(( "stray spad frame frame_used=%lu", fd_spad_frame_used( runner->spad ) )); + } 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 ); @@ -518,7 +531,6 @@ fd_exec_test_instr_context_create( fd_exec_instr_test_runner_t * runner, ctx->epoch_ctx = epoch_ctx; ctx->funk_txn = funk_txn; ctx->acc_mgr = acc_mgr; - ctx->valloc = fd_scratch_virtual(); ctx->instr = info; fd_log_collector_init( &ctx->txn_ctx->log_collector, 1 ); @@ -1657,6 +1669,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 ); if (is_cpi) { ctx->txn_ctx->instr_info_cnt = 1; @@ -1707,8 +1720,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 = fd_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 = fd_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 fb539ee004..db3fa51cf5 100644 --- a/src/flamenco/runtime/tests/fd_exec_sol_compat.c +++ b/src/flamenco/runtime/tests/fd_exec_sol_compat.c @@ -65,7 +65,7 @@ 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 */ + 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 d2a53235c1..4e8f9548d6 100644 --- a/src/flamenco/runtime/tests/fd_vm_test.c +++ b/src/flamenco/runtime/tests/fd_vm_test.c @@ -73,6 +73,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; @@ -96,8 +97,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 = fd_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 = fd_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; @@ -310,7 +311,7 @@ uint fd_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 272fb5dd6f..bf311e34ed 100644 --- a/src/flamenco/runtime/tests/fd_vm_test.h +++ b/src/flamenco/runtime/tests/fd_vm_test.h @@ -40,7 +40,7 @@ uint fd_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 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 diff --git a/src/flamenco/vm/syscall/test_vm_syscall_curve.c b/src/flamenco/vm/syscall/test_vm_syscall_curve.c index 3d73846899..1142c2dbf1 100644 --- a/src/flamenco/vm/syscall/test_vm_syscall_curve.c +++ b/src/flamenco/vm/syscall/test_vm_syscall_curve.c @@ -385,7 +385,7 @@ main( int argc, fd_vm_delete ( fd_vm_leave ( vm ) ); fd_sha256_delete( fd_sha256_leave( sha ) ); fd_rng_delete ( fd_rng_leave ( rng ) ); - test_vm_exec_instr_ctx_delete( instr_ctx ); + test_vm_exec_instr_ctx_delete( instr_ctx, fd_libc_alloc_virtual() ); FD_LOG_NOTICE(( "pass" )); fd_halt(); diff --git a/src/flamenco/vm/syscall/test_vm_syscalls.c b/src/flamenco/vm/syscall/test_vm_syscalls.c index 24a059e299..4ea042de7e 100644 --- a/src/flamenco/vm/syscall/test_vm_syscalls.c +++ b/src/flamenco/vm/syscall/test_vm_syscalls.c @@ -752,7 +752,7 @@ main( int argc, fd_vm_delete ( fd_vm_leave ( vm ) ); fd_sha256_delete( fd_sha256_leave( sha ) ); fd_rng_delete ( fd_rng_leave ( rng ) ); - test_vm_exec_instr_ctx_delete( instr_ctx ); + test_vm_exec_instr_ctx_delete( instr_ctx, fd_libc_alloc_virtual() ); FD_LOG_NOTICE(( "pass" )); fd_halt(); diff --git a/src/flamenco/vm/test_vm_instr.c b/src/flamenco/vm/test_vm_instr.c index a10865588c..2db0affa4f 100644 --- a/src/flamenco/vm/test_vm_instr.c +++ b/src/flamenco/vm/test_vm_instr.c @@ -476,7 +476,7 @@ run_input( test_input_t const * input, run_input2( out, vm, force_exec ); /* Clean up */ - test_vm_exec_instr_ctx_delete( instr_ctx ); + test_vm_exec_instr_ctx_delete( instr_ctx, fd_libc_alloc_virtual() ); free( fd_sbpf_syscalls_delete ( fd_sbpf_syscalls_leave ( syscalls ) ) ); free( fd_sbpf_calldests_delete( fd_sbpf_calldests_leave( calldests ) ) ); free( input_copy ); diff --git a/src/flamenco/vm/test_vm_interp.c b/src/flamenco/vm/test_vm_interp.c index 08afe8183d..a65fd727b2 100644 --- a/src/flamenco/vm/test_vm_interp.c +++ b/src/flamenco/vm/test_vm_interp.c @@ -286,7 +286,7 @@ test_0cu_exit( void ) { FD_TEST( fd_vm_exec ( vm )==FD_VM_ERR_SIGCOST ); fd_vm_delete( fd_vm_leave( vm ) ); - test_vm_exec_instr_ctx_delete( instr_ctx ); + test_vm_exec_instr_ctx_delete( instr_ctx, fd_libc_alloc_virtual() ); fd_sha256_delete( fd_sha256_leave( sha ) ); } @@ -1010,7 +1010,7 @@ main( int argc, free( text ); fd_sbpf_syscalls_delete( fd_sbpf_syscalls_leave( syscalls ) ); - test_vm_exec_instr_ctx_delete( instr_ctx ); + test_vm_exec_instr_ctx_delete( instr_ctx, fd_libc_alloc_virtual() ); test_static_syscalls_list(); diff --git a/src/flamenco/vm/test_vm_util.c b/src/flamenco/vm/test_vm_util.c index 64c1400ba1..4c64e6a1cc 100644 --- a/src/flamenco/vm/test_vm_util.c +++ b/src/flamenco/vm/test_vm_util.c @@ -17,8 +17,6 @@ test_vm_minimal_exec_instr_ctx( return NULL; } - ctx->valloc = valloc; - /* Keep slot_ctx and epoch_ctx initialization simple. We only want features ATM. Feel free to change this to use actual init semantics (*_new and *_join), but remember to update the cleanup function below :) */ @@ -46,9 +44,10 @@ test_vm_minimal_exec_instr_ctx( void test_vm_exec_instr_ctx_delete( - fd_exec_instr_ctx_t * ctx ) { + fd_exec_instr_ctx_t * ctx, + fd_valloc_t valloc +) { - fd_valloc_t valloc = ctx->valloc; fd_exec_slot_ctx_t * slot_ctx = (fd_exec_slot_ctx_t *)ctx->slot_ctx; fd_exec_epoch_ctx_t * epoch_ctx = slot_ctx->epoch_ctx; fd_exec_txn_ctx_t * txn_ctx = ctx->txn_ctx; diff --git a/src/flamenco/vm/test_vm_util.h b/src/flamenco/vm/test_vm_util.h index 5df1bf04b0..10ccacc463 100644 --- a/src/flamenco/vm/test_vm_util.h +++ b/src/flamenco/vm/test_vm_util.h @@ -16,7 +16,8 @@ test_vm_minimal_exec_instr_ctx( void test_vm_exec_instr_ctx_delete( - fd_exec_instr_ctx_t * ctx + fd_exec_instr_ctx_t * ctx, + fd_valloc_t valloc ); #endif diff --git a/src/util/spad/fd_spad.c b/src/util/spad/fd_spad.c index d681c57041..e338c710be 100644 --- a/src/util/spad/fd_spad.c +++ b/src/util/spad/fd_spad.c @@ -110,3 +110,28 @@ fd_spad_publish_debug( fd_spad_t * spad, tracking that state */ fd_spad_publish( spad, sz ); } + +/* fd_valloc virtual function table for spad */ +void * +fd_spad_valloc_malloc( void * _self, + ulong align, + ulong sz ) { + fd_spad_t * spad = _self; + void * rv = fd_spad_alloc( spad, align, sz ); + if( FD_UNLIKELY( fd_spad_mem_used( spad )>fd_spad_mem_max( spad ) ) ) { + FD_LOG_ERR(( "spad overflow mem_used=%lu mem_max=%lu", fd_spad_mem_used( spad ), fd_spad_mem_max( spad ) )); + } + return rv; +} + +void +fd_spad_valloc_free( void * _self, + void * _addr ) { + (void)_self; (void)_addr; +} + +const fd_valloc_vtable_t +fd_spad_vtable = { + .malloc = fd_spad_valloc_malloc, + .free = fd_spad_valloc_free +}; diff --git a/src/util/spad/fd_spad.h b/src/util/spad/fd_spad.h index 41801e479e..2d233df7d1 100644 --- a/src/util/spad/fd_spad.h +++ b/src/util/spad/fd_spad.h @@ -29,6 +29,7 @@ sanitization. */ #include "../bits/fd_bits.h" +#include "../valloc/fd_valloc.h" // For valloc wrapper interface /* FD_SPAD_{ALIGN,FOOTPRINT} give the alignment and footprint of a fd_spad_t. ALIGN is an integer power of 2. FOOTPRINT is a multiple @@ -530,6 +531,18 @@ fd_spad_private_frame_end_debug( fd_spad_t ** _spad ) { #define FD_SPAD_FRAME_END_DEBUG while(0); } while(0) +/* fd_valloc virtual function table for spad */ +extern const fd_valloc_vtable_t fd_spad_vtable; + +/* Returns an fd_valloc handle to the fd_spad join. + Valid for lifetime of the current spad frame. Handle invalid if spad + frame changes or spad detaches. */ +FD_FN_PURE static inline fd_valloc_t +fd_spad_virtual( fd_spad_t * spad ) { + fd_valloc_t valloc = { spad, &fd_spad_vtable }; + return valloc; +} + FD_PROTOTYPES_END #endif /* HEADER_fd_src_util_spad_fd_spad_h */