diff --git a/book/api/metrics-generated.md b/book/api/metrics-generated.md index b516be8d41d..8fd80624296 100644 --- a/book/api/metrics-generated.md +++ b/book/api/metrics-generated.md @@ -1045,6 +1045,10 @@ | bankf_​transaction_​result
{transaction_​result="insufficient_​funds_​for_​rent"} | counter | Result of loading and executing a transaction. (The transaction would leave an account with a lower balance than the rent-exempt minimum) | | bankf_​transaction_​result
{transaction_​result="unbalanced_​transaction"} | counter | Result of loading and executing a transaction. (The total referenced account lamports before and after the transaction was unbalanced) | | bankf_​transaction_​result
{transaction_​result="bundle_​peer"} | counter | Result of loading and executing a transaction. (The transaction was part of a bundle and an earlier transaction in the bundle failed) | +| bankf_​transaction_​landed
{transaction_​landed="landed_​success"} | counter | Whether a transaction landed in the block or not. (Transaction landed) | +| bankf_​transaction_​landed
{transaction_​landed="landed_​fees_​only"} | counter | Whether a transaction landed in the block or not. (Transaction landed, but was fees only and did not execute) | +| bankf_​transaction_​landed
{transaction_​landed="landed_​failed"} | counter | Whether a transaction landed in the block or not. (Transaction landed, but failed to execute) | +| bankf_​transaction_​landed
{transaction_​landed="unlanded"} | counter | Whether a transaction landed in the block or not. (Transaction did not land) | diff --git a/src/disco/gui/fd_gui.c b/src/disco/gui/fd_gui.c index 7ffefad3c2b..22050dedea6 100644 --- a/src/disco/gui/fd_gui.c +++ b/src/disco/gui/fd_gui.c @@ -434,32 +434,11 @@ fd_gui_txn_waterfall_snap( fd_gui_t * gui, cur->out.bank_invalid += bank_metrics[ MIDX( COUNTER, BANK, PROCESSING_FAILED ) ]; } else { - cur->out.block_success += bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_SUCCESS ) ]; - cur->out.block_fail += - bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INSTRUCTON_ERROR ) ]; - - cur->out.bank_invalid += - bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_ACCOUNT_NOT_FOUND ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_PROGRAM_ACCOUNT_NOT_FOUND ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INSUFFICIENT_FUNDS_FOR_FEE ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INVALID_ACCOUNT_FOR_FEE ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_ALREADY_PROCESSED ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_BLOCKHASH_NOT_FOUND ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INVALID_PROGRAM_FOR_EXECUTION ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_ADDRESS_LOOKUP_TABLE_NOT_FOUND ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INVALID_ADDRESS_LOOKUP_TABLE_OWNER ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INVALID_ADDRESS_LOOKUP_TABLE_DATA ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INVALID_ADDRESS_LOOKUP_TABLE_INDEX ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_MAX_LOADED_ACCOUNTS_DATA_SIZE_EXCEEDED ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_DUPLICATE_INSTRUCTION ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INVALID_LOADED_ACCOUNTS_DATA_SIZE_LIMIT ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_ACCOUNT_IN_USE ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_ACCOUNT_LOADED_TWICE ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_SIGNATURE_FAILURE ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_TOO_MANY_ACCOUNT_LOCKS ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_BUNDLE_PEER ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_INSUFFICIENT_FUNDS_FOR_RENT ) ] - + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_UNBALANCED_TRANSACTION ) ]; + cur->out.block_success += bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_LANDED_LANDED_SUCCESS ) ]; + cur->out.block_fail += + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_LANDED_LANDED_FEES_ONLY ) ] + + bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_LANDED_LANDED_FAILED ) ]; + cur->out.bank_invalid += bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_LANDED_UNLANDED ) ]; cur->out.bank_nonce_already_advanced = bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_NONCE_ALREADY_ADVANCED ) ]; cur->out.bank_nonce_advance_failed = bank_metrics[ MIDX( COUNTER, BANKF, TRANSACTION_RESULT_NONCE_ADVANCE_FAILED ) ]; diff --git a/src/disco/metrics/generated/fd_metrics_bankf.c b/src/disco/metrics/generated/fd_metrics_bankf.c index 11098cd4c80..a33f70282a0 100644 --- a/src/disco/metrics/generated/fd_metrics_bankf.c +++ b/src/disco/metrics/generated/fd_metrics_bankf.c @@ -28,4 +28,8 @@ const fd_metrics_meta_t FD_METRICS_BANKF[FD_METRICS_BANKF_TOTAL] = { DECLARE_METRIC_ENUM( BANKF_TRANSACTION_RESULT, COUNTER, TRANSACTION_RESULT, INSUFFICIENT_FUNDS_FOR_RENT ), DECLARE_METRIC_ENUM( BANKF_TRANSACTION_RESULT, COUNTER, TRANSACTION_RESULT, UNBALANCED_TRANSACTION ), DECLARE_METRIC_ENUM( BANKF_TRANSACTION_RESULT, COUNTER, TRANSACTION_RESULT, BUNDLE_PEER ), + DECLARE_METRIC_ENUM( BANKF_TRANSACTION_LANDED, COUNTER, TRANSACTION_LANDED, LANDED_SUCCESS ), + DECLARE_METRIC_ENUM( BANKF_TRANSACTION_LANDED, COUNTER, TRANSACTION_LANDED, LANDED_FEES_ONLY ), + DECLARE_METRIC_ENUM( BANKF_TRANSACTION_LANDED, COUNTER, TRANSACTION_LANDED, LANDED_FAILED ), + DECLARE_METRIC_ENUM( BANKF_TRANSACTION_LANDED, COUNTER, TRANSACTION_LANDED, UNLANDED ), }; diff --git a/src/disco/metrics/generated/fd_metrics_bankf.h b/src/disco/metrics/generated/fd_metrics_bankf.h index 2d71a51052f..a245ed8d904 100644 --- a/src/disco/metrics/generated/fd_metrics_bankf.h +++ b/src/disco/metrics/generated/fd_metrics_bankf.h @@ -40,7 +40,19 @@ #define FD_METRICS_COUNTER_BANKF_TRANSACTION_RESULT_UNBALANCED_TRANSACTION_OFF (40UL) #define FD_METRICS_COUNTER_BANKF_TRANSACTION_RESULT_BUNDLE_PEER_OFF (41UL) -#define FD_METRICS_BANKF_TOTAL (26UL) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_OFF (42UL) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_NAME "bankf_transaction_landed" +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_TYPE (FD_METRICS_TYPE_COUNTER) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_DESC "Whether a transaction landed in the block or not." +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_CVT (FD_METRICS_CONVERTER_NONE) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_CNT (4UL) + +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_LANDED_SUCCESS_OFF (42UL) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_LANDED_FEES_ONLY_OFF (43UL) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_LANDED_FAILED_OFF (44UL) +#define FD_METRICS_COUNTER_BANKF_TRANSACTION_LANDED_UNLANDED_OFF (45UL) + +#define FD_METRICS_BANKF_TOTAL (30UL) extern const fd_metrics_meta_t FD_METRICS_BANKF[FD_METRICS_BANKF_TOTAL]; #endif /* HEADER_fd_src_disco_metrics_generated_fd_metrics_bankf_h */ diff --git a/src/disco/metrics/generated/fd_metrics_enums.h b/src/disco/metrics/generated/fd_metrics_enums.h index 254fce97443..b28c9141379 100644 --- a/src/disco/metrics/generated/fd_metrics_enums.h +++ b/src/disco/metrics/generated/fd_metrics_enums.h @@ -546,6 +546,17 @@ #define FD_METRICS_ENUM_TRANSACTION_RESULT_V_BUNDLE_PEER_IDX 25 #define FD_METRICS_ENUM_TRANSACTION_RESULT_V_BUNDLE_PEER_NAME "bundle_peer" +#define FD_METRICS_ENUM_TRANSACTION_LANDED_NAME "transaction_landed" +#define FD_METRICS_ENUM_TRANSACTION_LANDED_CNT (4UL) +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_SUCCESS_IDX 0 +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_SUCCESS_NAME "landed_success" +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_FEES_ONLY_IDX 1 +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_FEES_ONLY_NAME "landed_fees_only" +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_FAILED_IDX 2 +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_FAILED_NAME "landed_failed" +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_UNLANDED_IDX 3 +#define FD_METRICS_ENUM_TRANSACTION_LANDED_V_UNLANDED_NAME "unlanded" + #define FD_METRICS_ENUM_SHRED_PROCESSING_RESULT_NAME "shred_processing_result" #define FD_METRICS_ENUM_SHRED_PROCESSING_RESULT_CNT (6UL) #define FD_METRICS_ENUM_SHRED_PROCESSING_RESULT_V_BAD_SLOT_IDX 0 diff --git a/src/disco/metrics/metrics.xml b/src/disco/metrics/metrics.xml index f0ce636f779..d47d5b86c05 100644 --- a/src/disco/metrics/metrics.xml +++ b/src/disco/metrics/metrics.xml @@ -681,8 +681,16 @@ metric introduced. + + + + + + + + diff --git a/src/discof/bank/fd_bank_tile.c b/src/discof/bank/fd_bank_tile.c index a1c4b77e751..adf8fbef140 100644 --- a/src/discof/bank/fd_bank_tile.c +++ b/src/discof/bank/fd_bank_tile.c @@ -60,6 +60,7 @@ typedef struct { struct { ulong txn_result[ FD_METRICS_ENUM_TRANSACTION_RESULT_CNT ]; + ulong txn_landed[ FD_METRICS_ENUM_TRANSACTION_LANDED_CNT ]; } metrics; } fd_bank_ctx_t; @@ -83,6 +84,7 @@ scratch_footprint( fd_topo_tile_t const * tile ) { static inline void metrics_write( fd_bank_ctx_t * ctx ) { FD_MCNT_ENUM_COPY( BANKF, TRANSACTION_RESULT, ctx->metrics.txn_result ); + FD_MCNT_ENUM_COPY( BANKF, TRANSACTION_LANDED, ctx->metrics.txn_landed ); } static int @@ -180,32 +182,37 @@ handle_microblock( fd_bank_ctx_t * ctx, txn->flags &= ~FD_TXN_P_FLAGS_SANITIZE_SUCCESS; txn->flags &= ~FD_TXN_P_FLAGS_EXECUTE_SUCCESS; - txn_ctx->exec_err = fd_runtime_prepare_and_execute_txn( ctx->banks, - ctx->_bank_idx, - txn_ctx, - txn, - NULL, - &ctx->exec_stack, - &ctx->exec_accounts[0], - NULL, - NULL ); + fd_bank_t * bank = fd_banks_bank_query( ctx->banks, ctx->_bank_idx ); + FD_TEST( bank ); + txn_ctx->err.exec_err = fd_runtime_prepare_and_execute_txn( bank, + txn_ctx, + txn, + NULL, + &ctx->exec_stack, + &ctx->exec_accounts[0], + NULL, + NULL ); /* Stash the result in the flags value so that pack can inspect it. */ - txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->exec_err)<<24); + txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->err.exec_err)<<24); - if( FD_UNLIKELY( !(txn_ctx->flags & FD_TXN_P_FLAGS_SANITIZE_SUCCESS ) ) ) { + if( FD_UNLIKELY( !txn_ctx->err.is_committable ) ) { + FD_TEST( !txn_ctx->err.is_fees_only ); fd_pack_rebate_sum_add_txn( ctx->rebater, txn, NULL, 1UL ); - ctx->metrics.txn_result[ fd_bank_err_from_runtime_err( txn_ctx->exec_err ) ]++; + ctx->metrics.txn_landed[ FD_METRICS_ENUM_TRANSACTION_LANDED_V_UNLANDED_IDX ]++; + ctx->metrics.txn_result[ fd_bank_err_from_runtime_err( txn_ctx->err.exec_err ) ]++; continue; } + if( FD_UNLIKELY( txn_ctx->err.is_fees_only ) ) ctx->metrics.txn_landed[ FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_FEES_ONLY_IDX ]++; + else if( FD_UNLIKELY( txn_ctx->err.txn_err ) ) ctx->metrics.txn_landed[ FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_FAILED_IDX ]++; + else ctx->metrics.txn_landed[ FD_METRICS_ENUM_TRANSACTION_LANDED_V_LANDED_SUCCESS_IDX ]++; + /* TXN_P_FLAGS_EXECUTE_SUCCESS means that it should be included in the block. It's a bit of a misnomer now that there are fee-only transactions. */ - FD_TEST( txn_ctx->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS ); txn->flags |= FD_TXN_P_FLAGS_EXECUTE_SUCCESS | FD_TXN_P_FLAGS_SANITIZE_SUCCESS; - - ctx->metrics.txn_result[ fd_bank_err_from_runtime_err( txn_ctx->exec_err ) ]++; + ctx->metrics.txn_result[ fd_bank_err_from_runtime_err( txn_ctx->err.exec_err ) ]++; /* Commit must succeed so no failure path. Once commit is called, the transactions MUST be mixed into the PoH otherwise we will @@ -221,10 +228,10 @@ handle_microblock( fd_bank_ctx_t * ctx, in finalize anyway. */ fd_runtime_finalize_txn( ctx->txn_ctx->funk, ctx->txn_ctx->progcache, txn_ctx->status_cache, txn_ctx->xid, txn_ctx, bank, NULL, &tips ); - if( FD_UNLIKELY( !txn_ctx->flags ) ) { + if( FD_UNLIKELY( !txn_ctx->err.is_committable ) ) { /* If the transaction failed to fit into the block, we need to updated the transaction flag with the error code. */ - txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->exec_err)<<24); + txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->err.exec_err)<<24); fd_cost_tracker_t * cost_tracker = fd_bank_cost_tracker_locking_modify( bank ); uchar * signature = (uchar *)txn_ctx->txn.payload + TXN( &txn_ctx->txn )->signature_off; int res = fd_cost_tracker_calculate_cost_and_add( cost_tracker, txn_ctx ); @@ -238,8 +245,8 @@ handle_microblock( fd_bank_ctx_t * ctx, cost_tracker->account_cost_limit )); } - uint actual_execution_cus = (uint)(txn_ctx->compute_budget_details.compute_unit_limit - txn_ctx->compute_budget_details.compute_meter); - uint actual_acct_data_cus = (uint)(txn_ctx->loaded_accounts_data_size_cost); + uint actual_execution_cus = (uint)(txn_ctx->details.compute_budget.compute_unit_limit - txn_ctx->details.compute_budget.compute_meter); + uint actual_acct_data_cus = (uint)(txn_ctx->details.loaded_accounts_data_size_cost); int is_simple_vote = 0; if( FD_UNLIKELY( is_simple_vote = fd_txn_is_simple_vote_transaction( TXN(txn), txn->payload ) ) ) { @@ -261,7 +268,7 @@ handle_microblock( fd_bank_ctx_t * ctx, that first the non-alt accounts are laid out, then the writable alt accounts, and finally the read-only alt accounts. */ fd_txn_t * txn_descriptor = TXN( &txn_ctx->txn ); - fd_acct_addr_t const * writable_alt = fd_type_pun_const( txn_ctx->account_keys+txn_descriptor->acct_addr_cnt ); + fd_acct_addr_t const * writable_alt = fd_type_pun_const( txn_ctx->accounts.account_keys+txn_descriptor->acct_addr_cnt ); fd_pack_rebate_sum_add_txn( ctx->rebater, txn, &writable_alt, 1UL ); /* The VM will stop executing and fail an instruction immediately if @@ -273,7 +280,7 @@ handle_microblock( fd_bank_ctx_t * ctx, FD_LOG_ERR(( "Actual CUs unexpectedly exceeded requested amount. actual_execution_cus (%u) actual_acct_data_cus " "(%u) requested_exec_plus_acct_data_cus (%u) is_simple_vote (%i) exec_failed (%i)", actual_execution_cus, actual_acct_data_cus, requested_exec_plus_acct_data_cus, is_simple_vote, - txn_ctx->exec_err )); + txn_ctx->err.exec_err )); } } @@ -364,15 +371,17 @@ handle_bundle( fd_bank_ctx_t * ctx, txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-FD_RUNTIME_TXN_ERR_BUNDLE_PEER)<<24); continue; } - - txn_ctx->exec_err = fd_runtime_prepare_and_execute_txn( ctx->banks, ctx->_bank_idx, txn_ctx, txn, NULL, &ctx->exec_stack, &ctx->exec_accounts[ i ], NULL, NULL ); - txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->exec_err)<<24); - if( FD_UNLIKELY( !(txn_ctx->flags & FD_TXN_P_FLAGS_SANITIZE_SUCCESS ) || txn_ctx->exec_err ) ) { + fd_bank_t * bank = fd_banks_bank_query( ctx->banks, ctx->_bank_idx ); + FD_TEST( bank ); + txn_ctx->bundle.is_bundle = 1; + txn_ctx->err.exec_err = fd_runtime_prepare_and_execute_txn( bank, txn_ctx, txn, NULL, &ctx->exec_stack, &ctx->exec_accounts[ i ], NULL, NULL ); + txn->flags = (txn->flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->err.exec_err)<<24); + if( FD_UNLIKELY( !txn_ctx->err.is_committable || txn_ctx->err.exec_err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { execution_success = 0; continue; } - writable_alt[i] = fd_type_pun_const( txn_ctx->account_keys+TXN( &txn_ctx->txn )->acct_addr_cnt ); + writable_alt[i] = fd_type_pun_const( txn_ctx->accounts.account_keys+TXN( &txn_ctx->txn )->acct_addr_cnt ); } /* If all of the transactions in the bundle executed successfully, we @@ -388,8 +397,8 @@ handle_bundle( fd_bank_ctx_t * ctx, txns[ i ].flags |= FD_TXN_P_FLAGS_EXECUTE_SUCCESS | FD_TXN_P_FLAGS_SANITIZE_SUCCESS; fd_runtime_finalize_txn( txn_ctx->funk, txn_ctx->progcache, txn_ctx->status_cache, txn_ctx->xid, txn_ctx, bank, NULL, &tips[ i ] ); - if( FD_UNLIKELY( !txn_ctx->flags ) ) { - txns[ i ].flags = (txns[ i ].flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->exec_err)<<24); + if( FD_UNLIKELY( !txn_ctx->err.is_committable ) ) { + txns[ i ].flags = (txns[ i ].flags & 0x00FFFFFFU) | ((uint)(-txn_ctx->err.exec_err)<<24); fd_cost_tracker_t * cost_tracker = fd_bank_cost_tracker_locking_modify( bank ); int res = fd_cost_tracker_calculate_cost_and_add( cost_tracker, txn_ctx ); FD_LOG_HEXDUMP_WARNING(( "txn", txns[ i ].payload, txns[ i ].payload_sz )); @@ -402,8 +411,8 @@ handle_bundle( fd_bank_ctx_t * ctx, cost_tracker->account_cost_limit )); } - uint actual_execution_cus = (uint)(txn_ctx->compute_budget_details.compute_unit_limit - txn_ctx->compute_budget_details.compute_meter); - uint actual_acct_data_cus = (uint)(txn_ctx->loaded_accounts_data_size_cost); + uint actual_execution_cus = (uint)(txn_ctx->details.compute_budget.compute_unit_limit - txn_ctx->details.compute_budget.compute_meter); + uint actual_acct_data_cus = (uint)(txn_ctx->details.loaded_accounts_data_size_cost); if( FD_UNLIKELY( fd_txn_is_simple_vote_transaction( TXN( &txns[ i ] ), txns[ i ].payload ) ) ) { actual_execution_cus = FD_PACK_VOTE_DEFAULT_COMPUTE_UNITS; actual_acct_data_cus = 0U; diff --git a/src/discof/exec/fd_exec_tile.c b/src/discof/exec/fd_exec_tile.c index 599cee2505e..c21974a6950 100644 --- a/src/discof/exec/fd_exec_tile.c +++ b/src/discof/exec/fd_exec_tile.c @@ -130,19 +130,19 @@ returnable_frag( fd_exec_tile_ctx_t * ctx, case FD_EXEC_TT_TXN_EXEC: { /* Execute. */ fd_exec_txn_exec_msg_t * msg = fd_chunk_to_laddr( ctx->replay_in->mem, chunk ); - ctx->txn_ctx->exec_err = fd_runtime_prepare_and_execute_txn( ctx->banks, - msg->bank_idx, - ctx->txn_ctx, - &msg->txn, - ctx->capture_ctx, - &ctx->exec_stack, - &ctx->exec_accounts, - ctx->dumping_mem, - &ctx->tracing_mem[0][0] ); + fd_bank_t * bank = fd_banks_bank_query( ctx->banks, msg->bank_idx ); + FD_TEST( bank ); + ctx->txn_ctx->err.exec_err = fd_runtime_prepare_and_execute_txn( bank, + ctx->txn_ctx, + &msg->txn, + ctx->capture_ctx, + &ctx->exec_stack, + &ctx->exec_accounts, + ctx->dumping_mem, + &ctx->tracing_mem[0][0] ); /* Commit. */ - fd_bank_t * bank = fd_banks_bank_query( ctx->banks, msg->bank_idx ); - if( FD_LIKELY( ctx->txn_ctx->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS ) ) { + if( FD_LIKELY( ctx->txn_ctx->err.is_committable ) ) { fd_funk_txn_xid_t xid = (fd_funk_txn_xid_t){ .ul = { fd_bank_slot_get( bank ), bank->idx } }; fd_runtime_finalize_txn( ctx->funk, ctx->progcache, ctx->txncache, &xid, ctx->txn_ctx, bank, ctx->capture_ctx, NULL ); } @@ -386,15 +386,15 @@ publish_next_capture_ctx_account_update( fd_exec_tile_ctx_t * ctx, static void publish_txn_finalized_msg( fd_exec_tile_ctx_t * ctx, fd_stem_context_t * stem ) { - fd_exec_task_done_msg_t * msg = fd_chunk_to_laddr( ctx->exec_replay_out->mem, ctx->exec_replay_out->chunk ); - msg->bank_idx = ctx->txn_ctx->bank_idx; - msg->txn_exec->txn_idx = ctx->txn_idx; - msg->txn_exec->err = !(ctx->txn_ctx->flags&FD_TXN_P_FLAGS_EXECUTE_SUCCESS); - msg->txn_exec->slot = ctx->slot; - msg->txn_exec->start_shred_idx = ctx->txn_ctx->txn.start_shred_idx; - msg->txn_exec->end_shred_idx = ctx->txn_ctx->txn.end_shred_idx; + fd_exec_task_done_msg_t * msg = fd_chunk_to_laddr( ctx->exec_replay_out->mem, ctx->exec_replay_out->chunk ); + msg->bank_idx = ctx->txn_ctx->bank->idx; + msg->txn_exec->txn_idx = ctx->txn_idx; + msg->txn_exec->err = !ctx->txn_ctx->err.is_committable; + msg->txn_exec->slot = ctx->slot; + msg->txn_exec->start_shred_idx = ctx->txn_ctx->txn.start_shred_idx; + msg->txn_exec->end_shred_idx = ctx->txn_ctx->txn.end_shred_idx; if( FD_UNLIKELY( msg->txn_exec->err ) ) { - FD_LOG_WARNING(( "txn failed to execute, bad block detected err=%d", ctx->txn_ctx->exec_err )); + FD_LOG_WARNING(( "txn failed to execute, bad block detected err=%d", ctx->txn_ctx->err.txn_err )); } fd_stem_publish( stem, ctx->exec_replay_out->idx, (FD_EXEC_TT_TXN_EXEC<<32)|ctx->tile_idx, ctx->exec_replay_out->chunk, sizeof(*msg), 0UL, ctx->dispatch_time_comp, fd_frag_meta_ts_comp( fd_tickcount() ) ); diff --git a/src/flamenco/features/fd_features.h b/src/flamenco/features/fd_features.h index 9c1cce2da9d..4d23d214181 100644 --- a/src/flamenco/features/fd_features.h +++ b/src/flamenco/features/fd_features.h @@ -17,13 +17,13 @@ /* Convenience macros for checking features */ #define FD_FEATURE_ACTIVE_(_slot, _features, _feature_name) ( _slot >= (_features)-> _feature_name ) -#define FD_FEATURE_JUST_ACTIVATED_(_slot, _features, _feature_name) ( _slot == (_features). _feature_name ) -#define FD_FEATURE_ACTIVE_OFFSET_(_slot, _features, _offset) ( _slot >= (_features).f[_offset>>3] ) -#define FD_FEATURE_JUST_ACTIVATED_OFFSET_(_slot, _features, _offset) ( _slot == (_features).f[_offset>>3] ) +#define FD_FEATURE_JUST_ACTIVATED_(_slot, _features, _feature_name) ( _slot == (_features)-> _feature_name ) +#define FD_FEATURE_ACTIVE_OFFSET_(_slot, _features, _offset) ( _slot >= (_features)->f[_offset>>3] ) +#define FD_FEATURE_JUST_ACTIVATED_OFFSET_(_slot, _features, _offset) ( _slot == (_features)->f[_offset>>3] ) #define FD_FEATURE_SET_ACTIVE(_features, _feature_name, _slot) ( (_features)-> _feature_name = _slot ) #define FD_FEATURE_ACTIVE_OFFSET(_slot, _features, _offset) FD_FEATURE_ACTIVE_OFFSET_( _slot, _features, _offset ) -#define FD_FEATURE_JUST_ACTIVATED_OFFSET(_bank, _offset) FD_FEATURE_JUST_ACTIVATED_OFFSET_( fd_bank_slot_get( _bank ), fd_bank_features_get( _bank ), _offset ) +#define FD_FEATURE_JUST_ACTIVATED_OFFSET(_bank, _offset) FD_FEATURE_JUST_ACTIVATED_OFFSET_( fd_bank_slot_get( _bank ), fd_bank_features_query( _bank ), _offset ) #define FD_FEATURE_ACTIVE(_slot, _features, _feature_name) FD_FEATURE_ACTIVE_( _slot, _features, _feature_name ) #define FD_FEATURE_ACTIVE_BANK(_bank, _feature_name) FD_FEATURE_ACTIVE_( fd_bank_slot_get( _bank ), fd_bank_features_query( _bank ), _feature_name ) diff --git a/src/flamenco/log_collector/fd_log_collector.h b/src/flamenco/log_collector/fd_log_collector.h index 3d26e1b087d..5c657a59b71 100644 --- a/src/flamenco/log_collector/fd_log_collector.h +++ b/src/flamenco/log_collector/fd_log_collector.h @@ -146,7 +146,7 @@ static inline void fd_log_collector_msg( fd_exec_instr_ctx_t * ctx, char const * msg, ulong msg_sz ) { - fd_log_collector_t * log = &ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &ctx->txn_ctx->log.log_collector; if( FD_LIKELY( log->disabled ) ) { return; } @@ -171,7 +171,7 @@ fd_log_collector_msg( fd_exec_instr_ctx_t * ctx, or with the UL literal. va_args behaves weirdly otherwise */ static inline void fd_log_collector_msg_many( fd_exec_instr_ctx_t * ctx, int num_buffers, ... ) { - fd_log_collector_t * log = &ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &ctx->txn_ctx->log.log_collector; if( FD_LIKELY( log->disabled ) ) { return; } @@ -241,7 +241,7 @@ __attribute__ ((format (printf, 2, 3))) static inline void fd_log_collector_printf_dangerous_max_127( fd_exec_instr_ctx_t * ctx, char const * fmt, ... ) { - fd_log_collector_t * log = &ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &ctx->txn_ctx->log.log_collector; if( FD_LIKELY( log->disabled ) ) { return; } @@ -299,7 +299,7 @@ __attribute__ ((format (printf, 2, 3))) static inline void fd_log_collector_printf_dangerous_128_to_2k( fd_exec_instr_ctx_t * ctx, char const * fmt, ... ) { - fd_log_collector_t * log = &ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &ctx->txn_ctx->log.log_collector; if( FD_LIKELY( log->disabled ) ) { return; } @@ -383,15 +383,15 @@ fd_log_collector_printf_inefficient_max_512( fd_exec_instr_ctx_t * ctx, so this function precomputes it and stores it inside the instr_ctx. */ static inline void fd_log_collector_program_invoke( fd_exec_instr_ctx_t * ctx ) { - if( FD_LIKELY( ctx->txn_ctx->log_collector.disabled ) ) { + if( FD_LIKELY( ctx->txn_ctx->log.log_collector.disabled ) ) { return; } - fd_pubkey_t const * program_id_pubkey = &ctx->txn_ctx->account_keys[ ctx->instr->program_id ]; + fd_pubkey_t const * program_id_pubkey = &ctx->txn_ctx->accounts.account_keys[ ctx->instr->program_id ]; /* Cache ctx->program_id_base58 */ fd_base58_encode_32( program_id_pubkey->uc, NULL, ctx->program_id_base58 ); /* Max msg_sz: 22 - 4 + 44 + 10 = 72 < 127 => we can use printf */ - fd_log_collector_printf_dangerous_max_127( ctx, "Program %s invoke [%u]", ctx->program_id_base58, ctx->txn_ctx->instr_stack_sz ); + fd_log_collector_printf_dangerous_max_127( ctx, "Program %s invoke [%u]", ctx->program_id_base58, ctx->txn_ctx->instr.stack_sz ); } /* fd_log_collector_program_log logs: @@ -415,14 +415,14 @@ fd_log_collector_program_log( fd_exec_instr_ctx_t * ctx, char const * msg, ulong TODO: implement based on fd_log_collector_msg_many(). */ static inline void fd_log_collector_program_return( fd_exec_instr_ctx_t * ctx ) { - if( FD_LIKELY( ctx->txn_ctx->log_collector.disabled ) ) { + if( FD_LIKELY( ctx->txn_ctx->log.log_collector.disabled ) ) { return; } /* ctx->txn_ctx->return_data is 1024 bytes max, so its base64 repr is at most (1024+2)/3*4 bytes, plus we use 1 byte for \0. */ - char return_base64[ (sizeof(ctx->txn_ctx->return_data.data)+2)/3*4+1 ]; - ulong sz = fd_base64_encode( return_base64, ctx->txn_ctx->return_data.data, ctx->txn_ctx->return_data.len ); + char return_base64[ (sizeof(ctx->txn_ctx->details.return_data.data)+2)/3*4+1 ]; + ulong sz = fd_base64_encode( return_base64, ctx->txn_ctx->details.return_data.data, ctx->txn_ctx->details.return_data.len ); return_base64[ sz ] = 0; /* Max msg_sz: 21 - 4 + 44 + 1368 = 1429 < 1500 => we can use printf, but have to handle sz */ ulong msg_sz = 17 + strlen(ctx->program_id_base58) + sz; @@ -454,7 +454,7 @@ fd_log_collector_program_success( fd_exec_instr_ctx_t * ctx ) { the result, and therefore can be skipped at this stage. */ static inline void fd_log_collector_program_failure( fd_exec_instr_ctx_t * ctx ) { - if( FD_LIKELY( ctx->txn_ctx->log_collector.disabled ) ) { + if( FD_LIKELY( ctx->txn_ctx->log.log_collector.disabled ) ) { return; } @@ -465,20 +465,20 @@ fd_log_collector_program_failure( fd_exec_instr_ctx_t * ctx ) { char custom_err[33] = { 0 }; const char * err = custom_err; const fd_exec_txn_ctx_t * txn_ctx = ctx->txn_ctx; - if( FD_UNLIKELY( txn_ctx->exec_err_kind==FD_EXECUTOR_ERR_KIND_INSTR && - txn_ctx->exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ) ) { + if( FD_UNLIKELY( txn_ctx->err.exec_err_kind==FD_EXECUTOR_ERR_KIND_INSTR && + txn_ctx->err.exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ) ) { /* Max msg_sz = 32 <= 66 */ - snprintf( custom_err, sizeof(custom_err), "custom program error: 0x%x", txn_ctx->custom_err ); - } else if( txn_ctx->exec_err ) { - switch( txn_ctx->exec_err_kind ) { + snprintf( custom_err, sizeof(custom_err), "custom program error: 0x%x", txn_ctx->err.custom_err ); + } else if( txn_ctx->err.exec_err ) { + switch( txn_ctx->err.exec_err_kind ) { case FD_EXECUTOR_ERR_KIND_SYSCALL: - err = fd_vm_syscall_strerror( txn_ctx->exec_err ); + err = fd_vm_syscall_strerror( txn_ctx->err.exec_err ); break; case FD_EXECUTOR_ERR_KIND_INSTR: - err = fd_executor_instr_strerror( txn_ctx->exec_err ); + err = fd_executor_instr_strerror( txn_ctx->err.exec_err ); break; default: - err = fd_vm_ebpf_strerror( txn_ctx->exec_err ); + err = fd_vm_ebpf_strerror( txn_ctx->err.exec_err ); } } diff --git a/src/flamenco/log_collector/test_log_collector.c b/src/flamenco/log_collector/test_log_collector.c index 0bfc084677e..9ef96d94784 100644 --- a/src/flamenco/log_collector/test_log_collector.c +++ b/src/flamenco/log_collector/test_log_collector.c @@ -14,7 +14,7 @@ void test_log_messages_bytes_limit_agave( void ) { fd_exec_instr_ctx_t ctx[1]; fd_exec_txn_ctx_t txn[1]; ctx->txn_ctx = txn; - fd_log_collector_t * log = &txn->log_collector; + fd_log_collector_t * log = &txn->log.log_collector; fd_log_collector_init( log, 1 ); for( ulong i=0; i<20000; i++ ) { @@ -32,7 +32,7 @@ static void test_log_messages_bytes_limit( void ) { fd_exec_instr_ctx_t ctx[1]; fd_exec_txn_ctx_t txn[1]; ctx->txn_ctx = txn; - fd_log_collector_t * log = &txn->log_collector; + fd_log_collector_t * log = &txn->log.log_collector; fd_log_collector_init( log, 1 ); for( ulong i=0; i<10000; i++ ) { @@ -50,7 +50,7 @@ static void test_log_messages_single_log_limit( void ) { fd_exec_instr_ctx_t ctx[1]; fd_exec_txn_ctx_t txn[1]; ctx->txn_ctx = txn; - fd_log_collector_t * log = &txn->log_collector; + fd_log_collector_t * log = &txn->log.log_collector; char msg10k[ 10000+1 ]; sprintf( msg10k, "%0*d", 10000, 0 ); char msg9999[ 9999+1 ]; sprintf( msg9999, "%0*d", 9999, 0 ); @@ -74,7 +74,7 @@ static void test_log_messages_weird_behavior( void ) { fd_exec_instr_ctx_t ctx[1]; fd_exec_txn_ctx_t txn[1]; ctx->txn_ctx = txn; - fd_log_collector_t * log = &txn->log_collector; + fd_log_collector_t * log = &txn->log.log_collector; char msg9999[ 9999+1 ]; sprintf( msg9999, "%0*d", 9999, 0 ); @@ -95,7 +95,7 @@ static void test_log_messages_equivalences( void ) { fd_exec_instr_ctx_t ctx[1]; fd_exec_txn_ctx_t txn[1]; ctx->txn_ctx = txn; - fd_log_collector_t * log = &txn->log_collector; + fd_log_collector_t * log = &txn->log.log_collector; uchar msg[17] = { 0x67, 0x72, 0xc3, 0xbc, 0x65, 0x7a, 0x69, 0x00, 0x0a, 0xf0, 0x9f, 0x94, 0xa5, 0xf0, 0x9f, 0x92, 0x83 }; diff --git a/src/flamenco/rewards/fd_rewards.c b/src/flamenco/rewards/fd_rewards.c index 74e17916f65..67377e10900 100644 --- a/src/flamenco/rewards/fd_rewards.c +++ b/src/flamenco/rewards/fd_rewards.c @@ -590,7 +590,7 @@ calculate_stake_vote_rewards( fd_bank_t * bank, fd_vote_state_credits_t * realc_credit = !!runtime_stack->stakes.prev_vote_credits_used ? &runtime_stack->stakes.vote_credits[ vote_state_ele->idx ] : NULL; - /* redeem_rewards is actually just responisble for calculating the + /* redeem_rewards is actually just responsible for calculating the vote and stake rewards for each stake account. It does not do rewards redemption: it is a misnomer. */ fd_calculated_stake_rewards_t calculated_stake_rewards[1] = {0}; diff --git a/src/flamenco/runtime/context/fd_exec_instr_ctx.c b/src/flamenco/runtime/context/fd_exec_instr_ctx.c index 55225e14194..b79fc4708de 100644 --- a/src/flamenco/runtime/context/fd_exec_instr_ctx.c +++ b/src/flamenco/runtime/context/fd_exec_instr_ctx.c @@ -7,7 +7,7 @@ fd_exec_instr_ctx_find_idx_of_instr_account( fd_exec_instr_ctx_t const * ctx, fd_pubkey_t const * pubkey ) { for( int i=0; iinstr->acct_cnt; i++ ) { ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction; - if( memcmp( pubkey->uc, ctx->txn_ctx->account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) { + if( memcmp( pubkey->uc, ctx->txn_ctx->accounts.account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) { return i; } } @@ -54,7 +54,7 @@ fd_exec_instr_ctx_try_borrow_account( fd_exec_instr_ctx_t const * ctx, if( FD_UNLIKELY( err ) ) { /* Return a MissingAccount error if the account is not found. https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L603 */ - FD_TXN_ERR_FOR_LOG_INSTR( ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_MISSING_ACC; } @@ -100,7 +100,7 @@ fd_exec_instr_ctx_try_borrow_instr_account_with_key( fd_exec_instr_ctx_t const * fd_borrowed_account_t * account ) { for( ushort i=0; iinstr->acct_cnt; i++ ) { ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction; - if( memcmp( pubkey->uc, ctx->txn_ctx->account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) { + if( memcmp( pubkey->uc, ctx->txn_ctx->accounts.account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) { return fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, account ); } } @@ -147,7 +147,7 @@ fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx, ushort idx_in_txn = ctx->instr->accounts[ j ].index_in_transaction; is_signer |= ( ( !!fd_instr_acc_is_signer_idx( ctx->instr, j, NULL ) ) & - ( 0==memcmp( pubkey->key, ctx->txn_ctx->account_keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) ); + ( 0==memcmp( pubkey->key, ctx->txn_ctx->accounts.account_keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) ); } return is_signer; } diff --git a/src/flamenco/runtime/context/fd_exec_txn_ctx.c b/src/flamenco/runtime/context/fd_exec_txn_ctx.c index cd3623bda62..580d43359d6 100644 --- a/src/flamenco/runtime/context/fd_exec_txn_ctx.c +++ b/src/flamenco/runtime/context/fd_exec_txn_ctx.c @@ -3,6 +3,7 @@ #include "../fd_executor.h" #include "../../vm/fd_vm.h" #include "../fd_system_ids.h" +#include "../fd_bank.h" void * fd_exec_txn_ctx_new( void * mem ) { @@ -19,10 +20,6 @@ fd_exec_txn_ctx_new( void * mem ) { fd_exec_txn_ctx_t * self = (fd_exec_txn_ctx_t *) mem; fd_memset( self, 0, sizeof(fd_exec_txn_ctx_t) ); - FD_COMPILER_MFENCE(); - self->magic = FD_EXEC_TXN_CTX_MAGIC; - FD_COMPILER_MFENCE(); - return mem; } @@ -35,11 +32,6 @@ fd_exec_txn_ctx_join( void * mem ) { fd_exec_txn_ctx_t * ctx = (fd_exec_txn_ctx_t *) mem; - if( FD_UNLIKELY( ctx->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) { - FD_LOG_WARNING(( "bad magic" )); - return NULL; - } - return ctx; } @@ -50,11 +42,6 @@ fd_exec_txn_ctx_leave( fd_exec_txn_ctx_t * ctx) { return NULL; } - if( FD_UNLIKELY( ctx->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) { - FD_LOG_WARNING(( "bad magic" )); - return NULL; - } - return (void *) ctx; } @@ -70,16 +57,6 @@ fd_exec_txn_ctx_delete( void * mem ) { return NULL; } - fd_exec_txn_ctx_t * hdr = (fd_exec_txn_ctx_t *)mem; - if( FD_UNLIKELY( hdr->magic!=FD_EXEC_TXN_CTX_MAGIC ) ) { - FD_LOG_WARNING(( "bad magic" )); - return NULL; - } - - FD_COMPILER_MFENCE(); - FD_VOLATILE( hdr->magic ) = 0UL; - FD_COMPILER_MFENCE(); - return mem; } @@ -88,11 +65,11 @@ fd_exec_txn_ctx_get_account_at_index( fd_exec_txn_ctx_t * ctx, ushort idx, fd_txn_account_t * * account, fd_txn_account_condition_fn_t * condition ) { - if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) { + if( FD_UNLIKELY( idx>=ctx->accounts.accounts_cnt ) ) { return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT; } - fd_txn_account_t * txn_account = &ctx->accounts[idx]; + fd_txn_account_t * txn_account = &ctx->accounts.accounts[idx]; *account = txn_account; if( FD_LIKELY( condition != NULL ) ) { @@ -135,9 +112,9 @@ fd_exec_txn_ctx_get_executable_account( fd_exec_txn_ctx_t * ctx, return FD_ACC_MGR_SUCCESS; } - for( ushort i=0; iexecutable_cnt; i++ ) { - if( memcmp( pubkey->uc, ctx->executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) )==0 ) { - fd_txn_account_t * txn_account = &ctx->executable_accounts[i]; + for( ushort i=0; iaccounts.executable_cnt; i++ ) { + if( memcmp( pubkey->uc, ctx->accounts.executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) )==0 ) { + fd_txn_account_t * txn_account = &ctx->accounts.executable_accounts[i]; *account = txn_account; if( FD_LIKELY( condition != NULL ) ) { @@ -159,56 +136,14 @@ fd_exec_txn_ctx_get_key_of_account_at_index( fd_exec_txn_ctx_t * ctx, fd_pubkey_t const * * key ) { /* Return a NotEnoughAccountKeys error if idx is out of bounds. https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L218 */ - if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) { + if( FD_UNLIKELY( idx>=ctx->accounts.accounts_cnt ) ) { return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS; } - *key = &ctx->account_keys[ idx ]; + *key = &ctx->accounts.account_keys[ idx ]; return FD_EXECUTOR_INSTR_SUCCESS; } -void -fd_exec_txn_ctx_setup_basic( fd_exec_txn_ctx_t * ctx ) { - fd_compute_budget_details_new( &ctx->compute_budget_details ); - - ctx->custom_err = 0U; - ctx->instr_stack_sz = 0; - ctx->accounts_cnt = 0UL; - ctx->executable_cnt = 0UL; - ctx->programs_to_reverify_cnt = 0UL; - - ctx->paid_fees = 0UL; - ctx->loaded_accounts_data_size = 0UL; - ctx->loaded_accounts_data_size_cost = 0UL; - ctx->accounts_resize_delta = 0UL; - - ctx->num_instructions = 0; - memset( ctx->return_data.program_id.key, 0, sizeof(fd_pubkey_t) ); - ctx->return_data.len = 0; - - ctx->failed_instr = NULL; - ctx->instr_err_idx = INT_MAX; - ctx->capture_ctx = NULL; - - ctx->instr_info_cnt = 0UL; - ctx->cpi_instr_info_cnt = 0UL; - ctx->instr_trace_length = 0UL; - - ctx->exec_err = 0; - ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE; - ctx->current_instr_idx = 0; -} - -void -fd_exec_txn_ctx_teardown( fd_exec_txn_ctx_t * ctx ) { - (void)ctx; -} - -void -fd_exec_txn_ctx_reset_return_data( fd_exec_txn_ctx_t * txn_ctx ) { - txn_ctx->return_data.len = 0; -} - /* https://github.com/anza-xyz/agave/blob/v2.1.1/sdk/program/src/message/versions/v0/loaded.rs#L162 */ int fd_txn_account_is_demotion( const int idx, @@ -243,12 +178,12 @@ fd_txn_account_has_bpf_loader_upgradeable( const fd_pubkey_t * account_keys, https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/program/src/message/sanitized.rs#L38-L47 */ int fd_exec_txn_ctx_account_is_writable_idx( fd_exec_txn_ctx_t const * txn_ctx, ushort idx ) { - uint bpf_upgradeable = fd_txn_account_has_bpf_loader_upgradeable( txn_ctx->account_keys, txn_ctx->accounts_cnt ); - return fd_exec_txn_account_is_writable_idx_flat( txn_ctx->slot, + uint bpf_upgradeable = fd_txn_account_has_bpf_loader_upgradeable( txn_ctx->accounts.account_keys, txn_ctx->accounts.accounts_cnt ); + return fd_exec_txn_account_is_writable_idx_flat( fd_bank_slot_get( txn_ctx->bank ), idx, - &txn_ctx->account_keys[idx], + &txn_ctx->accounts.account_keys[idx], TXN( &txn_ctx->txn ), - &txn_ctx->features, + fd_bank_features_query( txn_ctx->bank ), bpf_upgradeable ); } diff --git a/src/flamenco/runtime/context/fd_exec_txn_ctx.h b/src/flamenco/runtime/context/fd_exec_txn_ctx.h index a4db4975f4b..2cc0ad9066f 100644 --- a/src/flamenco/runtime/context/fd_exec_txn_ctx.h +++ b/src/flamenco/runtime/context/fd_exec_txn_ctx.h @@ -40,119 +40,70 @@ typedef struct fd_exec_instr_trace_entry fd_exec_instr_trace_entry_t; #define FD_MAX_INSTRUCTION_STACK_DEPTH (5UL) struct fd_exec_txn_ctx { - ulong magic; /* ==FD_EXEC_TXN_CTX_MAGIC */ - - /* TODO: These are fields borrowed from the slot and epoch ctx. This - could be refactored even further. Currently these fields are not - all valid local joins within the scope of txn execution. */ - - uint flags; - - fd_bank_t * bank; - + /* Input fields: memory, bank, acc db, funk, prog cache, and txn */ + fd_bank_t * bank; + fd_txncache_t * status_cache; + fd_funk_t funk[1]; + fd_funk_txn_xid_t xid[1]; + fd_progcache_t * progcache; + fd_progcache_t _progcache[1]; + fd_txn_p_t txn; fd_exec_stack_t * exec_stack; fd_exec_accounts_t * exec_accounts; + fd_bank_hash_cmp_t * bank_hash_cmp; - /* All pointers starting here are valid local joins in txn execution. */ - fd_features_t features; - fd_txncache_t * status_cache; - int enable_exec_recording; - fd_bank_hash_cmp_t * bank_hash_cmp; - fd_funk_t funk[1]; - fd_progcache_t * progcache; - fd_progcache_t _progcache[1]; - fd_funk_txn_xid_t xid[1]; - ulong slot; - ulong bank_idx; - fd_txn_p_t txn; - - fd_compute_budget_details_t compute_budget_details; /* Compute budget details */ - - /* Fields below here are not guaranteed to be local joins in txn execution. */ - - ulong paid_fees; - ulong loaded_accounts_data_size; /* The actual transaction loaded data size */ - ulong loaded_accounts_data_size_cost; /* The cost of the loaded accounts data size in CUs */ - uint custom_err; /* When a custom error is returned, this is where the numeric value gets stashed */ - uchar instr_stack_sz; /* Current depth of the instruction execution stack. */ - fd_exec_instr_ctx_t instr_stack[FD_MAX_INSTRUCTION_STACK_DEPTH]; /* Instruction execution stack. */ - fd_exec_instr_ctx_t * failed_instr; - int instr_err_idx; /* During sanitization, v0 transactions are allowed to have up to 256 accounts: https://github.com/anza-xyz/agave/blob/838c1952595809a31520ff1603a13f2c9123aa51/sdk/program/src/message/versions/v0/mod.rs#L139 Nonetheless, when Agave prepares a sanitized batch for execution and tries to lock accounts, a lower limit is enforced: https://github.com/anza-xyz/agave/blob/838c1952595809a31520ff1603a13f2c9123aa51/accounts-db/src/account_locks.rs#L118 That is the limit we are going to use here. */ - ulong accounts_cnt; /* Number of account pubkeys accessed by this transaction. */ - fd_pubkey_t account_keys[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of account pubkeys accessed by this transaction. */ - ulong executable_cnt; /* Number of BPF upgradeable loader accounts. */ - fd_txn_account_t executable_accounts[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of BPF upgradeable loader program data accounts */ - fd_txn_account_t accounts[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of borrowed accounts accessed by this transaction. */ - - /* When a program is deployed or upgraded, we must queue it to be - updated in the program cache (if it exists already) so that - the cache entry's ELF / sBPF information can be updated for future - executions. We keep an array of pubkeys for the transaction to - track which programs need to be reverified. The actual queueing - for reverification is done in the transaction finalization step. */ - uchar programs_to_reverify_cnt; - fd_pubkey_t programs_to_reverify[ MAX_TX_ACCOUNT_LOCKS ]; - + struct { + ulong accounts_cnt; /* Number of account pubkeys accessed by this transaction. */ + fd_pubkey_t account_keys[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of account pubkeys accessed by this transaction. */ + fd_txn_account_t accounts[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of borrowed accounts accessed by this transaction. */ + ulong executable_cnt; /* Number of BPF upgradeable loader accounts. */ + fd_txn_account_t executable_accounts[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of BPF upgradeable loader program data accounts */ /* The next three fields describe Agave's "rollback" accounts, which - are copies of the fee payer and (if applicable) nonce account. If the - transaction fails to load, the fee payer is still debited the transaction fee, - and the nonce account is advanced. The fee payer must also be rolled back to it's - state pre-transaction, plus debited any transaction fees. - + are copies of the fee payer and (if applicable) nonce account. If + the transaction fails to load, the fee payer is still debited the + transaction fee, and the nonce account is advanced. The fee payer + must also be rolled back to its state pre-transaction, plus + debited any transaction fees. This is a bit of a misnomer but Agave calls it "rollback". This is the account state that the nonce account should be in when - the txn fails. - It will advance the nonce account, rather than "roll back". - */ - fd_txn_account_t rollback_nonce_account[ 1 ]; - ulong nonce_account_idx_in_txn; /* If the transaction has a nonce account that must be advanced, this would be !=ULONG_MAX. */ - fd_txn_account_t rollback_fee_payer_account[ 1 ]; - - uint num_instructions; /* Counter for number of instructions in txn */ - fd_txn_return_data_t return_data; /* Data returned from `return_data` syscalls */ - ulong accounts_resize_delta; /* Transaction level tracking for account resizing */ - fd_hash_t blake_txn_msg_hash; /* Hash of raw transaction message used by the status cache */ - ulong execution_fee; /* Execution fee paid by the fee payer in the transaction */ - ulong priority_fee; /* Priority fee paid by the fee payer in the transaction */ - - fd_capture_ctx_t * capture_ctx; - - /* The instr_infos for the entire transaction are allocated at the start of - the transaction. However, this must preserve a different counter because - the top level instructions must get set up at once. The instruction - error check on a maximum instruction size can be done on the - instr_info_cnt instead of the instr_trace_length because it is a proxy - for the trace_length: the instr_info_cnt gets incremented faster than - the instr_trace_length because it counts all of the top level instructions - first. */ - fd_instr_info_t instr_infos[FD_MAX_INSTRUCTION_TRACE_LENGTH]; - ulong instr_info_cnt; - - /* These instr infos are statically allocated at the beginning of a transaction - and are only written to / referred to within the VM. It's kept - at the transaction level because syscalls like `GetProcessedSiblingInstruction()` - may refer to instructions processed earlier in the transaction. */ - fd_instr_info_t cpi_instr_infos[FD_MAX_INSTRUCTION_TRACE_LENGTH]; - ulong cpi_instr_info_cnt; - - /* Each instr info within `instr_trace` may refer to an `instr_infos` or `cpi_instr_infos` - entry. */ - fd_exec_instr_trace_entry_t instr_trace[FD_MAX_INSTRUCTION_TRACE_LENGTH]; /* Instruction trace */ - ulong instr_trace_length; /* Number of instructions in the trace */ - - fd_log_collector_t log_collector; /* Log collector instance */ - - /* Execution error and type, to match Agave. */ - int exec_err; - int exec_err_kind; - - /* The current instruction index being executed */ - int current_instr_idx; + the txn fails. It will advance the nonce account, rather than "roll + back". */ + fd_txn_account_t rollback_nonce[ 1 ]; + /* If the transaction has a nonce account that must be advanced, + this would be !=ULONG_MAX. */ + ulong nonce_idx_in_txn; + fd_txn_account_t rollback_fee_payer[ 1 ]; + + } accounts; + + struct { + uchar stack_sz; /* Current depth of the instruction execution stack. */ + fd_exec_instr_ctx_t stack[FD_MAX_INSTRUCTION_STACK_DEPTH]; /* Instruction execution stack. */ + /* The memory for all of the instructions in the transaction + (including CPI instructions) are preallocated. However, the order + in which the instructions are executed does not match the order in + which they are allocated. The instr_trace will instead be used to + track the order in which the instructions are executed. We leave + space for an extra instruction to account for the case where the + transaction has too many instructions leading to + FD_EXECUTOR_INSTR_ERR_MAX_INSN_TRACE_LENS_EXCEEDED. + TODO: In reality, we should just be allocating instr_infos per + instruction and not up front. The dependency on using instr_info + for the sysvar instruction setup is not needed and should be + removed. At this point, instr_info snad instr_trace should be + combined. */ + fd_instr_info_t infos[FD_MAX_INSTRUCTION_TRACE_LENGTH * 2UL]; + ulong info_cnt; + fd_exec_instr_trace_entry_t trace[FD_MAX_INSTRUCTION_TRACE_LENGTH]; /* Instruction trace */ + ulong trace_length; /* Number of instructions in the trace */ + /* The current instruction index being executed */ + int current_idx; + } instr; struct { int is_bundle; @@ -160,21 +111,54 @@ struct fd_exec_txn_ctx { ulong prev_txn_ctxs_cnt; } bundle; - /* debugging options */ + struct { + int is_committable; + int is_fees_only; + int txn_err; + /* These are error fields produced by instruction execution + when txn_err == FD_RUNTIME_TXN_ERR_INSTRUCTION_ERROR (-9). */ + int exec_err; + int exec_err_kind; + int exec_err_idx; + uint custom_err; + } err; - /* Pointer to buffer used for dumping instructions and transactions - into protobuf files. */ - uchar * dumping_mem; + struct { + fd_compute_budget_details_t compute_budget; /* Compute budget details */ + ulong loaded_accounts_data_size; /* The actual transaction loaded data size */ + ulong loaded_accounts_data_size_cost; /* The cost of the loaded accounts data size in CUs */ + ulong accounts_resize_delta; /* Transaction level tracking for account resizing */ + fd_txn_return_data_t return_data; /* Data returned from `return_data` syscalls */ + fd_hash_t blake_txn_msg_hash; /* Hash of raw transaction message used by the status cache */ + ulong execution_fee; /* Execution fee paid by the fee payer in the transaction */ + ulong priority_fee; /* Priority fee paid by the fee payer in the transaction */ + /* When a program is deployed or upgraded, we must queue it to be + updated in the program cache (if it exists already) so that + the cache entry's ELF / sBPF information can be updated for + future executions. We keep an array of pubkeys for the + transaction to track which programs need to be reverified. The + actual queueing for reverification is done in the transaction + finalization step. */ + uchar programs_to_reverify_cnt; + fd_pubkey_t programs_to_reverify[ MAX_TX_ACCOUNT_LOCKS ]; + } details; - /* Pointer to buffer used for tracing instructions and transactions - into protobuf files. */ - int enable_vm_tracing; - uchar * tracing_mem; + struct { + int enable_exec_recording; + fd_log_collector_t log_collector; /* Log collector instance */ + fd_capture_ctx_t * capture_ctx; + /* Pointer to buffer used for dumping instructions and transactions + into protobuf files. */ + uchar * dumping_mem; + /* Pointer to buffer used for tracing instructions and transactions + into protobuf files. */ + int enable_vm_tracing; + uchar * tracing_mem; + } log; }; #define FD_EXEC_TXN_CTX_ALIGN (alignof(fd_exec_txn_ctx_t)) #define FD_EXEC_TXN_CTX_FOOTPRINT ( sizeof(fd_exec_txn_ctx_t)) -#define FD_EXEC_TXN_CTX_MAGIC (0x9AD93EE71469F4D7UL ) /* random */ FD_PROTOTYPES_BEGIN @@ -184,15 +168,15 @@ FD_PROTOTYPES_BEGIN /* Asserts that the error and error kind are not populated (zero) */ #define FD_TXN_TEST_ERR_OVERWRITE( txn_ctx ) \ - FD_TEST( !txn_ctx->exec_err ); \ - FD_TEST( !txn_ctx->exec_err_kind ) + FD_TEST( !txn_ctx->err.exec_err ); \ + FD_TEST( !txn_ctx->err.exec_err_kind ) /* Used prior to a FD_TXN_ERR_FOR_LOG_INSTR call to deliberately bypass overwrite handholding checks. Only use this if you know what you're doing. */ #define FD_TXN_PREPARE_ERR_OVERWRITE( txn_ctx ) \ - txn_ctx->exec_err = 0; \ - txn_ctx->exec_err_kind = 0 + txn_ctx->err.exec_err = 0; \ + txn_ctx->err.exec_err_kind = 0 #else @@ -201,11 +185,11 @@ FD_PROTOTYPES_BEGIN #endif -#define FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, err, idx ) (__extension__({ \ - FD_TXN_TEST_ERR_OVERWRITE( txn_ctx ); \ - txn_ctx->exec_err = err; \ - txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_INSTR; \ - txn_ctx->instr_err_idx = idx; \ +#define FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, err_, idx ) (__extension__({ \ + FD_TXN_TEST_ERR_OVERWRITE( txn_ctx ); \ + txn_ctx->err.exec_err = err_; \ + txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_INSTR; \ + txn_ctx->err.exec_err_idx = idx; \ })) void * @@ -220,14 +204,6 @@ fd_exec_txn_ctx_leave( fd_exec_txn_ctx_t * ctx ); void * fd_exec_txn_ctx_delete( void * mem ); -/* Sets up a basic transaction ctx without a txn descriptor or txn raw. Useful - for mocking transaction context objects for instructions. */ -void -fd_exec_txn_ctx_setup_basic( fd_exec_txn_ctx_t * ctx ); - -void -fd_exec_txn_ctx_teardown( fd_exec_txn_ctx_t * txn_ctx ); - /* Mirrors Agave function solana_sdk::transaction_context::find_index_of_account Backward scan over transaction accounts. @@ -238,8 +214,8 @@ fd_exec_txn_ctx_teardown( fd_exec_txn_ctx_t * txn_ctx ); static inline int fd_exec_txn_ctx_find_index_of_account( fd_exec_txn_ctx_t const * ctx, fd_pubkey_t const * pubkey ) { - for( ulong i=ctx->accounts_cnt; i>0UL; i-- ) { - if( 0==memcmp( pubkey, &ctx->account_keys[ i-1UL ], sizeof(fd_pubkey_t) ) ) { + for( ulong i=ctx->accounts.accounts_cnt; i>0UL; i-- ) { + if( 0==memcmp( pubkey, &ctx->accounts.account_keys[ i-1UL ], sizeof(fd_pubkey_t) ) ) { return (int)(i-1UL); } } @@ -290,9 +266,6 @@ fd_exec_txn_ctx_get_key_of_account_at_index( fd_exec_txn_ctx_t * ctx, ushort idx, fd_pubkey_t const * * key ); -void -fd_exec_txn_ctx_reset_return_data( fd_exec_txn_ctx_t * ctx ); - /* In agave, the writable accounts cache is populated by this below function. This cache is then referenced to determine if a transaction account is writable or not. diff --git a/src/flamenco/runtime/fd_borrowed_account.c b/src/flamenco/runtime/fd_borrowed_account.c index 181669d4733..f632cd7d19d 100644 --- a/src/flamenco/runtime/fd_borrowed_account.c +++ b/src/flamenco/runtime/fd_borrowed_account.c @@ -224,7 +224,7 @@ fd_borrowed_account_update_accounts_resize_delta( fd_borrowed_account_t * borrow /* TODO: The size delta should never exceed the value of ULONG_MAX so this could be replaced with a normal addition. However to match execution with the agave client, this is being left as a sat add */ - instr_ctx->txn_ctx->accounts_resize_delta = fd_ulong_sat_add( instr_ctx->txn_ctx->accounts_resize_delta, size_delta ); + instr_ctx->txn_ctx->details.accounts_resize_delta = fd_ulong_sat_add( instr_ctx->txn_ctx->details.accounts_resize_delta, size_delta ); *err = FD_EXECUTOR_INSTR_SUCCESS; return 1; } diff --git a/src/flamenco/runtime/fd_borrowed_account.h b/src/flamenco/runtime/fd_borrowed_account.h index 8a3ca036389..1742c2a0e5c 100644 --- a/src/flamenco/runtime/fd_borrowed_account.h +++ b/src/flamenco/runtime/fd_borrowed_account.h @@ -295,7 +295,7 @@ fd_borrowed_account_is_executable( fd_borrowed_account_t const * borrowed_acct ) FD_FN_PURE static inline int fd_borrowed_account_is_executable_internal( fd_borrowed_account_t const * borrowed_acct ) { - return !FD_FEATURE_ACTIVE( borrowed_acct->instr_ctx->txn_ctx->slot, &borrowed_acct->instr_ctx->txn_ctx->features, remove_accounts_executable_flag_checks ) && + return !FD_FEATURE_ACTIVE_BANK( borrowed_acct->instr_ctx->txn_ctx->bank, remove_accounts_executable_flag_checks ) && fd_borrowed_account_is_executable( borrowed_acct ); } @@ -423,7 +423,7 @@ fd_borrowed_account_can_data_be_resized( fd_borrowed_account_t const * borrowed_ /* The resize can not exceed the per-transaction maximum https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1104-L1108 */ ulong length_delta = fd_ulong_sat_sub( new_length, fd_txn_account_get_data_len( acct ) ); - ulong new_accounts_resize_delta = fd_ulong_sat_add( borrowed_acct->instr_ctx->txn_ctx->accounts_resize_delta, length_delta ); + ulong new_accounts_resize_delta = fd_ulong_sat_add( borrowed_acct->instr_ctx->txn_ctx->details.accounts_resize_delta, length_delta ); if( FD_UNLIKELY( new_accounts_resize_delta > MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN ) ) { *err = FD_EXECUTOR_INSTR_ERR_MAX_ACCS_DATA_ALLOCS_EXCEEDED; return 0; diff --git a/src/flamenco/runtime/fd_cost_tracker.c b/src/flamenco/runtime/fd_cost_tracker.c index f0c7f5a14d2..7334791b477 100644 --- a/src/flamenco/runtime/fd_cost_tracker.c +++ b/src/flamenco/runtime/fd_cost_tracker.c @@ -296,8 +296,8 @@ calculate_non_vote_transaction_cost( fd_exec_txn_ctx_t const * txn_ctx, .signature_cost = signature_cost, .write_lock_cost = write_lock_cost, .data_bytes_cost = data_bytes_cost, - .programs_execution_cost = fd_ulong_sat_sub( txn_ctx->compute_budget_details.compute_unit_limit, - txn_ctx->compute_budget_details.compute_meter ), + .programs_execution_cost = fd_ulong_sat_sub( txn_ctx->details.compute_budget.compute_unit_limit, + txn_ctx->details.compute_budget.compute_meter ), .loaded_accounts_data_size_cost = loaded_accounts_data_size_cost, .allocated_accounts_data_size = allocated_accounts_data_size, } @@ -384,10 +384,10 @@ would_fit( fd_cost_tracker_t const * cost_tracker, account_cost_map_t const * map = fd_type_pun_const(((cost_tracker_outer_t const *)cost_tracker)+1UL); account_cost_t const * pool = fd_type_pun_const( (void*)((ulong)cost_tracker + ((cost_tracker_outer_t const *)cost_tracker)->pool_offset) ); - for( ulong i=0UL; iaccounts_cnt; i++ ) { + for( ulong i=0UL; iaccounts.accounts_cnt; i++ ) { if( !fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, (ushort)i ) ) continue; - fd_pubkey_t const * writable_acc = &txn_ctx->account_keys[i]; + fd_pubkey_t const * writable_acc = &txn_ctx->accounts.account_keys[i]; account_cost_t const * chained_cost = account_cost_map_ele_query_const( map, writable_acc, NULL, pool ); if( FD_UNLIKELY( chained_cost && fd_ulong_sat_add( chained_cost->cost, cost )>cost_tracker->account_cost_limit ) ) { @@ -408,10 +408,10 @@ add_transaction_execution_cost( fd_cost_tracker_t * _cost_tracker, account_cost_map_t * map = fd_type_pun( cost_tracker+1UL ); account_cost_t * pool = fd_type_pun( (void*)((ulong)cost_tracker+cost_tracker->pool_offset) ); - for( ulong i=0UL; iaccounts_cnt; i++ ) { + for( ulong i=0UL; iaccounts.accounts_cnt; i++ ) { if( FD_LIKELY( !fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, (ushort)i ) ) ) continue; - fd_pubkey_t const * writable_acc = &txn_ctx->account_keys[i]; + fd_pubkey_t const * writable_acc = &txn_ctx->accounts.account_keys[i]; account_cost_t * account_cost = account_cost_map_ele_query( map, writable_acc, NULL, pool ); if( FD_UNLIKELY( !account_cost ) ) { diff --git a/src/flamenco/runtime/fd_cost_tracker.h b/src/flamenco/runtime/fd_cost_tracker.h index 4ae201b60a8..d5846e92133 100644 --- a/src/flamenco/runtime/fd_cost_tracker.h +++ b/src/flamenco/runtime/fd_cost_tracker.h @@ -128,7 +128,7 @@ fd_cost_tracker_init( fd_cost_tracker_t * cost_tracker, /* https://github.com/anza-xyz/agave/blob/v2.2.0/cost-model/src/cost_model.rs#L323-L328 */ FD_FN_PURE static inline ulong fd_cost_tracker_calculate_loaded_accounts_data_size_cost( fd_exec_txn_ctx_t const * txn_ctx ) { - ulong cost = fd_ulong_sat_sub( fd_ulong_sat_add( txn_ctx->loaded_accounts_data_size, + ulong cost = fd_ulong_sat_sub( fd_ulong_sat_add( txn_ctx->details.loaded_accounts_data_size, FD_ACCOUNT_DATA_COST_PAGE_SIZE ), 1UL ); cost /= FD_ACCOUNT_DATA_COST_PAGE_SIZE; diff --git a/src/flamenco/runtime/fd_executor.c b/src/flamenco/runtime/fd_executor.c index 1d09f4aba94..0d81b50e6cb 100644 --- a/src/flamenco/runtime/fd_executor.c +++ b/src/flamenco/runtime/fd_executor.c @@ -281,7 +281,7 @@ fd_executor_check_status_cache( fd_exec_txn_ctx_t * txn_ctx ) { return FD_RUNTIME_EXECUTE_SUCCESS; } - if( FD_UNLIKELY( txn_ctx->nonce_account_idx_in_txn!=ULONG_MAX ) ) { + if( FD_UNLIKELY( txn_ctx->accounts.nonce_idx_in_txn!=ULONG_MAX ) ) { /* In Agave, durable nonce transactions are inserted to the status cache the same as any others, but this is only to serve RPC requests, they do not need to be in there for correctness as the @@ -296,10 +296,10 @@ fd_executor_check_status_cache( fd_exec_txn_ctx_t * txn_ctx ) { fd_blake3_init( b3 ); fd_blake3_append( b3, "solana-tx-message-v1", 20UL ); fd_blake3_append( b3, ((uchar *)txn_ctx->txn.payload + TXN( &txn_ctx->txn )->message_off),(ulong)( txn_ctx->txn.payload_sz - TXN( &txn_ctx->txn )->message_off ) ); - fd_blake3_fini( b3, &txn_ctx->blake_txn_msg_hash ); + fd_blake3_fini( b3, &txn_ctx->details.blake_txn_msg_hash ); fd_hash_t * blockhash = (fd_hash_t *)((uchar *)txn_ctx->txn.payload + TXN( &txn_ctx->txn )->recent_blockhash_off); - int found = fd_txncache_query( txn_ctx->status_cache, txn_ctx->bank->txncache_fork_id, blockhash->uc, txn_ctx->blake_txn_msg_hash.uc ); + int found = fd_txncache_query( txn_ctx->status_cache, txn_ctx->bank->txncache_fork_id, blockhash->uc, txn_ctx->details.blake_txn_msg_hash.uc ); if( FD_UNLIKELY( found ) ) return FD_RUNTIME_TXN_ERR_ALREADY_PROCESSED; return FD_RUNTIME_EXECUTE_SUCCESS; @@ -380,10 +380,10 @@ fd_executor_setup_instr_infos_from_txn_instrs( fd_exec_txn_ctx_t * txn_ctx ) { /* Set up the instr infos for the transaction */ for( ushort i=0; itxn )->instr[i]; - fd_instr_info_init_from_txn_instr( &txn_ctx->instr_infos[i], txn_ctx, instr ); + fd_instr_info_init_from_txn_instr( &txn_ctx->instr.infos[i], txn_ctx, instr ); } - txn_ctx->instr_info_cnt = instr_cnt; + txn_ctx->instr.info_cnt = instr_cnt; } /* https://github.com/anza-xyz/agave/blob/v2.0.9/svm/src/account_loader.rs#L410-427 */ @@ -434,7 +434,7 @@ load_transaction_account( fd_exec_txn_ctx_t * txn_ctx, constructed by the SVM and modified within each transaction's instruction execution only, so it incurs a loaded size cost of 0. */ - fd_sysvar_instructions_serialize_account( txn_ctx, (fd_instr_info_t const *)txn_ctx->instr_infos, TXN( &txn_ctx->txn )->instr_cnt, txn_idx ); + fd_sysvar_instructions_serialize_account( txn_ctx, (fd_instr_info_t const *)txn_ctx->instr.infos, TXN( &txn_ctx->txn )->instr_cnt, txn_idx ); return 0UL; } @@ -479,11 +479,11 @@ load_transaction_account( fd_exec_txn_ctx_t * txn_ctx, https://github.com/anza-xyz/agave/blob/v2.3.1/svm/src/account_loader.rs#L691-L807 */ static int fd_executor_load_transaction_accounts_old( fd_exec_txn_ctx_t * txn_ctx ) { - ulong requested_loaded_accounts_data_size = txn_ctx->compute_budget_details.loaded_accounts_data_size_limit; + ulong requested_loaded_accounts_data_size = txn_ctx->details.compute_budget.loaded_accounts_data_size_limit; /* https://github.com/anza-xyz/agave/blob/v2.2.0/svm/src/account_loader.rs#L429-L443 */ - for( ushort i=0; iaccounts_cnt; i++ ) { - fd_txn_account_t * acct = &txn_ctx->accounts[i]; + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { + fd_txn_account_t * acct = &txn_ctx->accounts.accounts[i]; uchar unknown_acc = !!(fd_exec_txn_ctx_get_account_at_index( txn_ctx, i, &acct, fd_txn_account_check_exists ) || fd_txn_account_get_lamports( acct )==0UL); uchar is_writable = !!(fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, i )); @@ -500,7 +500,7 @@ fd_executor_load_transaction_accounts_old( fd_exec_txn_ctx_t * txn_ctx ) { is enabled. */ int err = accumulate_and_check_loaded_account_data_size( fd_txn_account_get_data_len( acct ), requested_loaded_accounts_data_size, - &txn_ctx->loaded_accounts_data_size ); + &txn_ctx->details.loaded_accounts_data_size ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { return err; } @@ -511,7 +511,7 @@ fd_executor_load_transaction_accounts_old( fd_exec_txn_ctx_t * txn_ctx ) { ulong loaded_acc_size = load_transaction_account( txn_ctx, acct, is_writable, unknown_acc, i ); int err = accumulate_and_check_loaded_account_data_size( loaded_acc_size, requested_loaded_accounts_data_size, - &txn_ctx->loaded_accounts_data_size ); + &txn_ctx->details.loaded_accounts_data_size ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { return err; @@ -529,7 +529,7 @@ fd_executor_load_transaction_accounts_old( fd_exec_txn_ctx_t * txn_ctx ) { fd_txn_instr_t const * instr = &TXN( &txn_ctx->txn )->instr[i]; /* https://github.com/anza-xyz/agave/blob/v2.2.0/svm/src/account_loader.rs#L449-L451 */ - if( FD_UNLIKELY( !memcmp( txn_ctx->account_keys[ instr->program_id ].key, fd_solana_native_loader_id.key, sizeof(fd_pubkey_t) ) ) ) { + if( FD_UNLIKELY( !memcmp( txn_ctx->accounts.account_keys[ instr->program_id ].key, fd_solana_native_loader_id.key, sizeof(fd_pubkey_t) ) ) ) { continue; } @@ -595,7 +595,7 @@ fd_executor_load_transaction_accounts_old( fd_exec_txn_ctx_t * txn_ctx ) { https://github.com/anza-xyz/agave/blob/v2.2.0/svm/src/account_loader.rs#L511-L517 */ err = accumulate_and_check_loaded_account_data_size( fd_txn_account_get_data_len( owner_account ), requested_loaded_accounts_data_size, - &txn_ctx->loaded_accounts_data_size ); + &txn_ctx->details.loaded_accounts_data_size ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { return err; } @@ -616,9 +616,9 @@ fd_increase_calculated_data_size( fd_exec_txn_ctx_t * txn_ctx, } /* https://github.com/anza-xyz/agave/blob/v2.3.1/svm/src/account_loader.rs#L505-L507 */ - txn_ctx->loaded_accounts_data_size = fd_ulong_sat_add( txn_ctx->loaded_accounts_data_size, data_size_delta ); + txn_ctx->details.loaded_accounts_data_size = fd_ulong_sat_add( txn_ctx->details.loaded_accounts_data_size, data_size_delta ); - if( FD_UNLIKELY( txn_ctx->loaded_accounts_data_size>txn_ctx->compute_budget_details.loaded_accounts_data_size_limit ) ) { + if( FD_UNLIKELY( txn_ctx->details.loaded_accounts_data_size>txn_ctx->details.compute_budget.loaded_accounts_data_size_limit ) ) { return FD_RUNTIME_TXN_ERR_MAX_LOADED_ACCOUNTS_DATA_SIZE_EXCEEDED; } @@ -667,8 +667,8 @@ fd_collect_loaded_account( fd_exec_txn_ctx_t * txn_ctx, /* Iterate through the account keys and make sure the programdata account is not present so it doesn't get loaded twice. https://github.com/anza-xyz/agave/blob/v2.3.1/svm/src/account_loader.rs#L617 */ - for( ushort i=0; iaccounts_cnt; i++ ) { - if( FD_UNLIKELY( !memcmp( &txn_ctx->account_keys[i], &loader_state->inner.program.programdata_address, sizeof(fd_pubkey_t) ) ) ) { + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { + if( FD_UNLIKELY( !memcmp( &txn_ctx->accounts.account_keys[i], &loader_state->inner.program.programdata_address, sizeof(fd_pubkey_t) ) ) ) { return FD_RUNTIME_EXECUTE_SUCCESS; } } @@ -741,8 +741,8 @@ fd_executor_load_transaction_accounts_simd_186( fd_exec_txn_ctx_t * txn_ctx ) { } /* https://github.com/anza-xyz/agave/blob/v2.3.1/svm/src/account_loader.rs#L642-L660 */ - for( ushort i=0; iaccounts_cnt; i++ ) { - fd_txn_account_t * acct = &txn_ctx->accounts[i]; + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { + fd_txn_account_t * acct = &txn_ctx->accounts.accounts[i]; uchar unknown_acc = !!(fd_exec_txn_ctx_get_account_at_index( txn_ctx, i, &acct, fd_txn_account_check_exists ) || fd_txn_account_get_lamports( acct )==0UL); uchar is_writable = !!(fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, i )); @@ -834,15 +834,15 @@ fd_executor_validate_account_locks( fd_exec_txn_ctx_t const * txn_ctx ) { /* Ensure the number of account keys does not exceed the transaction lock limit https://github.com/anza-xyz/agave/blob/v2.2.17/accounts-db/src/account_locks.rs#L121 */ ulong tx_account_lock_limit = get_transaction_account_lock_limit( txn_ctx ); - if( FD_UNLIKELY( txn_ctx->accounts_cnt>tx_account_lock_limit ) ) { + if( FD_UNLIKELY( txn_ctx->accounts.accounts_cnt>tx_account_lock_limit ) ) { return FD_RUNTIME_TXN_ERR_TOO_MANY_ACCOUNT_LOCKS; } /* Duplicate account check https://github.com/anza-xyz/agave/blob/v2.2.17/accounts-db/src/account_locks.rs#L123 */ - for( ushort i=0; iaccounts_cnt; i++ ) { - for( ushort j=(ushort)(i+1U); jaccounts_cnt; j++ ) { - if( FD_UNLIKELY( !memcmp( &txn_ctx->account_keys[i], &txn_ctx->account_keys[j], sizeof(fd_pubkey_t) ) ) ) { + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { + for( ushort j=(ushort)(i+1U); jaccounts.accounts_cnt; j++ ) { + if( FD_UNLIKELY( !memcmp( &txn_ctx->accounts.account_keys[i], &txn_ctx->accounts.account_keys[j], sizeof(fd_pubkey_t) ) ) ) { return FD_RUNTIME_TXN_ERR_ACCOUNT_LOADED_TWICE; } } @@ -874,7 +874,7 @@ fd_executor_calculate_fee( fd_exec_txn_ctx_t * txn_ctx, ulong num_signatures = txn_descriptor->signature_cnt; for (ushort i=0; iinstr_cnt; ++i ) { fd_txn_instr_t const * txn_instr = &txn_descriptor->instr[i]; - fd_pubkey_t * program_id = &txn_ctx->account_keys[txn_instr->program_id]; + fd_pubkey_t * program_id = &txn_ctx->accounts.account_keys[txn_instr->program_id]; if( !memcmp(program_id->uc, fd_solana_keccak_secp_256k_program_id.key, sizeof(fd_pubkey_t)) || !memcmp(program_id->uc, fd_solana_ed25519_sig_verify_program_id.key, sizeof(fd_pubkey_t)) || (!memcmp(program_id->uc, fd_solana_secp256r1_program_id.key, sizeof(fd_pubkey_t)) && FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, enable_secp256r1_precompile )) ) { @@ -886,7 +886,7 @@ fd_executor_calculate_fee( fd_exec_txn_ctx_t * txn_ctx, } } *ret_execution_fee = FD_RUNTIME_FEE_STRUCTURE_LAMPORTS_PER_SIGNATURE * num_signatures; - *ret_priority_fee = fd_get_prioritization_fee( &txn_ctx->compute_budget_details ); + *ret_priority_fee = fd_get_prioritization_fee( &txn_ctx->details.compute_budget ); } /* This function creates a rollback account for just the fee payer. Although Agave @@ -908,25 +908,25 @@ fd_executor_calculate_fee( fd_exec_txn_ctx_t * txn_ctx, static void fd_executor_create_rollback_fee_payer_account( fd_exec_txn_ctx_t * txn_ctx, ulong total_fee ) { - fd_pubkey_t * fee_payer_key = &txn_ctx->account_keys[FD_FEE_PAYER_TXN_IDX]; + fd_pubkey_t * fee_payer_key = &txn_ctx->accounts.account_keys[FD_FEE_PAYER_TXN_IDX]; fd_txn_account_t * rollback_fee_payer_acc; /* When setting the data of the rollback fee payer, there is an edge case where the fee payer is the nonce account. In this case, we can just deduct fees from the nonce account and return, because we save the nonce account in the commit phase anyways. */ - if( FD_UNLIKELY( txn_ctx->nonce_account_idx_in_txn==FD_FEE_PAYER_TXN_IDX ) ) { - rollback_fee_payer_acc = txn_ctx->rollback_nonce_account; + if( FD_UNLIKELY( txn_ctx->accounts.nonce_idx_in_txn==FD_FEE_PAYER_TXN_IDX ) ) { + rollback_fee_payer_acc = txn_ctx->accounts.rollback_nonce; } else { fd_account_meta_t const * meta = NULL; if( FD_UNLIKELY( txn_ctx->bundle.is_bundle ) ) { int is_found = 0; for( ulong i=txn_ctx->bundle.prev_txn_ctxs_cnt; i>0UL && !is_found; i-- ) {; fd_exec_txn_ctx_t * prev_txn_ctx = txn_ctx->bundle.prev_txn_ctxs[ i-1 ]; - for( ushort j=0UL; jaccounts_cnt; j++ ) { - if( !memcmp( &prev_txn_ctx->account_keys[ j ], fee_payer_key, sizeof(fd_pubkey_t) ) && fd_exec_txn_ctx_account_is_writable_idx( prev_txn_ctx, j ) ) { + for( ushort j=0UL; jaccounts.accounts_cnt; j++ ) { + if( !memcmp( &prev_txn_ctx->accounts.account_keys[ j ], fee_payer_key, sizeof(fd_pubkey_t) ) && fd_exec_txn_ctx_account_is_writable_idx( prev_txn_ctx, j ) ) { /* Found the account in a previous transaction */ - meta = prev_txn_ctx-> accounts[ j ].meta; + meta = prev_txn_ctx->accounts.accounts[ j ].meta; is_found = 1; break; } @@ -948,14 +948,14 @@ fd_executor_create_rollback_fee_payer_account( fd_exec_txn_ctx_t * txn_ctx, uchar * fee_payer_data = txn_ctx->exec_accounts->rollback_fee_payer_mem; fd_memcpy( fee_payer_data, (uchar *)meta, sizeof(fd_account_meta_t) + meta->dlen ); if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new( - txn_ctx->rollback_fee_payer_account, + txn_ctx->accounts.rollback_fee_payer, fee_payer_key, (fd_account_meta_t *)fee_payer_data, 1 ) ) ) ) { FD_LOG_CRIT(( "Failed to join txn account" )); } - rollback_fee_payer_acc = txn_ctx->rollback_fee_payer_account; + rollback_fee_payer_acc = txn_ctx->accounts.rollback_fee_payer; } /* Deduct the transaction fees from the rollback account. Because of prior checks, this should never fail. */ @@ -1003,8 +1003,8 @@ fd_executor_validate_transaction_fee_payer( fd_exec_txn_ctx_t * txn_ctx ) { /* Set the starting lamports (to avoid unbalanced lamports issues in instruction execution) */ fee_payer_rec->starting_lamports = fd_txn_account_get_lamports( fee_payer_rec ); /* TODO: why do we do this everywhere? */ - txn_ctx->execution_fee = execution_fee; - txn_ctx->priority_fee = priority_fee; + txn_ctx->details.execution_fee = execution_fee; + txn_ctx->details.priority_fee = priority_fee; return FD_RUNTIME_EXECUTE_SUCCESS; } @@ -1012,12 +1012,12 @@ fd_executor_validate_transaction_fee_payer( fd_exec_txn_ctx_t * txn_ctx ) { /* Simply unpacks the account keys from the serialized transaction and sets them in the txn_ctx. */ void fd_executor_setup_txn_account_keys( fd_exec_txn_ctx_t * txn_ctx ) { - txn_ctx->accounts_cnt = (uchar)TXN( &txn_ctx->txn )->acct_addr_cnt; + txn_ctx->accounts.accounts_cnt = (uchar)TXN( &txn_ctx->txn )->acct_addr_cnt; fd_pubkey_t * tx_accs = (fd_pubkey_t *)((uchar *)txn_ctx->txn.payload + TXN( &txn_ctx->txn )->acct_addr_off); // Set up accounts in the transaction body and perform checks for( ulong i = 0UL; i < TXN( &txn_ctx->txn )->acct_addr_cnt; i++ ) { - txn_ctx->account_keys[i] = tx_accs[i]; + txn_ctx->accounts.account_keys[i] = tx_accs[i]; } } @@ -1034,16 +1034,16 @@ fd_executor_setup_txn_alut_account_keys( fd_exec_txn_ctx_t * txn_ctx ) { return FD_RUNTIME_TXN_ERR_ACCOUNT_NOT_FOUND; } - fd_acct_addr_t * accts_alt = (fd_acct_addr_t *) fd_type_pun( &txn_ctx->account_keys[txn_ctx->accounts_cnt] ); + fd_acct_addr_t * accts_alt = (fd_acct_addr_t *) fd_type_pun( &txn_ctx->accounts.account_keys[txn_ctx->accounts.accounts_cnt] ); int err = fd_runtime_load_txn_address_lookup_tables( TXN( &txn_ctx->txn ), txn_ctx->txn.payload, txn_ctx->funk, txn_ctx->xid, - txn_ctx->slot, + fd_bank_slot_get( txn_ctx->bank ), slot_hashes, accts_alt ); fd_sysvar_cache_slot_hashes_leave_const( sysvar_cache, slot_hashes ); - txn_ctx->accounts_cnt += TXN( &txn_ctx->txn )->addr_table_adtl_cnt; + txn_ctx->accounts.accounts_cnt += TXN( &txn_ctx->txn )->addr_table_adtl_cnt; if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) return err; } @@ -1070,9 +1070,9 @@ fd_txn_ctx_push( fd_exec_txn_ctx_t * txn_ctx, /* Check that the caller's lamport sum has not changed. https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/sdk/src/transaction_context.rs#L329-L340 */ - if( txn_ctx->instr_stack_sz>0 ) { + if( txn_ctx->instr.stack_sz>0 ) { /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/sdk/src/transaction_context.rs#L330 */ - fd_exec_instr_ctx_t const * caller_instruction_context = &txn_ctx->instr_stack[ txn_ctx->instr_stack_sz-1 ]; + fd_exec_instr_ctx_t const * caller_instruction_context = &txn_ctx->instr.stack[ txn_ctx->instr.stack_sz-1 ]; /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/sdk/src/transaction_context.rs#L331-L332 */ ulong original_caller_lamport_sum_h = caller_instruction_context->instr->starting_lamports_h; @@ -1097,16 +1097,16 @@ fd_txn_ctx_push( fd_exec_txn_ctx_t * txn_ctx, } /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/sdk/src/transaction_context.rs#L347-L351 */ - if( FD_UNLIKELY( txn_ctx->instr_trace_length>=FD_MAX_INSTRUCTION_TRACE_LENGTH ) ) { + if( FD_UNLIKELY( txn_ctx->instr.trace_length>=FD_MAX_INSTRUCTION_TRACE_LENGTH ) ) { return FD_EXECUTOR_INSTR_ERR_MAX_INSN_TRACE_LENS_EXCEEDED; } - txn_ctx->instr_trace_length++; + txn_ctx->instr.trace_length++; /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/sdk/src/transaction_context.rs#L352-L356 */ - if( FD_UNLIKELY( txn_ctx->instr_stack_sz>=FD_MAX_INSTRUCTION_STACK_DEPTH ) ) { + if( FD_UNLIKELY( txn_ctx->instr.stack_sz>=FD_MAX_INSTRUCTION_STACK_DEPTH ) ) { return FD_EXECUTOR_INSTR_ERR_CALL_DEPTH; } - txn_ctx->instr_stack_sz++; + txn_ctx->instr.stack_sz++; /* A beloved refactor moves sysvar instructions updating to the instruction level as of v2.2.12... https://github.com/anza-xyz/agave/blob/v2.2.12/transaction-context/src/lib.rs#L396-L407 */ @@ -1125,7 +1125,7 @@ fd_txn_ctx_push( fd_exec_txn_ctx_t * txn_ctx, } /* https://github.com/anza-xyz/agave/blob/v2.2.12/transaction-context/src/lib.rs#L403-L406 */ - fd_sysvar_instructions_update_current_instr_idx( sysvar_instructions_account, (ushort)txn_ctx->current_instr_idx ); + fd_sysvar_instructions_update_current_instr_idx( sysvar_instructions_account, (ushort)txn_ctx->instr.current_idx ); fd_txn_account_drop( sysvar_instructions_account ); } @@ -1159,18 +1159,18 @@ fd_instr_stack_push( fd_exec_txn_ctx_t * txn_ctx, } /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/program-runtime/src/invoke_context.rs#L256-L286 */ - if( txn_ctx->instr_stack_sz ) { + if( txn_ctx->instr.stack_sz ) { /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/program-runtime/src/invoke_context.rs#L261-L285 */ uchar contains = 0; uchar is_last = 0; // Checks all previous instructions in the stack for reentrancy - for( uchar level=0; levelinstr_stack_sz; level++ ) { - fd_exec_instr_ctx_t * instr_ctx = &txn_ctx->instr_stack[level]; + for( uchar level=0; levelinstr.stack_sz; level++ ) { + fd_exec_instr_ctx_t * instr_ctx = &txn_ctx->instr.stack[level]; // Optimization: compare program id index instead of pubkey since account keys are unique if( instr->program_id == instr_ctx->instr->program_id ) { // Reentrancy not allowed unless caller is calling itself - if( level == txn_ctx->instr_stack_sz-1 ) { + if( level == txn_ctx->instr.stack_sz-1 ) { is_last = 1; } contains = 1; @@ -1195,16 +1195,16 @@ int fd_instr_stack_pop( fd_exec_txn_ctx_t * txn_ctx, fd_instr_info_t const * instr ) { /* https://github.com/anza-xyz/agave/blob/c4b42ab045860d7b13b3912eafb30e6d2f4e593f/sdk/src/transaction_context.rs#L362-L364 */ - if( FD_UNLIKELY( txn_ctx->instr_stack_sz==0 ) ) { + if( FD_UNLIKELY( txn_ctx->instr.stack_sz==0 ) ) { return FD_EXECUTOR_INSTR_ERR_CALL_DEPTH; } - txn_ctx->instr_stack_sz--; + txn_ctx->instr.stack_sz--; /* Verify all executable accounts have no outstanding refs https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L367-L371 */ for( ushort i=0; iacct_cnt; i++ ) { ushort idx_in_txn = instr->accounts[i].index_in_transaction; - fd_txn_account_t * account = &txn_ctx->accounts[ idx_in_txn ]; + fd_txn_account_t * account = &txn_ctx->accounts.accounts[ idx_in_txn ]; if( FD_UNLIKELY( fd_txn_account_is_executable( account ) && fd_txn_account_is_borrowed( account ) ) ) { return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_OUTSTANDING; @@ -1241,14 +1241,10 @@ fd_execute_instr_end( fd_exec_instr_ctx_t * instr_ctx, /* Only report the stack pop error on success */ if( FD_UNLIKELY( instr_exec_result==FD_EXECUTOR_INSTR_SUCCESS && stack_pop_err ) ) { FD_TXN_PREPARE_ERR_OVERWRITE( instr_ctx->txn_ctx ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, stack_pop_err, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, stack_pop_err, instr_ctx->txn_ctx->err.exec_err_idx ); instr_exec_result = stack_pop_err; } - if( FD_UNLIKELY( instr_exec_result && !instr_ctx->txn_ctx->failed_instr ) ) { - instr_ctx->txn_ctx->failed_instr = instr_ctx; - } - return instr_exec_result; } @@ -1259,37 +1255,37 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, int instr_exec_result = fd_instr_stack_push( txn_ctx, instr ); if( FD_UNLIKELY( instr_exec_result ) ) { FD_TXN_PREPARE_ERR_OVERWRITE( txn_ctx ); - FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->err.exec_err_idx ); return instr_exec_result; } /* `process_executable_chain()` https://github.com/anza-xyz/agave/blob/v2.2.12/program-runtime/src/invoke_context.rs#L512-L619 */ - fd_exec_instr_ctx_t * ctx = &txn_ctx->instr_stack[ txn_ctx->instr_stack_sz - 1 ]; + fd_exec_instr_ctx_t * ctx = &txn_ctx->instr.stack[ txn_ctx->instr.stack_sz - 1 ]; *ctx = (fd_exec_instr_ctx_t) { .instr = instr, .txn_ctx = txn_ctx, .sysvar_cache = sysvar_cache, }; - fd_base58_encode_32( txn_ctx->accounts[ instr->program_id ].pubkey->uc, NULL, ctx->program_id_base58 ); + fd_base58_encode_32( txn_ctx->accounts.accounts[ instr->program_id ].pubkey->uc, NULL, ctx->program_id_base58 ); - txn_ctx->instr_trace[ txn_ctx->instr_trace_length - 1 ] = (fd_exec_instr_trace_entry_t) { + txn_ctx->instr.trace[ txn_ctx->instr.trace_length - 1 ] = (fd_exec_instr_trace_entry_t) { .instr_info = instr, - .stack_height = txn_ctx->instr_stack_sz, + .stack_height = txn_ctx->instr.stack_sz, }; /* Look up the native program. We check for precompiles within the lookup function as well. https://github.com/anza-xyz/agave/blob/v2.1.6/svm/src/message_processor.rs#L88 */ fd_exec_instr_fn_t native_prog_fn; uchar is_precompile; - int err = fd_executor_lookup_native_program( &txn_ctx->accounts[ instr->program_id ], + int err = fd_executor_lookup_native_program( &txn_ctx->accounts.accounts[ instr->program_id ], txn_ctx, &native_prog_fn, &is_precompile ); if( FD_UNLIKELY( err ) ) { FD_TXN_PREPARE_ERR_OVERWRITE( txn_ctx ); - FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, err, txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, err, txn_ctx->err.exec_err_idx ); return err; } @@ -1300,7 +1296,7 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, /* Only reset the return data when executing a native builtin program (not a precompile) https://github.com/anza-xyz/agave/blob/v2.1.6/program-runtime/src/invoke_context.rs#L536-L537 */ if( FD_LIKELY( !is_precompile ) ) { - fd_exec_txn_ctx_reset_return_data( txn_ctx ); + txn_ctx->details.return_data.len = 0; } /* Execute the native program. */ @@ -1309,7 +1305,7 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, /* Unknown program. In this case specifically, we should not log the program id. */ instr_exec_result = FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID; FD_TXN_PREPARE_ERR_OVERWRITE( txn_ctx ); - FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->err.exec_err_idx ); return fd_execute_instr_end( ctx, instr, instr_exec_result ); } @@ -1326,14 +1322,14 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, TODO: This hackily handles cases where the exec_err and exec_err_kind is not set yet. We should change our native programs to set this in their respective processors. */ - if( !txn_ctx->exec_err ) { + if( !txn_ctx->err.exec_err ) { FD_TXN_PREPARE_ERR_OVERWRITE( txn_ctx ); - FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->err.exec_err_idx ); fd_log_collector_program_failure( ctx ); } else { fd_log_collector_program_failure( ctx ); FD_TXN_PREPARE_ERR_OVERWRITE( txn_ctx ); - FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( txn_ctx, instr_exec_result, txn_ctx->err.exec_err_idx ); } } @@ -1343,49 +1339,13 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, void fd_executor_reclaim_account( fd_exec_txn_ctx_t * txn_ctx, fd_txn_account_t * account ) { - fd_txn_account_set_slot( account, txn_ctx->slot ); + fd_txn_account_set_slot( account, fd_bank_slot_get( txn_ctx->bank ) ); if( FD_UNLIKELY( fd_txn_account_get_lamports( account )==0UL ) ) { fd_txn_account_set_data_len( account, 0UL ); fd_txn_account_clear_owner( account ); } } -void -fd_exec_txn_ctx_setup( fd_bank_t * bank, - void * accdb_shfunk, - void * progcache_shfunk, - fd_funk_txn_xid_t const * xid, - fd_txncache_t * status_cache, - fd_exec_txn_ctx_t * ctx, - fd_bank_hash_cmp_t * bank_hash_cmp, - void * progcache_scratch, - ulong progcache_scratch_sz ) { - if( FD_UNLIKELY( !fd_funk_join( ctx->funk, accdb_shfunk ) ) ) { - FD_LOG_CRIT(( "fd_funk_join(accdb) failed" )); - } - - if( progcache_shfunk ) { - ctx->progcache = fd_progcache_join( ctx->_progcache, progcache_shfunk, progcache_scratch, progcache_scratch_sz ); - if( FD_UNLIKELY( !ctx->progcache ) ) { - FD_LOG_CRIT(( "fd_progcache_join() failed" )); - } - } - - ctx->xid[0] = *xid; - - ctx->status_cache = status_cache; - - ctx->bank_hash_cmp = bank_hash_cmp; - - ctx->enable_exec_recording = !!( bank->flags & FD_BANK_FLAGS_EXEC_RECORDING ); - - ctx->bank = bank; - - ctx->slot = fd_bank_slot_get( bank ); - - ctx->features = fd_bank_features_get( ctx->bank ); -} - fd_txn_account_t * fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx, ushort idx ) { @@ -1393,7 +1353,7 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx, /* To setup a transaction account, we need to first retrieve a read-only handle to the account from the database. */ - fd_pubkey_t * acc = &txn_ctx->account_keys[ idx ]; + fd_pubkey_t * acc = &txn_ctx->accounts.account_keys[ idx ]; fd_account_meta_t const * meta = NULL; @@ -1413,10 +1373,10 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx, int is_found = 0; for( ulong i=txn_ctx->bundle.prev_txn_ctxs_cnt; i>0UL && !is_found; i-- ) { fd_exec_txn_ctx_t * prev_txn_ctx = txn_ctx->bundle.prev_txn_ctxs[ i-1 ]; - for( ushort j=0UL; jaccounts_cnt; j++ ) { - if( !memcmp( &prev_txn_ctx->account_keys[ j ], acc, sizeof(fd_pubkey_t) ) && fd_exec_txn_ctx_account_is_writable_idx( prev_txn_ctx, j ) ) { + for( ushort j=0UL; jaccounts.accounts_cnt; j++ ) { + if( !memcmp( &prev_txn_ctx->accounts.account_keys[ j ], acc, sizeof(fd_pubkey_t) ) && fd_exec_txn_ctx_account_is_writable_idx( prev_txn_ctx, j ) ) { /* Found the account in a previous transaction */ - meta = prev_txn_ctx->accounts[ j ].meta; + meta = prev_txn_ctx->accounts.accounts[ j ].meta; is_found = 1; break; } @@ -1440,7 +1400,7 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx, FD_LOG_CRIT(( "fd_txn_account_init_from_funk_readonly err=%d", err )); } - fd_txn_account_t * txn_account = &txn_ctx->accounts[ idx ]; + fd_txn_account_t * txn_account = &txn_ctx->accounts.accounts[ idx ]; int is_writable = fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, idx ) || idx==FD_FEE_PAYER_TXN_IDX; fd_account_meta_t * account_meta = NULL; @@ -1508,7 +1468,7 @@ fd_executor_setup_executable_account( fd_exec_txn_ctx_t * txn_ctx, invoked, the call will fail at the instruction execution level since the programdata account will not exist within the executable accounts list. */ fd_pubkey_t * programdata_acc = &program_loader_state->inner.program.programdata_address; - if( FD_LIKELY( fd_txn_account_init_from_funk_readonly( &txn_ctx->executable_accounts[ *executable_idx ], + if( FD_LIKELY( fd_txn_account_init_from_funk_readonly( &txn_ctx->accounts.executable_accounts[ *executable_idx ], programdata_acc, txn_ctx->funk, txn_ctx->xid )==0 ) ) { @@ -1519,9 +1479,9 @@ fd_executor_setup_executable_account( fd_exec_txn_ctx_t * txn_ctx, void fd_executor_setup_accounts_for_txn( fd_exec_txn_ctx_t * txn_ctx ) { ushort j = 0UL; - fd_memset( txn_ctx->accounts, 0, sizeof(fd_txn_account_t) * txn_ctx->accounts_cnt ); + fd_memset( txn_ctx->accounts.accounts, 0, sizeof(fd_txn_account_t) * txn_ctx->accounts.accounts_cnt ); - for( ushort i=0; iaccounts_cnt; i++ ) { + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { fd_txn_account_t * txn_account = fd_executor_setup_txn_account( txn_ctx, i ); if( FD_UNLIKELY( txn_account && @@ -1531,17 +1491,17 @@ fd_executor_setup_accounts_for_txn( fd_exec_txn_ctx_t * txn_ctx ) { } /* Dumping ELF files to protobuf, if applicable */ - int dump_elf_to_pb = txn_ctx->capture_ctx && - txn_ctx->slot >= txn_ctx->capture_ctx->dump_proto_start_slot && - txn_ctx->capture_ctx->dump_elf_to_pb; + int dump_elf_to_pb = txn_ctx->log.capture_ctx && + fd_bank_slot_get( txn_ctx->bank ) >= txn_ctx->log.capture_ctx->dump_proto_start_slot && + txn_ctx->log.capture_ctx->dump_elf_to_pb; if( FD_UNLIKELY( dump_elf_to_pb ) ) { - for( ushort i=0; iaccounts_cnt; i++ ) { - fd_dump_elf_to_protobuf( txn_ctx, &txn_ctx->accounts[i] ); + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { + fd_dump_elf_to_protobuf( txn_ctx, &txn_ctx->accounts.accounts[i] ); } } - txn_ctx->nonce_account_idx_in_txn = ULONG_MAX; - txn_ctx->executable_cnt = j; + txn_ctx->accounts.nonce_idx_in_txn = ULONG_MAX; + txn_ctx->accounts.executable_cnt = j; /* Set up instr infos from the txn descriptor. No Agave equivalent to this function. */ fd_executor_setup_instr_infos_from_txn_instrs( txn_ctx ); @@ -1568,22 +1528,22 @@ fd_executor_txn_verify( fd_txn_p_t * txn_p, int fd_execute_txn( fd_exec_txn_ctx_t * txn_ctx ) { - bool dump_insn = txn_ctx->capture_ctx && txn_ctx->slot >= txn_ctx->capture_ctx->dump_proto_start_slot && txn_ctx->capture_ctx->dump_instr_to_pb; + bool dump_insn = txn_ctx->log.capture_ctx && fd_bank_slot_get( txn_ctx->bank ) >= txn_ctx->log.capture_ctx->dump_proto_start_slot && txn_ctx->log.capture_ctx->dump_instr_to_pb; - /* Initialize log collection */ - fd_log_collector_init( &txn_ctx->log_collector, txn_ctx->enable_exec_recording ); + /* Initialize log collection. */ + fd_log_collector_init( &txn_ctx->log.log_collector, txn_ctx->log.enable_exec_recording ); for( ushort i=0; itxn )->instr_cnt; i++ ) { - txn_ctx->current_instr_idx = i; + txn_ctx->instr.current_idx = i; if( FD_UNLIKELY( dump_insn ) ) { // Capture the input and convert it into a Protobuf message - fd_dump_instr_to_protobuf( txn_ctx, &txn_ctx->instr_infos[i], i ); + fd_dump_instr_to_protobuf( txn_ctx, &txn_ctx->instr.infos[i], i ); } - int instr_exec_result = fd_execute_instr( txn_ctx, &txn_ctx->instr_infos[i] ); + int instr_exec_result = fd_execute_instr( txn_ctx, &txn_ctx->instr.infos[i] ); if( FD_UNLIKELY( instr_exec_result!=FD_EXECUTOR_INSTR_SUCCESS ) ) { - if ( txn_ctx->instr_err_idx==INT_MAX ) { - txn_ctx->instr_err_idx = i; + if ( txn_ctx->err.exec_err_idx==INT_MAX ) { + txn_ctx->err.exec_err_idx = i; } return FD_RUNTIME_TXN_ERR_INSTRUCTION_ERROR; } @@ -1605,8 +1565,8 @@ fd_executor_txn_check( fd_exec_txn_ctx_t * txn_ctx ) { ulong ending_lamports_h = 0; /* https://github.com/anza-xyz/agave/blob/b2c388d6cbff9b765d574bbb83a4378a1fc8af32/svm/src/account_rent_state.rs#L63 */ - for( ulong idx = 0; idx < txn_ctx->accounts_cnt; idx++ ) { - fd_txn_account_t * b = &txn_ctx->accounts[idx]; + for( ulong idx = 0; idx < txn_ctx->accounts.accounts_cnt; idx++ ) { + fd_txn_account_t * b = &txn_ctx->accounts.accounts[idx]; // Was this account written to? /* TODO: Clean this logic up... lots of redundant checks with our newer account loading model. @@ -1714,7 +1674,7 @@ fd_executor_instr_strerror( int err ) { case FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED : return "instruction tries to borrow reference for an account which is already borrowed"; case FD_EXECUTOR_INSTR_ERR_ACC_BORROW_OUTSTANDING : return "instruction left account with an outstanding borrowed reference"; case FD_EXECUTOR_INSTR_ERR_DUPLICATE_ACCOUNT_OUT_OF_SYNC : return "instruction modifications of multiply-passed account differ"; - case FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR : return ""; // custom handling via txn_ctx->custom_err + case FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR : return ""; // custom handling via txn_ctx->err.custom_err case FD_EXECUTOR_INSTR_ERR_INVALID_ERR : return "program returned invalid error code"; case FD_EXECUTOR_INSTR_ERR_EXECUTABLE_DATA_MODIFIED : return "instruction changed executable accounts data"; case FD_EXECUTOR_INSTR_ERR_EXECUTABLE_LAMPORT_CHANGE : return "instruction changed the balance of an executable account"; diff --git a/src/flamenco/runtime/fd_executor.h b/src/flamenco/runtime/fd_executor.h index 36861a8ee68..7c0bcd076ee 100644 --- a/src/flamenco/runtime/fd_executor.h +++ b/src/flamenco/runtime/fd_executor.h @@ -113,13 +113,13 @@ fd_executor_validate_account_locks( fd_exec_txn_ctx_t const * txn_ctx ); static inline int fd_exec_consume_cus( fd_exec_txn_ctx_t * txn_ctx, ulong cus ) { - ulong new_cus = txn_ctx->compute_budget_details.compute_meter - cus; - int underflow = (txn_ctx->compute_budget_details.compute_meter < cus); + ulong new_cus = txn_ctx->details.compute_budget.compute_meter - cus; + int underflow = (txn_ctx->details.compute_budget.compute_meter < cus); if( FD_UNLIKELY( underflow ) ) { - txn_ctx->compute_budget_details.compute_meter = 0UL; + txn_ctx->details.compute_budget.compute_meter = 0UL; return FD_EXECUTOR_INSTR_ERR_COMPUTE_BUDGET_EXCEEDED; } - txn_ctx->compute_budget_details.compute_meter = new_cus; + txn_ctx->details.compute_budget.compute_meter = new_cus; return FD_EXECUTOR_INSTR_SUCCESS; } @@ -133,17 +133,6 @@ int fd_instr_stack_pop( fd_exec_txn_ctx_t * txn_ctx, fd_instr_info_t const * instr ); -void -fd_exec_txn_ctx_setup( fd_bank_t * bank, - void * accdb_shfunk, - void * progcache_shfunk, - fd_funk_txn_xid_t const * xid, - fd_txncache_t * status_cache, - fd_exec_txn_ctx_t * ctx, - fd_bank_hash_cmp_t * bank_hash_cmp, - void * progcache_scratch, - ulong progcache_scratch_sz ); - FD_PROTOTYPES_END #endif /* HEADER_fd_src_flamenco_runtime_fd_executor_h */ diff --git a/src/flamenco/runtime/fd_pubkey_utils.c b/src/flamenco/runtime/fd_pubkey_utils.c index 34b50cba679..b16ce22a974 100644 --- a/src/flamenco/runtime/fd_pubkey_utils.c +++ b/src/flamenco/runtime/fd_pubkey_utils.c @@ -14,12 +14,12 @@ fd_pubkey_create_with_seed( fd_exec_instr_ctx_t const * ctx, static char const pda_marker[] = {"ProgramDerivedAddress"}; if( seed_sz>MAX_SEED_LEN ) { - ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_MAX_SEED_LEN_EXCEEDED; + ctx->txn_ctx->err.custom_err = FD_PUBKEY_ERR_MAX_SEED_LEN_EXCEEDED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } if( 0==memcmp( owner+11UL, pda_marker, 21UL ) ) { - ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_ILLEGAL_OWNER; + ctx->txn_ctx->err.custom_err = FD_PUBKEY_ERR_ILLEGAL_OWNER; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } diff --git a/src/flamenco/runtime/fd_runtime.c b/src/flamenco/runtime/fd_runtime.c index 027c9048e53..5abe786ccd8 100644 --- a/src/flamenco/runtime/fd_runtime.c +++ b/src/flamenco/runtime/fd_runtime.c @@ -3,6 +3,7 @@ #include "fd_acc_mgr.h" #include "fd_alut_interp.h" #include "fd_bank.h" +#include "fd_executor_err.h" #include "fd_hashes.h" #include "fd_runtime_err.h" #include "fd_runtime_init.h" @@ -564,6 +565,12 @@ fd_runtime_update_bank_hash( fd_bank_t * bank, int fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { + /* Set up the core account keys. These are the account keys directly + passed in via the serialized transaction, represented as an array. + Note that this does not include additional keys referenced in + address lookup tables. */ + fd_executor_setup_txn_account_keys( txn_ctx ); + int err; /* https://github.com/anza-xyz/agave/blob/16de8b75ebcd57022409b422de557dd37b1de8db/sdk/src/transaction/sanitized.rs#L263-L275 @@ -591,9 +598,9 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { */ - uchar dump_txn = !!( txn_ctx->capture_ctx && - txn_ctx->slot >= txn_ctx->capture_ctx->dump_proto_start_slot && - txn_ctx->capture_ctx->dump_txn_to_pb ); + uchar dump_txn = !!( txn_ctx->log.capture_ctx && + fd_bank_slot_get( txn_ctx->bank ) >= txn_ctx->log.capture_ctx->dump_proto_start_slot && + txn_ctx->log.capture_ctx->dump_txn_to_pb ); if( FD_UNLIKELY( dump_txn ) ) { fd_dump_txn_to_protobuf( txn_ctx ); } @@ -602,14 +609,14 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { the compute budget instructions. */ err = fd_executor_verify_transaction( txn_ctx ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { - txn_ctx->flags = 0U; + txn_ctx->err.is_committable = 0; return err; } /* Resolve and verify ALUT-referenced account keys, if applicable */ err = fd_executor_setup_txn_alut_account_keys( txn_ctx ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { - txn_ctx->flags = 0U; + txn_ctx->err.is_committable = 0; return err; } @@ -622,7 +629,7 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { https://github.com/anza-xyz/agave/blob/838c1952595809a31520ff1603a13f2c9123aa51/accounts-db/src/account_locks.rs#L118 */ err = fd_executor_validate_account_locks( txn_ctx ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { - txn_ctx->flags = 0U; + txn_ctx->err.is_committable = 0; return err; } @@ -630,7 +637,7 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { https://github.com/anza-xyz/agave/blob/ced98f1ebe73f7e9691308afa757323003ff744f/runtime/src/bank.rs#L3667-L3672 */ err = fd_executor_check_transactions( txn_ctx ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { - txn_ctx->flags = 0U; + txn_ctx->err.is_committable = 0; return err; } @@ -639,7 +646,7 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { https://github.com/anza-xyz/agave/blob/ced98f1ebe73f7e9691308afa757323003ff744f/svm/src/transaction_processor.rs#L236-L249 */ err = fd_executor_validate_transaction_fee_payer( txn_ctx ); if( FD_UNLIKELY( err!=FD_RUNTIME_EXECUTE_SUCCESS ) ) { - txn_ctx->flags = 0U; + txn_ctx->err.is_committable = 0; return err; } @@ -649,7 +656,7 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { /* Regardless of whether transaction accounts were loaded successfully, the transaction is included in the block and transaction fees are collected. https://github.com/anza-xyz/agave/blob/v2.1.6/svm/src/transaction_processor.rs#L341-L357 */ - txn_ctx->flags |= FD_TXN_P_FLAGS_FEES_ONLY; + txn_ctx->err.is_fees_only = 1; /* If the transaction fails to load, the "rollback" accounts will include one of the following: 1. Nonce account only @@ -661,14 +668,14 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ) { https://github.com/anza-xyz/agave/blob/v2.1.14/runtime/src/bank.rs#L4116 In any case, we should always add the dlen of the fee payer. */ - txn_ctx->loaded_accounts_data_size = fd_txn_account_get_data_len( &txn_ctx->accounts[FD_FEE_PAYER_TXN_IDX] ); + txn_ctx->details.loaded_accounts_data_size = fd_txn_account_get_data_len( &txn_ctx->accounts.accounts[FD_FEE_PAYER_TXN_IDX] ); /* Special case handling for if a nonce account is present in the transaction. */ - if( txn_ctx->nonce_account_idx_in_txn!=ULONG_MAX ) { + if( txn_ctx->accounts.nonce_idx_in_txn!=ULONG_MAX ) { /* If the nonce account is not the fee payer, then we separately add the dlen of the nonce account. Otherwise, we would be double counting the dlen of the fee payer. */ - if( txn_ctx->nonce_account_idx_in_txn!=FD_FEE_PAYER_TXN_IDX ) { - txn_ctx->loaded_accounts_data_size += fd_txn_account_get_data_len( txn_ctx->rollback_nonce_account ); + if( txn_ctx->accounts.nonce_idx_in_txn!=FD_FEE_PAYER_TXN_IDX ) { + txn_ctx->details.loaded_accounts_data_size += fd_txn_account_get_data_len( txn_ctx->accounts.rollback_nonce ); } } } @@ -882,12 +889,11 @@ fd_runtime_finalize_txn( fd_funk_t * funk, /* Collect fees */ FD_ATOMIC_FETCH_AND_ADD( fd_bank_txn_count_modify( bank ), 1UL ); - FD_ATOMIC_FETCH_AND_ADD( fd_bank_execution_fees_modify( bank ), txn_ctx->execution_fee ); - FD_ATOMIC_FETCH_AND_ADD( fd_bank_priority_fees_modify( bank ), txn_ctx->priority_fee ); - + FD_ATOMIC_FETCH_AND_ADD( fd_bank_execution_fees_modify( bank ), txn_ctx->details.execution_fee ); + FD_ATOMIC_FETCH_AND_ADD( fd_bank_priority_fees_modify( bank ), txn_ctx->details.priority_fee ); FD_ATOMIC_FETCH_AND_ADD( fd_bank_signature_count_modify( bank ), TXN( &txn_ctx->txn )->signature_cnt ); - if( FD_UNLIKELY( txn_ctx->exec_err ) ) { + if( FD_UNLIKELY( txn_ctx->err.exec_err ) ) { /* Save the fee_payer. Everything but the fee balance should be reset. TODO: an optimization here could be to use a dirty flag in the @@ -902,13 +908,13 @@ fd_runtime_finalize_txn( fd_funk_t * funk, 3. Nonce account is not the fee payer We should always rollback the nonce account first. Note that the nonce account may be the fee payer (case 2). */ - if( txn_ctx->nonce_account_idx_in_txn!=ULONG_MAX ) { - fd_runtime_save_account( funk, xid, txn_ctx->rollback_nonce_account, bank, capture_ctx ); + if( txn_ctx->accounts.nonce_idx_in_txn!=ULONG_MAX ) { + fd_runtime_save_account( funk, xid, txn_ctx->accounts.rollback_nonce, bank, capture_ctx ); } /* Now, we must only save the fee payer if the nonce account was not the fee payer (because that was already saved above) */ - if( FD_LIKELY( txn_ctx->nonce_account_idx_in_txn!=FD_FEE_PAYER_TXN_IDX ) ) { - fd_runtime_save_account( funk, xid, txn_ctx->rollback_fee_payer_account, bank, capture_ctx ); + if( FD_LIKELY( txn_ctx->accounts.nonce_idx_in_txn!=FD_FEE_PAYER_TXN_IDX ) ) { + fd_runtime_save_account( funk, xid, txn_ctx->accounts.rollback_fee_payer, bank, capture_ctx ); } } else { @@ -919,14 +925,14 @@ fd_runtime_finalize_txn( fd_funk_t * funk, tip_accounts = MAINNET_TIP_ACCOUNTS; } - for( ushort i=0; iaccounts_cnt; i++ ) { + for( ushort i=0; iaccounts.accounts_cnt; i++ ) { /* We are only interested in saving writable accounts and the fee payer account. */ if( !fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, i ) && i!=FD_FEE_PAYER_TXN_IDX ) { continue; } - fd_txn_account_t * acc_rec = fd_txn_account_join( &txn_ctx->accounts[i] ); + fd_txn_account_t * acc_rec = fd_txn_account_join( &txn_ctx->accounts.accounts[i] ); if( FD_UNLIKELY( !acc_rec ) ) { FD_LOG_CRIT(( "fd_runtime_finalize_txn: failed to join account at idx %u", i )); } @@ -955,9 +961,9 @@ fd_runtime_finalize_txn( fd_funk_t * funk, /* Reclaim any accounts that have 0-lamports, now that any related cache updates have been applied. */ - fd_executor_reclaim_account( txn_ctx, &txn_ctx->accounts[i] ); + fd_executor_reclaim_account( txn_ctx, &txn_ctx->accounts.accounts[i] ); - fd_runtime_save_account( funk, xid, &txn_ctx->accounts[i], bank, capture_ctx ); + fd_runtime_save_account( funk, xid, &txn_ctx->accounts.accounts[i], bank, capture_ctx ); } /* We need to queue any existing program accounts that may have @@ -965,8 +971,8 @@ fd_runtime_finalize_txn( fd_funk_t * funk, cache since their programdata may have changed. ELF / sBPF metadata will need to be updated. */ ulong current_slot = fd_bank_slot_get( bank ); - for( uchar i=0; iprograms_to_reverify_cnt; i++ ) { - fd_pubkey_t const * program_key = &txn_ctx->programs_to_reverify[i]; + for( uchar i=0; idetails.programs_to_reverify_cnt; i++ ) { + fd_pubkey_t const * program_key = &txn_ctx->details.programs_to_reverify[i]; fd_progcache_invalidate( progcache, xid, program_key, current_slot ); } } @@ -976,31 +982,32 @@ fd_runtime_finalize_txn( fd_funk_t * funk, ulong * nonvote_txn_count = fd_bank_nonvote_txn_count_modify( bank ); FD_ATOMIC_FETCH_AND_ADD(nonvote_txn_count, 1); - if( FD_UNLIKELY( txn_ctx->exec_err ) ){ + if( FD_UNLIKELY( txn_ctx->err.exec_err ) ) { ulong * nonvote_failed_txn_count = fd_bank_nonvote_failed_txn_count_modify( bank ); FD_ATOMIC_FETCH_AND_ADD( nonvote_failed_txn_count, 1 ); } } - if( FD_UNLIKELY( txn_ctx->exec_err ) ){ + if( FD_UNLIKELY( txn_ctx->err.exec_err ) ) { ulong * failed_txn_count = fd_bank_failed_txn_count_modify( bank ); FD_ATOMIC_FETCH_AND_ADD( failed_txn_count, 1 ); } ulong * total_compute_units_used = fd_bank_total_compute_units_used_modify( bank ); - FD_ATOMIC_FETCH_AND_ADD( total_compute_units_used, txn_ctx->compute_budget_details.compute_unit_limit - txn_ctx->compute_budget_details.compute_meter ); + FD_ATOMIC_FETCH_AND_ADD( total_compute_units_used, txn_ctx->details.compute_budget.compute_unit_limit - txn_ctx->details.compute_budget.compute_meter ); /* Update the cost tracker */ fd_cost_tracker_t * cost_tracker = fd_bank_cost_tracker_locking_modify( bank ); int res = fd_cost_tracker_calculate_cost_and_add( cost_tracker, txn_ctx ); if( FD_UNLIKELY( res!=FD_COST_TRACKER_SUCCESS ) ) { - txn_ctx->flags = 0U; + FD_LOG_DEBUG(( "fd_runtime_finalize_txn: transaction failed to fit into block %d", res )); + txn_ctx->err.is_committable = 0; } fd_bank_cost_tracker_end_locking_modify( bank ); - txn_ctx->loaded_accounts_data_size_cost = fd_cost_tracker_calculate_loaded_accounts_data_size_cost( txn_ctx ); + txn_ctx->details.loaded_accounts_data_size_cost = fd_cost_tracker_calculate_loaded_accounts_data_size_cost( txn_ctx ); - if( FD_LIKELY( txncache && txn_ctx->nonce_account_idx_in_txn==ULONG_MAX ) ) { + if( FD_LIKELY( txncache && txn_ctx->accounts.nonce_idx_in_txn==ULONG_MAX ) ) { /* In Agave, durable nonce transactions are inserted to the status cache the same as any others, but this is only to serve RPC requests, they do not need to be in there for correctness as the @@ -1008,13 +1015,12 @@ fd_runtime_finalize_txn( fd_funk_t * funk, entirely to simplify and improve performance of the txn cache. */ fd_hash_t * blockhash = (fd_hash_t *)((uchar *)txn_ctx->txn.payload + TXN( &txn_ctx->txn )->recent_blockhash_off); - fd_txncache_insert( txncache, bank->txncache_fork_id, blockhash->uc, txn_ctx->blake_txn_msg_hash.uc ); + fd_txncache_insert( txncache, bank->txncache_fork_id, blockhash->uc, txn_ctx->details.blake_txn_msg_hash.uc ); } } int -fd_runtime_prepare_and_execute_txn( fd_banks_t * banks, - ulong bank_idx, +fd_runtime_prepare_and_execute_txn( fd_bank_t * bank, fd_exec_txn_ctx_t * txn_ctx, fd_txn_p_t * txn, fd_capture_ctx_t * capture_ctx, @@ -1022,51 +1028,55 @@ fd_runtime_prepare_and_execute_txn( fd_banks_t * banks, fd_exec_accounts_t * exec_accounts, uchar * dumping_mem, uchar * tracing_mem ) { - int exec_res = 0; - - fd_bank_t * bank = fd_banks_bank_query( banks, bank_idx ); - if( FD_UNLIKELY( !bank ) ) { - FD_LOG_CRIT(( "Could not get bank at pool idx %lu", bank_idx )); - } - ulong slot = fd_bank_slot_get( bank ); - - /* Setup and execute the transaction. */ txn_ctx->bank = bank; - txn_ctx->slot = fd_bank_slot_get( bank ); - txn_ctx->bank_idx = bank_idx; - txn_ctx->features = fd_bank_features_get( bank ); - txn_ctx->enable_exec_recording = !!( bank->flags & FD_BANK_FLAGS_EXEC_RECORDING ); - txn_ctx->xid[0] = (fd_funk_txn_xid_t){ .ul = { slot, bank_idx } }; + txn_ctx->xid[0] = (fd_funk_txn_xid_t){ .ul = { fd_bank_slot_get( bank ), bank->idx } }; txn_ctx->txn = *txn; txn_ctx->exec_stack = exec_stack; txn_ctx->exec_accounts = exec_accounts; - txn_ctx->dumping_mem = dumping_mem; - txn_ctx->tracing_mem = tracing_mem; - txn_ctx->flags = FD_TXN_P_FLAGS_SANITIZE_SUCCESS; - fd_exec_txn_ctx_setup_basic( txn_ctx ); - txn_ctx->capture_ctx = capture_ctx; - - /* Set up the core account keys. These are the account keys directly - passed in via the serialized transaction, represented as an array. - Note that this does not include additional keys referenced in - address lookup tables. */ - fd_executor_setup_txn_account_keys( txn_ctx ); - - /* Pre-execution checks */ - exec_res = fd_runtime_pre_execute_check( txn_ctx ); - if( FD_UNLIKELY( !( txn_ctx->flags & FD_TXN_P_FLAGS_SANITIZE_SUCCESS ) ) ) { - return exec_res; - } - /* Execute the transaction. Note that fees-only transactions are still - marked as "executed". */ - txn_ctx->flags |= FD_TXN_P_FLAGS_EXECUTE_SUCCESS; - if( FD_LIKELY( !( txn_ctx->flags & FD_TXN_P_FLAGS_FEES_ONLY ) ) ) { - exec_res = fd_execute_txn( txn_ctx ); + txn_ctx->accounts.accounts_cnt = 0UL; + txn_ctx->accounts.executable_cnt = 0UL; + + txn_ctx->details.programs_to_reverify_cnt = 0UL; + txn_ctx->details.loaded_accounts_data_size = 0UL; + txn_ctx->details.loaded_accounts_data_size_cost = 0UL; + txn_ctx->details.accounts_resize_delta = 0UL; + txn_ctx->details.return_data.len = 0UL; + memset( txn_ctx->details.return_data.program_id.key, 0, sizeof(fd_pubkey_t) ); + fd_compute_budget_details_new( &txn_ctx->details.compute_budget ); + + txn_ctx->log.enable_exec_recording = !!( bank->flags & FD_BANK_FLAGS_EXEC_RECORDING ); + txn_ctx->log.dumping_mem = dumping_mem; + txn_ctx->log.tracing_mem = tracing_mem; + txn_ctx->log.capture_ctx = capture_ctx; + + txn_ctx->instr.info_cnt = 0UL; + txn_ctx->instr.trace_length = 0UL; + txn_ctx->instr.current_idx = 0; + txn_ctx->instr.stack_sz = 0; + + txn_ctx->accounts.accounts_cnt = 0UL; + txn_ctx->accounts.executable_cnt = 0UL; + + txn_ctx->err.is_committable = 1; + txn_ctx->err.is_fees_only = 0; + txn_ctx->err.txn_err = FD_RUNTIME_EXECUTE_SUCCESS; + txn_ctx->err.exec_err = FD_EXECUTOR_INSTR_SUCCESS; + txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE; + txn_ctx->err.exec_err_idx = INT_MAX; + txn_ctx->err.custom_err = 0; + + /* Transaction sanitization. If a transaction can't be commited or is + fees-only, we return early. */ + txn_ctx->err.txn_err = fd_runtime_pre_execute_check( txn_ctx ); + + /* Execute the transaction. */ + if( FD_LIKELY( txn_ctx->err.is_committable && !txn_ctx->err.is_fees_only ) ) { + txn_ctx->err.txn_err = fd_execute_txn( txn_ctx ); } - return exec_res; + return txn_ctx->err.txn_err; } /* fd_executor_txn_verify and fd_runtime_pre_execute_check are responisble @@ -1162,7 +1172,7 @@ fd_apply_builtin_program_feature_transitions( fd_bank_t * bank, fd_builtin_program_t const * builtins = fd_builtins(); for( ulong i=0UL; ienable_feature_offset ) ) { + if( builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( bank ), fd_bank_features_query( bank ), builtins[i].core_bpf_migration_config->enable_feature_offset ) ) { FD_LOG_DEBUG(( "Migrating builtin program %s to core BPF", FD_BASE58_ENC_32_ALLOCA( builtins[i].pubkey->key ) )); fd_migrate_builtin_to_core_bpf( bank, accdb, xid, runtime_stack, builtins[i].core_bpf_migration_config, capture_ctx ); } @@ -1176,7 +1186,7 @@ fd_apply_builtin_program_feature_transitions( fd_bank_t * bank, /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank.rs#L6776-L6793 */ fd_stateless_builtin_program_t const * stateless_builtins = fd_stateless_builtins(); for( ulong i=0UL; ienable_feature_offset ) ) { + if( stateless_builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( bank ), fd_bank_features_query( bank ), stateless_builtins[i].core_bpf_migration_config->enable_feature_offset ) ) { FD_LOG_DEBUG(( "Migrating stateless builtin program %s to core BPF", FD_BASE58_ENC_32_ALLOCA( stateless_builtins[i].pubkey->key ) )); fd_migrate_builtin_to_core_bpf( bank, accdb, xid, runtime_stack, stateless_builtins[i].core_bpf_migration_config, capture_ctx ); } diff --git a/src/flamenco/runtime/fd_runtime.h b/src/flamenco/runtime/fd_runtime.h index 838ef31ba25..6bd644b00db 100644 --- a/src/flamenco/runtime/fd_runtime.h +++ b/src/flamenco/runtime/fd_runtime.h @@ -318,8 +318,7 @@ fd_runtime_pre_execute_check( fd_exec_txn_ctx_t * txn_ctx ); transaction. */ int -fd_runtime_prepare_and_execute_txn( fd_banks_t * banks, - ulong bank_idx, +fd_runtime_prepare_and_execute_txn( fd_bank_t * bank, fd_exec_txn_ctx_t * txn_ctx, fd_txn_p_t * txn, fd_capture_ctx_t * capture_ctx, diff --git a/src/flamenco/runtime/info/fd_instr_info.c b/src/flamenco/runtime/info/fd_instr_info.c index 42336a6e02d..e27ad6c0ef5 100644 --- a/src/flamenco/runtime/info/fd_instr_info.c +++ b/src/flamenco/runtime/info/fd_instr_info.c @@ -8,7 +8,7 @@ fd_instr_info_accumulate_starting_lamports( fd_instr_info_t * instr, ushort idx_in_callee, ushort idx_in_txn ) { if( FD_LIKELY( !instr->is_duplicate[ idx_in_callee ] ) ) { - fd_txn_account_t const * account = &txn_ctx->accounts[ idx_in_txn ]; + fd_txn_account_t const * account = &txn_ctx->accounts.accounts[ idx_in_txn ]; if( fd_txn_account_get_meta( account ) ) { fd_uwide_inc( &instr->starting_lamports_h, &instr->starting_lamports_l, @@ -28,17 +28,17 @@ fd_instr_info_init_from_txn_instr( fd_instr_info_t * instr, instr->program_id = txn_instr->program_id; - /* See note in fd_instr_info.h. TLDR capping this value at 256 should have - literally 0 effect on program execution, down to the error codes. This - is purely for the sake of not increasing the overall memory footprint of the - transaction context. If this change causes issues, we may need to increase - the array sizes in the instr info. */ + /* See note in fd_instr_info.h. TLDR: capping this value at 256 + should have literally 0 effect on program execution, down to the + error codes. This is purely for the sake of not increasing the + overall memory footprint of the transaction context. If this + change causes issues, we may need to increase the array sizes in + the instr info. */ instr->acct_cnt = fd_ushort_min( txn_instr->acct_cnt, FD_INSTR_ACCT_MAX ); instr->data_sz = txn_instr->data_sz; instr->data = (uchar *)txn_ctx->txn.payload + txn_instr->data_off; - uchar acc_idx_seen[ FD_INSTR_ACCT_MAX ]; - memset(acc_idx_seen, 0, FD_INSTR_ACCT_MAX); + uchar acc_idx_seen[ FD_INSTR_ACCT_MAX ] = {0}; for( ushort i=0; iacct_cnt; i++ ) { ushort acc_idx = instr_acc_idxs[i]; @@ -63,7 +63,7 @@ fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr, *total_lamports_l = 0UL; for( ulong i=0UL; iacct_cnt; ++i ) { ushort idx_in_txn = instr->accounts[i].index_in_transaction; - fd_txn_account_t const * account = &txn_ctx->accounts[ idx_in_txn ]; + fd_txn_account_t const * account = &txn_ctx->accounts.accounts[ idx_in_txn ]; if( !fd_txn_account_get_meta( account ) || instr->is_duplicate[i] ) { 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 04b994db517..f0fadf2f1a3 100644 --- a/src/flamenco/runtime/program/fd_address_lookup_table_program.c +++ b/src/flamenco/runtime/program/fd_address_lookup_table_program.c @@ -289,7 +289,7 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx, seeds[0] = (uchar const *)authority_key; seeds[1] = (uchar const *)&derivation_slot; err = fd_pubkey_derive_pda( &fd_solana_address_lookup_table_program_id, 2UL, seeds, - seed_szs, (uchar*)&create->bump_seed, derived_tbl_key, &ctx->txn_ctx->custom_err ); + seed_szs, (uchar*)&create->bump_seed, derived_tbl_key, &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( err ) ) { return err; } diff --git a/src/flamenco/runtime/program/fd_bpf_loader_program.c b/src/flamenco/runtime/program/fd_bpf_loader_program.c index e5a09ba823c..74efea54f7e 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_program.c +++ b/src/flamenco/runtime/program/fd_bpf_loader_program.c @@ -139,13 +139,13 @@ fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, } fd_vm_syscall_register_slot( syscalls, - instr_ctx->txn_ctx->slot, - &instr_ctx->txn_ctx->features, + fd_bank_slot_get( instr_ctx->txn_ctx->bank ), + fd_bank_features_query( instr_ctx->txn_ctx->bank ), 1 ); /* Load executable */ fd_sbpf_elf_info_t elf_info[ 1UL ]; - fd_prog_versions_t versions = fd_prog_versions( &instr_ctx->txn_ctx->features, instr_ctx->txn_ctx->slot ); + fd_prog_versions_t versions = fd_prog_versions( fd_bank_features_query( instr_ctx->txn_ctx->bank ), fd_bank_slot_get( instr_ctx->txn_ctx->bank ) ); fd_sbpf_loader_config_t config = { 0 }; config.elf_deploy_checks = deploy_mode; @@ -184,8 +184,8 @@ fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, vm = fd_vm_init( /* vm */ vm, /* instr_ctx */ instr_ctx, - /* heap_max */ instr_ctx->txn_ctx->compute_budget_details.heap_size, - /* entry_cu */ instr_ctx->txn_ctx->compute_budget_details.compute_meter, + /* heap_max */ instr_ctx->txn_ctx->details.compute_budget.heap_size, + /* entry_cu */ instr_ctx->txn_ctx->details.compute_budget.compute_meter, /* rodata */ prog->rodata, /* rodata_sz */ prog->rodata_sz, /* text */ prog->text, @@ -216,7 +216,7 @@ fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx, } /* Queue the program for reverification */ - instr_ctx->txn_ctx->programs_to_reverify[instr_ctx->txn_ctx->programs_to_reverify_cnt++] = *program_key; + instr_ctx->txn_ctx->details.programs_to_reverify[instr_ctx->txn_ctx->details.programs_to_reverify_cnt++] = *program_key; return FD_EXECUTOR_INSTR_SUCCESS; } @@ -386,8 +386,8 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, /* TODO do we really need to re-do this on every instruction? */ fd_vm_syscall_register_slot( syscalls, - instr_ctx->txn_ctx->slot, - &instr_ctx->txn_ctx->features, + fd_bank_slot_get( instr_ctx->txn_ctx->bank ), + fd_bank_features_query( instr_ctx->txn_ctx->bank ), 0 ); /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/programs/bpf_loader/src/lib.rs#L1362-L1368 */ @@ -417,8 +417,8 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, fd_vm_t _vm[1]; fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) ); - ulong pre_insn_cus = instr_ctx->txn_ctx->compute_budget_details.compute_meter; - ulong heap_size = instr_ctx->txn_ctx->compute_budget_details.heap_size; + ulong pre_insn_cus = instr_ctx->txn_ctx->details.compute_budget.compute_meter; + ulong heap_size = instr_ctx->txn_ctx->details.compute_budget.heap_size; /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/lib.rs#L275-L278 */ ulong heap_cost = calculate_heap_cost( heap_size, FD_VM_HEAP_COST ); @@ -428,16 +428,16 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, } /* For dumping syscalls for seed corpora */ - int dump_syscall_to_pb = instr_ctx->txn_ctx->capture_ctx && - instr_ctx->txn_ctx->slot >= instr_ctx->txn_ctx->capture_ctx->dump_proto_start_slot && - instr_ctx->txn_ctx->capture_ctx->dump_syscall_to_pb; + int dump_syscall_to_pb = instr_ctx->txn_ctx->log.capture_ctx && + fd_bank_slot_get( instr_ctx->txn_ctx->bank ) >= instr_ctx->txn_ctx->log.capture_ctx->dump_proto_start_slot && + instr_ctx->txn_ctx->log.capture_ctx->dump_syscall_to_pb; /* TODO: (topointon): correctly set check_size in vm setup */ vm = fd_vm_init( /* vm */ vm, /* instr_ctx */ instr_ctx, /* heap_max */ heap_size, - /* entry_cu */ instr_ctx->txn_ctx->compute_budget_details.compute_meter, + /* entry_cu */ instr_ctx->txn_ctx->details.compute_budget.compute_meter, /* rodata */ fd_progcache_rec_rodata( cache_entry ), /* rodata_sz */ cache_entry->rodata_sz, /* text (note: text_off is byte offset) */ (ulong *)((ulong)fd_progcache_rec_rodata( cache_entry ) + (ulong)cache_entry->text_off), @@ -466,13 +466,13 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, return FD_EXECUTOR_INSTR_ERR_PROGRAM_ENVIRONMENT_SETUP_FAILURE; } - if( FD_UNLIKELY( instr_ctx->txn_ctx->enable_vm_tracing && instr_ctx->txn_ctx->tracing_mem ) ) { - vm->trace = fd_vm_trace_join( fd_vm_trace_new( instr_ctx->txn_ctx->tracing_mem + ((instr_ctx->txn_ctx->instr_stack_sz-1UL) * FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT), FD_RUNTIME_VM_TRACE_EVENT_MAX, FD_RUNTIME_VM_TRACE_EVENT_DATA_MAX )); + if( FD_UNLIKELY( instr_ctx->txn_ctx->log.enable_vm_tracing && instr_ctx->txn_ctx->log.tracing_mem ) ) { + vm->trace = fd_vm_trace_join( fd_vm_trace_new( instr_ctx->txn_ctx->log.tracing_mem + ((instr_ctx->txn_ctx->instr.stack_sz-1UL) * FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT), FD_RUNTIME_VM_TRACE_EVENT_MAX, FD_RUNTIME_VM_TRACE_EVENT_DATA_MAX )); if( FD_UNLIKELY( !vm->trace ) ) FD_LOG_ERR(( "unable to create trace; make sure you've compiled with sufficient spad size " )); } int exec_err = fd_vm_exec( vm ); - instr_ctx->txn_ctx->compute_budget_details.compute_meter = vm->cu; + instr_ctx->txn_ctx->details.compute_budget.compute_meter = vm->cu; if( FD_UNLIKELY( vm->trace ) ) { err = fd_vm_trace_printf( vm->trace, vm->syscalls ); @@ -484,7 +484,7 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, /* Log consumed compute units and return data. https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/lib.rs#L1418-L1429 */ fd_log_collector_program_consumed( instr_ctx, pre_insn_cus-vm->cu, pre_insn_cus ); - if( FD_UNLIKELY( instr_ctx->txn_ctx->return_data.len ) ) { + if( FD_UNLIKELY( instr_ctx->txn_ctx->details.return_data.len ) ) { fd_log_collector_program_return( instr_ctx ); } @@ -497,7 +497,7 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, if( FD_LIKELY( !exec_err ) ) { ulong status = vm->reg[0]; if( FD_UNLIKELY( status ) ) { - err = program_error_to_instr_error( status, &instr_ctx->txn_ctx->custom_err ); + err = program_error_to_instr_error( status, &instr_ctx->txn_ctx->err.custom_err ); FD_VM_PREPARE_ERR_OVERWRITE( vm ); FD_VM_ERR_FOR_LOG_INSTR( vm, err ); return err; @@ -507,7 +507,7 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, /* (SIMD-182) Consume ALL requested CUs on non-Syscall errors */ if( FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, deplete_cu_meter_on_vm_failure ) && exec_err!=FD_VM_ERR_EBPF_SYSCALL_ERROR ) { - instr_ctx->txn_ctx->compute_budget_details.compute_meter = 0UL; + instr_ctx->txn_ctx->details.compute_budget.compute_meter = 0UL; } /* Direct mapping access violation case @@ -516,7 +516,7 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, as to what caused the error. https://github.com/anza-xyz/agave/blob/v3.0.4/programs/bpf_loader/src/lib.rs#L1556-L1618 */ if( FD_UNLIKELY( stricter_abi_and_runtime_constraints && - ( exec_err==FD_VM_ERR_EBPF_ACCESS_VIOLATION || instr_ctx->txn_ctx->exec_err==FD_VM_ERR_EBPF_ACCESS_VIOLATION ) && + ( exec_err==FD_VM_ERR_EBPF_ACCESS_VIOLATION || instr_ctx->txn_ctx->err.exec_err==FD_VM_ERR_EBPF_ACCESS_VIOLATION ) && vm->segv_vaddr!=ULONG_MAX ) ) { /* vaddrs start at 0xFFFFFFFF + 1, so anything below it would not correspond to any account metadata. */ @@ -584,8 +584,8 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, and our design decisions for making our error codes match. */ /* Instr error case. Set the error kind and return the instruction error */ - if( instr_ctx->txn_ctx->exec_err_kind==FD_EXECUTOR_ERR_KIND_INSTR ) { - err = instr_ctx->txn_ctx->exec_err; + if( instr_ctx->txn_ctx->err.exec_err_kind==FD_EXECUTOR_ERR_KIND_INSTR ) { + err = instr_ctx->txn_ctx->err.exec_err; FD_VM_PREPARE_ERR_OVERWRITE( vm ); FD_VM_ERR_FOR_LOG_INSTR( vm, err ); return err; @@ -593,8 +593,8 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, /* Syscall error case. The VM would have also set the syscall error code in the txn_ctx exec_err. */ - if( instr_ctx->txn_ctx->exec_err_kind==FD_EXECUTOR_ERR_KIND_SYSCALL ) { - err = instr_ctx->txn_ctx->exec_err; + if( instr_ctx->txn_ctx->err.exec_err_kind==FD_EXECUTOR_ERR_KIND_SYSCALL ) { + err = instr_ctx->txn_ctx->err.exec_err; FD_VM_PREPARE_ERR_OVERWRITE( vm ); FD_VM_ERR_FOR_LOG_SYSCALL( vm, err ); return FD_EXECUTOR_INSTR_ERR_PROGRAM_FAILED_TO_COMPLETE; @@ -602,8 +602,8 @@ fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx, /* An access violation that takes place inside a syscall will cause `exec_res` to be set to EbpfError::SyscallError, - but the `txn_ctx->exec_err_kind` will be set to EBPF and - `txn_ctx->exec_err` will be set to the EBPF error. In this + 'but the `txn_ctx->err.exec_err_kind` will be set to EBPF and + `txn_ctx->err.exec_err` will be set to the EBPF error. In this specific case, there is nothing to do since the error and error kind area already set correctly. Otherwise, we need to log the EBPF error. */ @@ -1172,7 +1172,7 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { ulong seed_sz = sizeof(fd_pubkey_t); uchar bump_seed = 0; err = fd_pubkey_find_program_address( program_id, 1UL, seeds, &seed_sz, derived_address, - &bump_seed, &instr_ctx->txn_ctx->custom_err ); + &bump_seed, &instr_ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( err ) ) { /* TODO: We should handle these errors more gracefully instead of just killing the client (e.g. excluding the transaction from the block). */ @@ -1244,7 +1244,7 @@ process_loader_upgradeable_instruction( fd_exec_instr_ctx_t * instr_ctx ) { /* caller_program_id == program_id */ fd_pubkey_t signers[ 1UL ]; - err = fd_pubkey_derive_pda( program_id, 1UL, seeds, &seed_sz, &bump_seed, signers, &instr_ctx->txn_ctx->custom_err ); + err = fd_pubkey_derive_pda( program_id, 1UL, seeds, &seed_sz, &bump_seed, signers, &instr_ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( err ) ) { return err; } @@ -2559,7 +2559,7 @@ fd_bpf_loader_program_execute( fd_exec_instr_ctx_t * ctx ) { } ulong program_data_slot = program_data_account_state->inner.program_data.slot; - if( FD_UNLIKELY( program_data_slot>=ctx->txn_ctx->slot ) ) { + if( FD_UNLIKELY( program_data_slot>=fd_bank_slot_get( ctx->txn_ctx->bank ) ) ) { /* The account was likely just deployed or upgraded. Corresponds to 'LoadedProgramType::DelayVisibility' */ fd_log_collector_msg_literal( ctx, "Program is not deployed" ); @@ -2612,26 +2612,45 @@ fd_directly_invoke_loader_v3_deploy( fd_bank_t * bank, fd_pubkey_t const * program_key, uchar const * elf, ulong elf_sz ) { - /* FIXME: Breaking this until exec spad is replaced. */ FD_LOG_ERR(( "fd_directly_invoke_loader_v3_deploy is not implemented" )); - return 0; - /* Set up a dummy instr and txn context */ + /* Set up a dummy instr and txn context. + FIXME: Memory for a txn context needs to be allocated */ fd_exec_txn_ctx_t * txn_ctx = fd_exec_txn_ctx_join( fd_exec_txn_ctx_new( NULL ) ); - fd_exec_txn_ctx_setup( bank, - accdb_shfunk, - NULL, - xid, - NULL, - txn_ctx, - NULL, - NULL, - 0UL ); - - fd_exec_txn_ctx_setup_basic( txn_ctx ); - txn_ctx->instr_stack_sz = 1; - fd_exec_instr_ctx_t * instr_ctx = &txn_ctx->instr_stack[0]; + if( FD_UNLIKELY( !fd_funk_join( txn_ctx->funk, accdb_shfunk ) ) ) { + FD_LOG_CRIT(( "fd_funk_join(accdb) failed" )); + } + txn_ctx->xid[0] = *xid; + txn_ctx->progcache = NULL; + txn_ctx->status_cache = NULL; + txn_ctx->bank_hash_cmp = NULL; + txn_ctx->log.enable_exec_recording = !!(bank->flags & FD_BANK_FLAGS_EXEC_RECORDING); + txn_ctx->bank = bank; + + fd_compute_budget_details_new( &txn_ctx->details.compute_budget ); + txn_ctx->accounts.accounts_cnt = 0UL; + txn_ctx->accounts.executable_cnt = 0UL; + + txn_ctx->details.programs_to_reverify_cnt = 0UL; + txn_ctx->details.loaded_accounts_data_size = 0UL; + txn_ctx->details.loaded_accounts_data_size_cost = 0UL; + txn_ctx->details.accounts_resize_delta = 0UL; + + memset( txn_ctx->details.return_data.program_id.key, 0, sizeof(fd_pubkey_t) ); + txn_ctx->details.return_data.len = 0; + + txn_ctx->log.capture_ctx = NULL; + + txn_ctx->instr.info_cnt = 0UL; + txn_ctx->instr.trace_length = 0UL; + + txn_ctx->err.exec_err = 0; + txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE; + txn_ctx->instr.current_idx = 0; + + txn_ctx->instr.stack_sz = 1; + fd_exec_instr_ctx_t * instr_ctx = &txn_ctx->instr.stack[0]; *instr_ctx = (fd_exec_instr_ctx_t) { .instr = NULL, .txn_ctx = txn_ctx, diff --git a/src/flamenco/runtime/program/fd_bpf_loader_serialization.c b/src/flamenco/runtime/program/fd_bpf_loader_serialization.c index f7df2eabff7..1e03d4444eb 100644 --- a/src/flamenco/runtime/program/fd_bpf_loader_serialization.c +++ b/src/flamenco/runtime/program/fd_bpf_loader_serialization.c @@ -264,7 +264,7 @@ fd_bpf_loader_input_serialize_aligned( fd_exec_instr_ctx_t * ctx, fd_vm_acc_region_meta_t * acc_region_metas, int stricter_abi_and_runtime_constraints, int direct_mapping ) { - fd_pubkey_t * txn_accs = ctx->txn_ctx->account_keys; + fd_pubkey_t * txn_accs = ctx->txn_ctx->accounts.account_keys; uchar acc_idx_seen[ FD_INSTR_ACCT_MAX ] = {0}; ushort dup_acc_idx[ FD_INSTR_ACCT_MAX ] = {0}; @@ -272,7 +272,7 @@ fd_bpf_loader_input_serialize_aligned( fd_exec_instr_ctx_t * ctx, /* 16-byte aligned buffer: https://github.com/anza-xyz/agave/blob/v3.0.0/program-runtime/src/serialization.rs#L60 */ - uchar * serialized_params = ctx->txn_ctx->exec_stack->bpf_loader_serialization.serialization_mem[ ctx->txn_ctx->instr_stack_sz-1UL ]; + uchar * serialized_params = ctx->txn_ctx->exec_stack->bpf_loader_serialization.serialization_mem[ ctx->txn_ctx->instr.stack_sz-1UL ]; uchar * serialized_params_start = serialized_params; uchar * curr_serialized_params_start = serialized_params; @@ -540,7 +540,7 @@ fd_bpf_loader_input_serialize_unaligned( fd_exec_instr_ctx_t * ctx, fd_vm_acc_region_meta_t * acc_region_metas, int stricter_abi_and_runtime_constraints, int direct_mapping ) { - fd_pubkey_t const * txn_accs = ctx->txn_ctx->account_keys; + fd_pubkey_t const * txn_accs = ctx->txn_ctx->accounts.account_keys; uchar acc_idx_seen[FD_INSTR_ACCT_MAX] = {0}; ushort dup_acc_idx[FD_INSTR_ACCT_MAX] = {0}; @@ -548,7 +548,7 @@ fd_bpf_loader_input_serialize_unaligned( fd_exec_instr_ctx_t * ctx, /* 16-byte aligned buffer: https://github.com/anza-xyz/agave/blob/v2.2.13/programs/bpf_loader/src/serialization.rs#L32 */ - uchar * serialized_params = ctx->txn_ctx->exec_stack->bpf_loader_serialization.serialization_mem[ ctx->txn_ctx->instr_stack_sz-1UL ]; + uchar * serialized_params = ctx->txn_ctx->exec_stack->bpf_loader_serialization.serialization_mem[ ctx->txn_ctx->instr.stack_sz-1UL ]; uchar * serialized_params_start = serialized_params; uchar * curr_serialized_params_start = serialized_params; diff --git a/src/flamenco/runtime/program/fd_builtin_programs.c b/src/flamenco/runtime/program/fd_builtin_programs.c index ce16ce6c92b..fc5c1f1ac65 100644 --- a/src/flamenco/runtime/program/fd_builtin_programs.c +++ b/src/flamenco/runtime/program/fd_builtin_programs.c @@ -286,9 +286,9 @@ fd_builtin_programs_init( fd_bank_t * bank, /** https://github.com/anza-xyz/agave/blob/v2.3.7/runtime/src/bank.rs#L4949 */ if( fd_bank_slot_get( bank )==0UL && builtins[i].enable_feature_offset==NO_ENABLE_FEATURE_ID && !fd_builtin_is_bpf( accdb->funk, xid, builtins[i].pubkey ) ) { fd_write_builtin_account( bank, accdb, xid, capture_ctx, *builtins[i].pubkey, builtins[i].data, strlen( builtins[i].data ) ); - } else if( builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( bank ), fd_bank_features_get( bank ), builtins[i].core_bpf_migration_config->enable_feature_offset ) ) { + } else if( builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( bank ), fd_bank_features_query( bank ), builtins[i].core_bpf_migration_config->enable_feature_offset ) ) { continue; - } else if( builtins[i].enable_feature_offset!=NO_ENABLE_FEATURE_ID && !FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( bank ), fd_bank_features_get( bank ), builtins[i].enable_feature_offset ) ) { + } else if( builtins[i].enable_feature_offset!=NO_ENABLE_FEATURE_ID && !FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( bank ), fd_bank_features_query( bank ), builtins[i].enable_feature_offset ) ) { continue; } else { fd_write_builtin_account( bank, accdb, xid, capture_ctx, *builtins[i].pubkey, builtins[i].data, strlen(builtins[i].data) ); @@ -353,7 +353,7 @@ fd_is_migrating_builtin_program( fd_exec_txn_ctx_t const * txn_ctx, fd_core_bpf_migration_config_t const * config = migrating_builtins[i]; if( !memcmp( pubkey->uc, config->builtin_program_id->key, sizeof(fd_pubkey_t) ) ) { if( config->enable_feature_offset!=NO_ENABLE_FEATURE_ID && - FD_FEATURE_ACTIVE_OFFSET( txn_ctx->slot, txn_ctx->features, config->enable_feature_offset ) ) { + FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( txn_ctx->bank ), fd_bank_features_query( txn_ctx->bank ), config->enable_feature_offset ) ) { /* The program has been migrated to BPF. */ *migrated_yet = 1; } diff --git a/src/flamenco/runtime/program/fd_compute_budget_program.c b/src/flamenco/runtime/program/fd_compute_budget_program.c index dcfd95fbd2a..adbdf3ded43 100644 --- a/src/flamenco/runtime/program/fd_compute_budget_program.c +++ b/src/flamenco/runtime/program/fd_compute_budget_program.c @@ -72,7 +72,7 @@ sanitize_requested_heap_size( ulong bytes ) { int fd_sanitize_compute_unit_limits( fd_exec_txn_ctx_t * ctx ) { - fd_compute_budget_details_t * details = &ctx->compute_budget_details; + fd_compute_budget_details_t * details = &ctx->details.compute_budget; /* https://github.com/anza-xyz/agave/blob/v2.3.1/compute-budget-instruction/src/compute_budget_instruction_details.rs#L106-L119 */ if( details->has_requested_heap_size ) { @@ -114,7 +114,7 @@ fd_sanitize_compute_unit_limits( fd_exec_txn_ctx_t * ctx ) { https://github.com/anza-xyz/agave/blob/v2.3.1/compute-budget-instruction/src/compute_budget_instruction_details.rs#L54-L99 */ int fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx ) { - fd_compute_budget_details_t * details = &ctx->compute_budget_details; + fd_compute_budget_details_t * details = &ctx->details.compute_budget; for( ushort i=0; itxn )->instr_cnt; i++ ) { fd_txn_instr_t const * instr = &TXN( &ctx->txn )->instr[i]; diff --git a/src/flamenco/runtime/program/fd_loader_v4_program.c b/src/flamenco/runtime/program/fd_loader_v4_program.c index 9cbc1219240..eb83632ad68 100644 --- a/src/flamenco/runtime/program/fd_loader_v4_program.c +++ b/src/flamenco/runtime/program/fd_loader_v4_program.c @@ -902,7 +902,7 @@ fd_loader_v4_program_execute( fd_exec_instr_ctx_t * instr_ctx ) { } /* Handle `DelayedVisibility` case */ - if( FD_UNLIKELY( state->slot>=instr_ctx->txn_ctx->slot ) ) { + if( FD_UNLIKELY( state->slot>=fd_bank_slot_get( instr_ctx->txn_ctx->bank ) ) ) { fd_log_collector_msg_literal( instr_ctx, "Program is not deployed" ); return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID; } diff --git a/src/flamenco/runtime/program/fd_precompiles.c b/src/flamenco/runtime/program/fd_precompiles.c index 09af27641b6..63de6a0d45f 100644 --- a/src/flamenco/runtime/program/fd_precompiles.c +++ b/src/flamenco/runtime/program/fd_precompiles.c @@ -97,10 +97,10 @@ fd_precompile_get_instr_data( fd_exec_instr_ctx_t * ctx, } else { - if( FD_UNLIKELY( index>=ctx->txn_ctx->instr_info_cnt ) ) + if( FD_UNLIKELY( index>=ctx->txn_ctx->instr.info_cnt ) ) return FD_EXECUTOR_PRECOMPILE_ERR_DATA_OFFSET; - fd_instr_info_t const * instr = &ctx->txn_ctx->instr_infos[ index ]; + fd_instr_info_t const * instr = &ctx->txn_ctx->instr.infos[ index ]; data = instr->data; data_sz = instr->data_sz; @@ -136,20 +136,20 @@ fd_precompile_ed25519_verify( fd_exec_instr_ctx_t * ctx ) { if( FD_UNLIKELY( data_sz == 2 && data[0] == 0 ) ) { return FD_EXECUTOR_INSTR_SUCCESS; } - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } ulong sig_cnt = data[0]; if( FD_UNLIKELY( sig_cnt==0 ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L97-L103 */ ulong expected_data_size = sig_cnt * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START; if( FD_UNLIKELY( data_sz < expected_data_size ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -169,7 +169,7 @@ fd_precompile_ed25519_verify( fd_exec_instr_ctx_t * ctx ) { SIGNATURE_SERIALIZED_SIZE, &sig ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -185,7 +185,7 @@ fd_precompile_ed25519_verify( fd_exec_instr_ctx_t * ctx ) { ED25519_PUBKEY_SERIALIZED_SIZE, &pubkey ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -202,14 +202,14 @@ fd_precompile_ed25519_verify( fd_exec_instr_ctx_t * ctx ) { msg_sz, &msg ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L147-L149 */ fd_sha512_t sha[1]; if( FD_UNLIKELY( fd_ed25519_verify( msg, msg_sz, sig, pubkey, sha )!=FD_ED25519_SUCCESS ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } @@ -233,21 +233,21 @@ fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) { if( FD_UNLIKELY( data_sz == 1 && data[0] == 0 ) ) { return FD_EXECUTOR_INSTR_SUCCESS; } - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/sdk/src/secp256k1_instruction.rs#L938-L947 */ ulong sig_cnt = data[0]; if( FD_UNLIKELY( sig_cnt==0 && data_sz>1 ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L948-L953 */ ulong expected_data_size = sig_cnt * SECP256K1_SIGNATURE_OFFSETS_SERIALIZED_SIZE + SECP256K1_SIGNATURE_OFFSETS_START; if( FD_UNLIKELY( data_sz < expected_data_size ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -269,7 +269,7 @@ fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) { SIGNATURE_SERIALIZED_SIZE + 1, /* extra byte is recovery id */ &sig ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -286,7 +286,7 @@ fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) { SECP256K1_PUBKEY_SERIALIZED_SIZE, ð_address ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -299,7 +299,7 @@ fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) { msg_sz, &msg ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -310,7 +310,7 @@ fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) { /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L1003-L1008 */ uchar pubkey[64]; if ( FD_UNLIKELY( fd_secp256k1_recover( pubkey, msg_hash, sig, recovery_id ) == NULL ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -319,7 +319,7 @@ fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) { fd_keccak256_hash( pubkey, 64, pubkey_hash ); if( FD_UNLIKELY( memcmp( eth_address, pubkey_hash+(FD_KECCAK256_HASH_SZ-SECP256K1_PUBKEY_SERIALIZED_SIZE), SECP256K1_PUBKEY_SERIALIZED_SIZE ) ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } @@ -343,26 +343,26 @@ fd_precompile_secp256r1_verify( fd_exec_instr_ctx_t * ctx ) { /* ... */ if( FD_UNLIKELY( data_sz < DATA_START ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } ulong sig_cnt = data[0]; if( FD_UNLIKELY( sig_cnt==0UL ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* https://github.com/anza-xyz/agave/blob/v2.3.1/precompiles/src/secp256r1.rs#L30 */ if( FD_UNLIKELY( sig_cnt>8UL ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* ... */ ulong expected_data_size = sig_cnt * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START; if( FD_UNLIKELY( data_sz < expected_data_size ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -379,7 +379,7 @@ fd_precompile_secp256r1_verify( fd_exec_instr_ctx_t * ctx ) { SIGNATURE_SERIALIZED_SIZE, &sig ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -391,7 +391,7 @@ fd_precompile_secp256r1_verify( fd_exec_instr_ctx_t * ctx ) { SECP256R1_PUBKEY_SERIALIZED_SIZE, &pubkey ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -404,14 +404,14 @@ fd_precompile_secp256r1_verify( fd_exec_instr_ctx_t * ctx ) { msg_sz, &msg ); if( FD_UNLIKELY( err ) ) { - ctx->txn_ctx->custom_err = (uint)err; + ctx->txn_ctx->err.custom_err = (uint)err; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } /* ... */ fd_sha256_t sha[1]; if( FD_UNLIKELY( fd_secp256r1_verify( msg, msg_sz, sig, pubkey, sha )!=FD_SECP256R1_SUCCESS ) ) { - ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; + ctx->txn_ctx->err.custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } diff --git a/src/flamenco/runtime/program/fd_stake_program.c b/src/flamenco/runtime/program/fd_stake_program.c index cb12f0d3c8a..3d1f06c2fee 100644 --- a/src/flamenco/runtime/program/fd_stake_program.c +++ b/src/flamenco/runtime/program/fd_stake_program.c @@ -850,8 +850,8 @@ get_if_mergeable( fd_exec_instr_ctx_t * invoke_context, // not const to int err; int is_some = fd_new_warmup_cooldown_rate_epoch( epoch_schedule, - &invoke_context->txn_ctx->features, - invoke_context->txn_ctx->slot, + fd_bank_features_query( invoke_context->txn_ctx->bank ), + fd_bank_slot_get( invoke_context->txn_ctx->bank ), &new_rate_activation_epoch, &err ); if( FD_UNLIKELY( err ) ) return err; @@ -1169,8 +1169,8 @@ get_stake_status( fd_exec_instr_ctx_t const * invoke_context, int err; int is_some = fd_new_warmup_cooldown_rate_epoch( epoch_schedule, - &invoke_context->txn_ctx->features, - invoke_context->txn_ctx->slot, + fd_bank_features_query( invoke_context->txn_ctx->bank ), + fd_bank_slot_get( invoke_context->txn_ctx->bank ), &new_rate_activation_epoch, &err ); if( FD_UNLIKELY( err ) ) return err; @@ -1215,8 +1215,8 @@ redelegate_stake( fd_exec_instr_ctx_t const * ctx, int err; int is_some = fd_new_warmup_cooldown_rate_epoch( epoch_schedule, - &ctx->txn_ctx->features, - ctx->txn_ctx->slot, + fd_bank_features_query( ctx->txn_ctx->bank ), + fd_bank_slot_get( ctx->txn_ctx->bank ), &new_rate_activation_epoch, &err ); if( FD_UNLIKELY( err ) ) return err; @@ -1402,7 +1402,7 @@ authorize_with_seed( fd_exec_instr_ctx_t const * ctx, stake_authorize, clock, custodian, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); } // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L310 @@ -1454,7 +1454,7 @@ delegate( fd_exec_instr_ctx_t const * ctx, &meta, ctx->txn_ctx, &validated_delegated_info, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; ulong stake_amount = validated_delegated_info.stake_amount; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L340 @@ -1488,7 +1488,7 @@ delegate( fd_exec_instr_ctx_t const * ctx, &meta, ctx->txn_ctx, &validated_delegated_info, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; ulong stake_amount = validated_delegated_info.stake_amount; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L354 @@ -1504,7 +1504,7 @@ delegate( fd_exec_instr_ctx_t const * ctx, &vote_state->inner.current, clock, stake_history, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L358 fd_stake_state_v2_t new_stake_state = { .discriminant = fd_stake_state_v2_enum_stake, @@ -1692,7 +1692,7 @@ split( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L469 if( FD_UNLIKELY( fd_ulong_sat_sub( stake->delegation.stake, lamports ) < minimum_delegation ) ) { - ctx->txn_ctx->custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION; + ctx->txn_ctx->err.custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1707,7 +1707,7 @@ split( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L487 if( FD_UNLIKELY( split_stake_amounttxn_ctx->custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION; + ctx->txn_ctx->err.custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1716,7 +1716,7 @@ split( fd_exec_instr_ctx_t const * ctx, rc = stake_split( stake, remaining_stake_delta, split_stake_amount, - &ctx->txn_ctx->custom_err, + &ctx->txn_ctx->err.custom_err, &split_stake ); if( FD_UNLIKELY( rc ) ) return rc; fd_stake_meta_t split_meta = *meta; @@ -1881,7 +1881,7 @@ merge( fd_exec_instr_ctx_t * ctx, // not const to log clock, stake_history, &stake_merge_kind, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; @@ -1903,7 +1903,7 @@ merge( fd_exec_instr_ctx_t * ctx, // not const to log clock, stake_history, &source_merge_kind, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; fd_stake_state_v2_t merged_state = {0}; @@ -1916,7 +1916,7 @@ merge( fd_exec_instr_ctx_t * ctx, // not const to log clock, &merged_state, &is_some, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; if( is_some ) { // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L608 @@ -2001,7 +2001,7 @@ move_stake_or_lamports_shared_checks( fd_exec_instr_ctx_t * invoke_context, // clock, stake_history, source_merge_kind, - &invoke_context->txn_ctx->custom_err ); + &invoke_context->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L191 @@ -2019,7 +2019,7 @@ move_stake_or_lamports_shared_checks( fd_exec_instr_ctx_t * invoke_context, // clock, stake_history, destination_merge_kind, - &invoke_context->txn_ctx->custom_err ); + &invoke_context->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L206 @@ -2057,7 +2057,7 @@ move_stake(fd_exec_instr_ctx_t * ctx, // not const to log stake_authority_index, &source_merge_kind, &destination_merge_kind, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L816 @@ -2214,7 +2214,7 @@ move_lamports(fd_exec_instr_ctx_t * ctx, // not const to log stake_authority_index, &source_merge_kind, &destination_merge_kind, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); if( FD_UNLIKELY( rc ) ) return rc; // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L953-L963 @@ -2364,7 +2364,7 @@ withdraw( fd_exec_instr_ctx_t const * ctx, } // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L871 if( FD_UNLIKELY( lockup_is_in_force( &lockup, clock, custodian_pubkey ) ) ) { - ctx->txn_ctx->custom_err = FD_STAKE_ERR_LOCKUP_IN_FORCE; + ctx->txn_ctx->err.custom_err = FD_STAKE_ERR_LOCKUP_IN_FORCE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; }; @@ -2462,7 +2462,7 @@ deactivate_delinquent( fd_exec_instr_ctx_t * ctx, // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L933 if( !acceptable_reference_epoch_credits( reference_vote_state.epoch_credits, current_epoch ) ) { - ctx->txn_ctx->custom_err = FD_STAKE_ERR_INSUFFICIENT_REFERENCE_VOTES; + ctx->txn_ctx->err.custom_err = FD_STAKE_ERR_INSUFFICIENT_REFERENCE_VOTES; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -2585,7 +2585,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { } } if( epoch_rewards_active && instruction->discriminant!=fd_stake_instruction_enum_get_minimum_delegation ) { - ctx->txn_ctx->custom_err = FD_STAKE_ERR_EPOCH_REWARDS_ACTIVE; + ctx->txn_ctx->err.custom_err = FD_STAKE_ERR_EPOCH_REWARDS_ACTIVE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -2662,7 +2662,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { stake_authorize, clock, custodian_pubkey, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); /* implicit drop */ break; @@ -2871,8 +2871,8 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { int err; int is_some = fd_new_warmup_cooldown_rate_epoch( epoch_schedule, - &ctx->txn_ctx->features, - ctx->txn_ctx->slot, + fd_bank_features_query( ctx->txn_ctx->bank ), + fd_bank_slot_get( ctx->txn_ctx->bank ), &new_rate_activation_epoch, &err ); if( FD_UNLIKELY( err ) ) return err; @@ -2915,7 +2915,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L221 - rc = deactivate( &me, clock, signers, &ctx->txn_ctx->custom_err ); + rc = deactivate( &me, clock, signers, &ctx->txn_ctx->err.custom_err ); /* implicit drop */ break; @@ -3041,7 +3041,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { stake_authorize, clock, custodian_pubkey, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); break; } @@ -3146,9 +3146,9 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { */ case fd_stake_instruction_enum_get_minimum_delegation: { ulong minimum_delegation = get_minimum_delegation( ctx->txn_ctx ); - fd_memcpy( &ctx->txn_ctx->return_data.program_id, fd_solana_stake_program_id.key, sizeof(fd_pubkey_t)); - fd_memcpy(ctx->txn_ctx->return_data.data, (uchar*)(&minimum_delegation), sizeof(ulong)); - ctx->txn_ctx->return_data.len = sizeof(ulong); + fd_memcpy( &ctx->txn_ctx->details.return_data.program_id, fd_solana_stake_program_id.key, sizeof(fd_pubkey_t)); + fd_memcpy(ctx->txn_ctx->details.return_data.data, (uchar*)(&minimum_delegation), sizeof(ulong)); + ctx->txn_ctx->details.return_data.len = sizeof(ulong); rc = 0; goto done; } @@ -3175,7 +3175,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR; // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L326 - rc = deactivate_delinquent( ctx, &me, 1, 2, clock->epoch, &ctx->txn_ctx->custom_err ); + rc = deactivate_delinquent( ctx, &me, 1, 2, clock->epoch, &ctx->txn_ctx->err.custom_err ); break; } @@ -3211,7 +3211,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) { lamports, 1UL, 2UL, - &ctx->txn_ctx->custom_err ); + &ctx->txn_ctx->err.custom_err ); break; } diff --git a/src/flamenco/runtime/program/fd_system_program.c b/src/flamenco/runtime/program/fd_system_program.c index e16f127ee86..b1e96c5b704 100644 --- a/src/flamenco/runtime/program/fd_system_program.c +++ b/src/flamenco/runtime/program/fd_system_program.c @@ -45,7 +45,7 @@ verify_seed_address( fd_exec_instr_ctx_t * ctx, "Create: address %s does not match derived address %s", FD_BASE58_ENC_32_ALLOCA( expected ), FD_BASE58_ENC_32_ALLOCA( actual ) ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -81,7 +81,7 @@ fd_system_program_transfer_verified( fd_exec_instr_ctx_t * ctx, if( transfer_amount > fd_borrowed_account_get_lamports( &from ) ) { /* Max msg_sz: 45 - 6 + 20 + 20 = 79 < 127 => we can use printf */ fd_log_collector_printf_dangerous_max_127( ctx, "Transfer: insufficient lamports %lu, need %lu", fd_borrowed_account_get_lamports( &from ), transfer_amount ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -127,7 +127,7 @@ fd_system_program_transfer( fd_exec_instr_ctx_t * ctx, /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */ ushort idx_in_txn = ctx->instr->accounts[ from_acct_idx ].index_in_transaction; fd_log_collector_printf_dangerous_max_127( ctx, - "Transfer: `from` account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->txn_ctx->account_keys[ idx_in_txn ] ) ); + "Transfer: `from` account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->txn_ctx->accounts.account_keys[ idx_in_txn ] ) ); return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE; } @@ -171,7 +171,7 @@ fd_system_program_allocate( fd_exec_instr_ctx_t * ctx, "Allocate: account (account %s, base %s) already in use", FD_BASE58_ENC_32_ALLOCA( &account->acct->pubkey ), base ? FD_BASE58_ENC_32_ALLOCA( base ) : "None" ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -181,7 +181,7 @@ fd_system_program_allocate( fd_exec_instr_ctx_t * ctx, /* Max msg_sz: 48 - 6 + 2*20 = 82 < 127 => we can use printf */ fd_log_collector_printf_dangerous_max_127( ctx, "Allocate: requested %lu, max allowed %lu", space, FD_RUNTIME_ACC_SZ_MAX ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -280,7 +280,7 @@ fd_system_program_create_account( fd_exec_instr_ctx_t * ctx, "Allocate: 'to' (account %s, base %s) already in use", FD_BASE58_ENC_32_ALLOCA( &to.acct->pubkey ), base ? FD_BASE58_ENC_32_ALLOCA( base ) : "None" ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -575,7 +575,7 @@ fd_system_program_exec_transfer_with_seed( fd_exec_instr_ctx_t * /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */ ushort idx_in_txn = ctx->instr->accounts[ from_base_idx ].index_in_transaction; fd_log_collector_printf_dangerous_max_127( ctx, - "Transfer: 'from' account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->txn_ctx->account_keys[ idx_in_txn ] ) ); + "Transfer: 'from' account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->txn_ctx->accounts.account_keys[ idx_in_txn ] ) ); return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE; } @@ -610,7 +610,7 @@ fd_system_program_exec_transfer_with_seed( fd_exec_instr_ctx_t * "Transfer: 'from' address %s does not match derived address %s", FD_BASE58_ENC_32_ALLOCA( from_key ), FD_BASE58_ENC_32_ALLOCA( address_from_seed ) ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } diff --git a/src/flamenco/runtime/program/fd_system_program_nonce.c b/src/flamenco/runtime/program/fd_system_program_nonce.c index f446d498e91..f8742606bc5 100644 --- a/src/flamenco/runtime/program/fd_system_program_nonce.c +++ b/src/flamenco/runtime/program/fd_system_program_nonce.c @@ -67,7 +67,7 @@ most_recent_block_hash( fd_exec_instr_ctx_t * ctx, fd_hash_t const * last_hash = fd_blockhashes_peek_last( blockhashes ); if( FD_UNLIKELY( last_hash==NULL ) ) { // Agave panics if this blockhash was never set at the start of the txn batch - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -194,7 +194,7 @@ fd_system_program_advance_nonce_account( fd_exec_instr_ctx_t * ctx, if( FD_UNLIKELY( 0==memcmp( data->durable_nonce.hash, next_durable_nonce.hash, sizeof(fd_hash_t) ) ) ) { fd_log_collector_msg_literal( ctx, "Advance nonce account: nonce can only advance once per slot" ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_BLOCKHASH_NOT_EXPIRED; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_BLOCKHASH_NOT_EXPIRED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -273,7 +273,7 @@ fd_system_program_exec_advance_nonce_account( fd_exec_instr_ctx_t * ctx ) { } while(0); if( FD_UNLIKELY( bhq_empty ) ) { fd_log_collector_msg_literal( ctx, "Advance nonce account: recent blockhash list is empty" ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -377,7 +377,7 @@ fd_system_program_withdraw_nonce_account( fd_exec_instr_ctx_t * ctx, if( FD_UNLIKELY( 0==memcmp( data->durable_nonce.hash, next_durable_nonce.hash, sizeof(fd_hash_t) ) ) ) { fd_log_collector_msg_literal( ctx, "Withdraw nonce account: nonce can only advance once per slot" ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_BLOCKHASH_NOT_EXPIRED; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_BLOCKHASH_NOT_EXPIRED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -642,7 +642,7 @@ fd_system_program_exec_initialize_nonce_account( fd_exec_instr_ctx_t * ctx, } while(0); if( FD_UNLIKELY( bhq_empty ) ) { fd_log_collector_msg_literal( ctx, "Initialize nonce account: recent blockhash list is empty" ); - ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES; + ctx->txn_ctx->err.custom_err = FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -946,7 +946,7 @@ fd_check_transaction_age( fd_exec_txn_ctx_t * txn_ctx ) { fd_txn_account_t durable_nonce_rec[1]; int err = fd_txn_account_init_from_funk_readonly( durable_nonce_rec, - &txn_ctx->account_keys[ nonce_idx ], + &txn_ctx->accounts.account_keys[ nonce_idx ], txn_ctx->funk, txn_ctx->xid ); if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) { @@ -990,13 +990,13 @@ fd_check_transaction_age( fd_exec_txn_ctx_t * txn_ctx ) { the nonce instruction are signers. This is a successful exit case. */ for( ushort i=0; iacct_cnt; ++i ) { if( fd_txn_is_signer( TXN( &txn_ctx->txn ), (int)instr_accts[i] ) ) { - if( !memcmp( &txn_ctx->account_keys[ instr_accts[i] ], &state->inner.current.inner.initialized.authority, sizeof( fd_pubkey_t ) ) ) { + if( !memcmp( &txn_ctx->accounts.account_keys[ instr_accts[i] ], &state->inner.current.inner.initialized.authority, sizeof(fd_pubkey_t) ) ) { /* Mark nonce account to make sure that we modify and hash the account even if the transaction failed to execute successfully. */ - txn_ctx->nonce_account_idx_in_txn = instr_accts[ 0 ]; + txn_ctx->accounts.nonce_idx_in_txn = instr_accts[ 0 ]; /* Now figure out the state that the nonce account should advance to. @@ -1004,7 +1004,7 @@ fd_check_transaction_age( fd_exec_txn_ctx_t * txn_ctx ) { fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly( txn_ctx->funk, txn_ctx->xid, - &txn_ctx->account_keys[ instr_accts[ 0UL ] ], + &txn_ctx->accounts.account_keys[ instr_accts[ 0UL ] ], NULL, &err, NULL ); @@ -1042,20 +1042,20 @@ fd_check_transaction_age( fd_exec_txn_ctx_t * txn_ctx ) { fd_memcpy( borrowed_account_data, meta, sizeof(fd_account_meta_t)+acc_data_len ); if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new( - txn_ctx->rollback_nonce_account, - &txn_ctx->account_keys[ instr_accts[ 0UL ] ], + txn_ctx->accounts.rollback_nonce, + &txn_ctx->accounts.account_keys[ instr_accts[ 0UL ] ], (fd_account_meta_t *)borrowed_account_data, 1 ) ) ) ) { FD_LOG_CRIT(( "Failed to join txn account" )); } - if( FD_UNLIKELY( fd_nonce_state_versions_size( &new_state )>fd_txn_account_get_data_len( txn_ctx->rollback_nonce_account ) ) ) { + if( FD_UNLIKELY( fd_nonce_state_versions_size( &new_state )>fd_txn_account_get_data_len( txn_ctx->accounts.rollback_nonce ) ) ) { return FD_RUNTIME_TXN_ERR_BLOCKHASH_FAIL_ADVANCE_NONCE_INSTR; } do { fd_bincode_encode_ctx_t encode_ctx = - { .data = fd_txn_account_get_data_mut( txn_ctx->rollback_nonce_account ), - .dataend = fd_txn_account_get_data_mut( txn_ctx->rollback_nonce_account ) + fd_txn_account_get_data_len( txn_ctx->rollback_nonce_account ) }; + { .data = fd_txn_account_get_data_mut( txn_ctx->accounts.rollback_nonce ), + .dataend = fd_txn_account_get_data_mut( txn_ctx->accounts.rollback_nonce ) + fd_txn_account_get_data_len( txn_ctx->accounts.rollback_nonce ) }; int err = fd_nonce_state_versions_encode( &new_state, &encode_ctx ); if( FD_UNLIKELY( err ) ) { return FD_RUNTIME_TXN_ERR_BLOCKHASH_FAIL_ADVANCE_NONCE_INSTR; diff --git a/src/flamenco/runtime/program/fd_vote_program.c b/src/flamenco/runtime/program/fd_vote_program.c index 1fd74459fd3..2144fc06d61 100644 --- a/src/flamenco/runtime/program/fd_vote_program.c +++ b/src/flamenco/runtime/program/fd_vote_program.c @@ -704,7 +704,7 @@ set_new_authorized_voter( fd_vote_state_t * self, // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L786 if( FD_UNLIKELY( authorized_voters_contains( &self->authorized_voters, target_epoch ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -767,7 +767,7 @@ process_timestamp( fd_vote_state_t * self, ( slot == self->last_timestamp.slot && ( slot != self->last_timestamp.slot || timestamp != self->last_timestamp.timestamp ) && self->last_timestamp.slot != 0 ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_TIMESTAMP_TOO_OLD; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_TIMESTAMP_TOO_OLD; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } self->last_timestamp.slot = slot; @@ -867,7 +867,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, fd_exec_instr_ctx_t const * ctx ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L208 if( FD_UNLIKELY( deq_fd_vote_lockout_t_empty( proposed_lockouts ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } fd_landed_vote_t const * last_vote = NULL; @@ -879,7 +879,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, if( FD_LIKELY( last_vote ) ) { if( FD_UNLIKELY( deq_fd_vote_lockout_t_peek_tail_const( proposed_lockouts )->slot <= last_vote->lockout.slot ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_VOTE_TOO_OLD; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_VOTE_TOO_OLD; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } @@ -889,7 +889,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L224 if( FD_UNLIKELY( deq_fd_slot_hash_t_empty( slot_hashes ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -899,7 +899,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, /* Check if the proposed vote is too old to be in the SlotHash history */ // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L230 if( FD_UNLIKELY( last_vote_state_update_slot < earliest_slot_hash_in_history ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_VOTE_TOO_OLD; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_VOTE_TOO_OLD; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -980,7 +980,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, "`proposed_lockouts_index` is positive when checking `SlotsNotOrdered`" ) ) ->slot ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L293 - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L295 @@ -1000,7 +1000,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, /* The vote slot does not exist in the SlotHashes history because it's too old, i.e. older than the oldest slot in the history. */ if( proposed_vote_slot >= earliest_slot_hash_in_history ) { - ctx->txn_ctx->custom_err = 0; + ctx->txn_ctx->err.custom_err = 0; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L310 @@ -1021,7 +1021,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, `proposed_vote_slot < earliest_slot_hash_in_history`, so from 1. we know that `new_proposed_root < earliest_slot_hash_in_history` */ if( new_proposed_root >= earliest_slot_hash_in_history ) { - ctx->txn_ctx->custom_err = 0; + ctx->txn_ctx->err.custom_err = 0; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1043,10 +1043,10 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, which means this vote state update is invalid. */ // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L340 if( has_root_to_check ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ON_DIFFERENT_FORK; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_ROOT_ON_DIFFERENT_FORK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } @@ -1085,7 +1085,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L372 if( proposed_lockouts_index != deq_fd_vote_lockout_t_cnt( proposed_lockouts ) ) { /* The last vote slot in the update did not exist in SlotHashes */ - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1095,7 +1095,7 @@ check_and_filter_proposed_vote_state( fd_vote_state_t * vote_state, sizeof( fd_hash_t ) ) != 0 ) { /* This means the newest vote in the slot has a match that doesn't match the expected hash for that slot on this fork */ - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1162,18 +1162,18 @@ check_slots_are_valid( fd_vote_state_t * vote_state, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L494 if( FD_UNLIKELY( j == deq_fd_slot_hash_t_cnt( slot_hashes ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_VOTE_TOO_OLD; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_VOTE_TOO_OLD; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } if( FD_UNLIKELY( i != vote_slots_len ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L514 if( FD_UNLIKELY( 0 != memcmp( &deq_fd_slot_hash_t_peek_index_const( slot_hashes, j )->hash, vote_hash, 32UL ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } return 0; @@ -1195,7 +1195,7 @@ process_new_vote_state( fd_vote_state_t * vote_state, FD_TEST( !deq_fd_landed_vote_t_empty( new_state ) ); // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L575 if( FD_UNLIKELY( deq_fd_landed_vote_t_cnt( new_state ) > MAX_LOCKOUT_HISTORY ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_TOO_MANY_VOTES; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_TOO_MANY_VOTES; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; }; @@ -1203,12 +1203,12 @@ process_new_vote_state( fd_vote_state_t * vote_state, if( FD_UNLIKELY( has_new_root && vote_state->has_root_slot ) ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L581 if( FD_UNLIKELY( new_root < vote_state->root_slot ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } else if( FD_UNLIKELY( !has_new_root && vote_state->has_root_slot ) ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L586 - ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L588 @@ -1221,29 +1221,29 @@ process_new_vote_state( fd_vote_state_t * vote_state, iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) { fd_landed_vote_t * vote = deq_fd_landed_vote_t_iter_ele( new_state, iter ); if( FD_LIKELY( vote->lockout.confirmation_count == 0 ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_ZERO_CONFIRMATIONS; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_ZERO_CONFIRMATIONS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else if( FD_UNLIKELY( vote->lockout.confirmation_count > MAX_LOCKOUT_HISTORY ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATION_TOO_LARGE; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_CONFIRMATION_TOO_LARGE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else if( FD_LIKELY( has_new_root ) ) { if( FD_UNLIKELY( vote->lockout.slot <= new_root && new_root != SLOT_DEFAULT ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOT_SMALLER_THAN_ROOT; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOT_SMALLER_THAN_ROOT; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } if( FD_LIKELY( previous_vote ) ) { if( FD_UNLIKELY( previous_vote->lockout.slot >= vote->lockout.slot ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else if( FD_UNLIKELY( previous_vote->lockout.confirmation_count <= vote->lockout.confirmation_count ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATIONS_NOT_ORDERED; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_CONFIRMATIONS_NOT_ORDERED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else if( FD_UNLIKELY( vote->lockout.slot > last_locked_out_slot( &previous_vote->lockout ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_NEW_VOTE_STATE_LOCKOUT_MISMATCH; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_NEW_VOTE_STATE_LOCKOUT_MISMATCH; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } @@ -1329,7 +1329,7 @@ process_new_vote_state( fd_vote_state_t * vote_state, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L697 if( last_locked_out_slot >= new_vote->lockout.slot ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L698 - ctx->txn_ctx->custom_err = FD_VOTE_ERR_LOCKOUT_CONFLICT; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_LOCKOUT_CONFLICT; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L700 @@ -1342,7 +1342,7 @@ process_new_vote_state( fd_vote_state_t * vote_state, } else if( FD_UNLIKELY( current_vote->lockout.slot == new_vote->lockout.slot ) ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L707 if( new_vote->lockout.confirmation_count < current_vote->lockout.confirmation_count ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATION_ROLL_BACK; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_CONFIRMATION_ROLL_BACK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1398,7 +1398,7 @@ process_new_vote_state( fd_vote_state_t * vote_state, if( deq_fd_landed_vote_t_empty( new_state ) ) { FD_LOG_ERR(( "solana panic" )); // TODO: solana panics ... unclear what to return - ctx->txn_ctx->custom_err = 0; + ctx->txn_ctx->err.custom_err = 0; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } ulong last_slot = deq_fd_landed_vote_t_peek_tail( new_state )->lockout.slot; @@ -1563,7 +1563,7 @@ update_commission( fd_borrowed_account_t * vote_account, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L940 if( FD_LIKELY( enforce_commission_update_rule ) ) { if( FD_UNLIKELY( !is_commission_update_allowed( clock->slot, epoch_schedule ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_COMMISSION_UPDATE_TOO_LATE; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_COMMISSION_UPDATE_TOO_LATE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } @@ -1637,7 +1637,7 @@ withdraw( fd_exec_instr_ctx_t const * ctx, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1034 if( FD_UNLIKELY( reject_active_vote_account_close ) ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1036 - ctx->txn_ctx->custom_err = FD_VOTE_ERR_ACTIVE_VOTE_ACCOUNT_CLOSE; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_ACTIVE_VOTE_ACCOUNT_CLOSE; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1040 @@ -1711,7 +1711,7 @@ process_vote( fd_vote_state_t * vote_state, fd_exec_instr_ctx_t const * ctx ) { // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L792 if( FD_UNLIKELY( deq_ulong_empty( vote->slots ) ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1752,7 +1752,7 @@ process_vote( fd_vote_state_t * vote_state, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L802 if( FD_UNLIKELY( deq_ulong_cnt( vote_slots ) == 0 ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_VOTES_TOO_OLD_ALL_FILTERED; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_VOTES_TOO_OLD_ALL_FILTERED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1875,7 +1875,7 @@ process_vote_with_account( fd_borrowed_account_t * vote_account, // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1126 if( FD_LIKELY( vote->has_timestamp ) ) { if( FD_UNLIKELY( deq_ulong_cnt( vote->slots ) == 0 ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } @@ -1888,7 +1888,7 @@ process_vote_with_account( fd_borrowed_account_t * vote_account, max = fd_ulong_max( max, *ele ); } if( FD_UNLIKELY( !max ) ) { - ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; + ctx->txn_ctx->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1131 diff --git a/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c b/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c index 8c77c31eee8..6765e53dea7 100644 --- a/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c +++ b/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c @@ -2,6 +2,7 @@ #include "zksdk/fd_zksdk.h" #include "../fd_executor.h" #include "../fd_runtime.h" +#include "../fd_bank.h" /* * ZK ElGamal Proof Program @@ -10,13 +11,13 @@ int fd_executor_zk_elgamal_proof_program_execute( fd_exec_instr_ctx_t * ctx ) { /* Feature-gate program activation */ - if( FD_UNLIKELY( !FD_FEATURE_ACTIVE( ctx->txn_ctx->slot, &ctx->txn_ctx->features, zk_elgamal_proof_program_enabled ) ) ) { + if( FD_UNLIKELY( !FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, zk_elgamal_proof_program_enabled ) ) ) { return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID; } /* https://github.com/anza-xyz/agave/blob/v2.2.16/programs/zk-elgamal-proof/src/lib.rs#L175-L187 */ - if( FD_LIKELY( FD_FEATURE_ACTIVE( ctx->txn_ctx->slot, &ctx->txn_ctx->features, disable_zk_elgamal_proof_program ) - && !FD_FEATURE_ACTIVE( ctx->txn_ctx->slot, &ctx->txn_ctx->features, reenable_zk_elgamal_proof_program ) ) ) { + if( FD_LIKELY( FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, disable_zk_elgamal_proof_program ) + && !FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, reenable_zk_elgamal_proof_program ) ) ) { fd_log_collector_msg_literal( ctx, "zk-elgamal-proof program is temporarily disabled" ); return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA; } diff --git a/src/flamenco/runtime/program/zksdk/test_zksdk.c b/src/flamenco/runtime/program/zksdk/test_zksdk.c index 930957d26ff..eb082dad6b6 100644 --- a/src/flamenco/runtime/program/zksdk/test_zksdk.c +++ b/src/flamenco/runtime/program/zksdk/test_zksdk.c @@ -4,6 +4,7 @@ This unit test just runs an instance of pubkey_validity. */ #include "fd_zksdk_private.h" #include "../../../../ballet/hex/fd_hex.h" +#include "../../fd_bank.h" #include "instructions/test_fd_zksdk_pubkey_validity.h" @@ -33,19 +34,19 @@ void create_test_ctx( fd_exec_instr_ctx_t * ctx, fd_exec_txn_ctx_t * txn_ctx, fd_instr_info_t * instr, - uchar * tx, - ulong tx_len, - ulong instr_off, - ulong compute_meter ) { + uchar * tx, + ulong tx_len, + ulong instr_off, + ulong compute_meter ) { // This is just minimally setting the instr data so we can test zkp verification // TODO: properly load tx ctx->txn_ctx = txn_ctx; - txn_ctx->compute_budget_details.compute_meter = compute_meter; + txn_ctx->details.compute_budget.compute_meter = compute_meter; ctx->instr = instr; instr->data = &tx[instr_off]; instr->data_sz = (ushort)(tx_len - instr_off); //TODO: this only works if the instruction is the last one instr->acct_cnt = 0; // TODO: hack to avoid filling proof context account (it requires to create the account first) - fd_log_collector_init( &ctx->txn_ctx->log_collector, 1 ); + fd_log_collector_init( &ctx->txn_ctx->log.log_collector, 1 ); } void @@ -68,9 +69,15 @@ test_pubkey_validity( FD_FN_UNUSED fd_rng_t * rng ) { fd_exec_instr_ctx_t ctx; fd_exec_txn_ctx_t txn_ctx[1]; fd_instr_info_t instr[1]; + fd_bank_t bank[1]; ulong tx_len = 0; ulong proof_offset = offset + 1 + context_sz; + txn_ctx->bank = bank; + fd_bank_slot_set( bank, 0UL ); + fd_features_t * features = fd_bank_features_modify( bank ); + fd_features_enable_all( features ); + // load test data uchar * tx = load_test_tx( hex, hex_sz, &tx_len ); create_test_ctx( &ctx, txn_ctx, instr, tx, tx_len, offset, cu ); diff --git a/src/flamenco/runtime/sysvar/fd_sysvar.c b/src/flamenco/runtime/sysvar/fd_sysvar.c index 8cda7495422..af5fcb4212a 100644 --- a/src/flamenco/runtime/sysvar/fd_sysvar.c +++ b/src/flamenco/runtime/sysvar/fd_sysvar.c @@ -66,7 +66,7 @@ fd_sysvar_instr_acct_check( fd_exec_instr_ctx_t const * ctx, } ushort idx_in_txn = ctx->instr->accounts[idx].index_in_transaction; - fd_pubkey_t const * addr_have = &ctx->txn_ctx->account_keys[ idx_in_txn ]; + fd_pubkey_t const * addr_have = &ctx->txn_ctx->accounts.account_keys[ idx_in_txn ]; if( FD_UNLIKELY( 0!=memcmp( addr_have, addr_want, sizeof(fd_pubkey_t) ) ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ARG; } diff --git a/src/flamenco/runtime/sysvar/fd_sysvar_instructions.c b/src/flamenco/runtime/sysvar/fd_sysvar_instructions.c index 9cfc7127d6c..23fbeaa368c 100644 --- a/src/flamenco/runtime/sysvar/fd_sysvar_instructions.c +++ b/src/flamenco/runtime/sysvar/fd_sysvar_instructions.c @@ -109,12 +109,12 @@ fd_sysvar_instructions_serialize_account( fd_exec_txn_ctx_t * txn_ctx, // pubkey ushort idx_in_txn = instr->accounts[j].index_in_transaction; - FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_ctx->account_keys[ idx_in_txn ] ); + FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_ctx->accounts.account_keys[ idx_in_txn ] ); offset += sizeof(fd_pubkey_t); } // program_id_pubkey - FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_ctx->account_keys[ instr->program_id ] ); + FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_ctx->accounts.account_keys[ instr->program_id ] ); offset += sizeof(fd_pubkey_t); // instr_data_len diff --git a/src/flamenco/runtime/tests/fd_block_harness.c b/src/flamenco/runtime/tests/fd_block_harness.c index 1a736bd7245..7e8d2e857c8 100644 --- a/src/flamenco/runtime/tests/fd_block_harness.c +++ b/src/flamenco/runtime/tests/fd_block_harness.c @@ -487,9 +487,9 @@ fd_solfuzz_block_ctx_exec( fd_solfuzz_runner_t * runner, /* Execute the transaction against the runtime */ res = FD_RUNTIME_EXECUTE_SUCCESS; fd_exec_txn_ctx_t * txn_ctx = fd_solfuzz_txn_ctx_exec( runner, xid, txn, &res ); - txn_ctx->exec_err = res; + txn_ctx->err.exec_err = res; - if( FD_UNLIKELY( !(txn_ctx->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS) ) ) { + if( FD_UNLIKELY( !txn_ctx->err.is_committable ) ) { break; } @@ -504,7 +504,7 @@ fd_solfuzz_block_ctx_exec( fd_solfuzz_runner_t * runner, capture_ctx, NULL ); - if( FD_UNLIKELY( !(txn_ctx->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS) ) ) { + if( FD_UNLIKELY( !txn_ctx->err.is_committable ) ) { break; } diff --git a/src/flamenco/runtime/tests/fd_dump_pb.c b/src/flamenco/runtime/tests/fd_dump_pb.c index a2aa4e0f917..6ca36a0aa5a 100644 --- a/src/flamenco/runtime/tests/fd_dump_pb.c +++ b/src/flamenco/runtime/tests/fd_dump_pb.c @@ -770,15 +770,15 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m txn_context_msg->account_shared_data = fd_spad_alloc( spad, alignof(fd_exec_test_acct_state_t), (256UL*2UL + txn_descriptor->addr_table_lookup_cnt + num_sysvar_entries) * sizeof(fd_exec_test_acct_state_t) ); - for( ulong i = 0; i < txn_ctx->accounts_cnt; ++i ) { + for( ulong i = 0; i < txn_ctx->accounts.accounts_cnt; ++i ) { fd_txn_account_t txn_account[1]; - int ret = fd_txn_account_init_from_funk_readonly( txn_account, &txn_ctx->account_keys[i], txn_ctx->funk, txn_ctx->xid ); + int ret = fd_txn_account_init_from_funk_readonly( txn_account, &txn_ctx->accounts.account_keys[i], txn_ctx->funk, txn_ctx->xid ); if( FD_UNLIKELY( ret ) ) { continue; } // Make sure account is not a non-migrating builtin - if( !is_builtin_account( &txn_ctx->account_keys[i] ) ) { + if( !is_builtin_account( &txn_ctx->accounts.account_keys[i] ) ) { dump_account_state( txn_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++], spad ); } } @@ -844,8 +844,8 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m // Make sure the account doesn't exist in the output accounts yet int account_exists = 0; - for( ulong j = 0; j < txn_ctx->accounts_cnt; j++ ) { - if ( 0 == memcmp( txn_ctx->account_keys[j].key, fd_dump_sysvar_ids[i], sizeof(fd_pubkey_t) ) ) { + for( ulong j = 0; j < txn_ctx->accounts.accounts_cnt; j++ ) { + if ( 0 == memcmp( txn_ctx->accounts.account_keys[j].key, fd_dump_sysvar_ids[i], sizeof(fd_pubkey_t) ) ) { account_exists = true; break; } @@ -876,11 +876,11 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m /* Transaction Context -> epoch_ctx */ txn_context_msg->has_epoch_ctx = true; txn_context_msg->epoch_ctx.has_features = true; - dump_sorted_features( &txn_ctx->features, &txn_context_msg->epoch_ctx.features, spad ); + dump_sorted_features( fd_bank_features_query( txn_ctx->bank ), &txn_context_msg->epoch_ctx.features, spad ); /* Transaction Context -> slot_ctx */ txn_context_msg->has_slot_ctx = true; - txn_context_msg->slot_ctx.slot = txn_ctx->slot; + txn_context_msg->slot_ctx.slot = fd_bank_slot_get( txn_ctx->bank ); } static void @@ -889,14 +889,14 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * fd_instr_info_t const * instr, fd_spad_t * spad ) { /* Program ID */ - fd_memcpy( instr_context->program_id, txn_ctx->account_keys[ instr->program_id ].uc, sizeof(fd_pubkey_t) ); + fd_memcpy( instr_context->program_id, txn_ctx->accounts.account_keys[ instr->program_id ].uc, sizeof(fd_pubkey_t) ); /* Accounts */ - instr_context->accounts_count = (pb_size_t) txn_ctx->accounts_cnt; - instr_context->accounts = fd_spad_alloc( spad, alignof(fd_exec_test_acct_state_t), (instr_context->accounts_count + num_sysvar_entries + txn_ctx->executable_cnt) * sizeof(fd_exec_test_acct_state_t)); - for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) { + instr_context->accounts_count = (pb_size_t) txn_ctx->accounts.accounts_cnt; + instr_context->accounts = fd_spad_alloc( spad, alignof(fd_exec_test_acct_state_t), (instr_context->accounts_count + num_sysvar_entries + txn_ctx->accounts.executable_cnt) * sizeof(fd_exec_test_acct_state_t)); + for( ulong i = 0; i < txn_ctx->accounts.accounts_cnt; i++ ) { // Copy account information over - fd_txn_account_t const * txn_account = &txn_ctx->accounts[i]; + fd_txn_account_t const * txn_account = &txn_ctx->accounts.accounts[i]; fd_exec_test_acct_state_t * output_account = &instr_context->accounts[i]; dump_account_state( txn_account, output_account, spad ); } @@ -910,8 +910,8 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * } // Make sure the account doesn't exist in the output accounts yet int account_exists = 0; - for( ulong j = 0; j < txn_ctx->accounts_cnt; j++ ) { - if ( 0 == memcmp( txn_ctx->account_keys[j].key, fd_dump_sysvar_ids[i], sizeof(fd_pubkey_t) ) ) { + for( ulong j = 0; j < txn_ctx->accounts.accounts_cnt; j++ ) { + if ( 0 == memcmp( txn_ctx->accounts.account_keys[j].key, fd_dump_sysvar_ids[i], sizeof(fd_pubkey_t) ) ) { account_exists = true; break; } @@ -925,16 +925,16 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * } /* Add executable accounts */ - for( ulong i = 0; i < txn_ctx->executable_cnt; i++ ) { + for( ulong i = 0; i < txn_ctx->accounts.executable_cnt; i++ ) { fd_txn_account_t txn_account[1]; - int ret = fd_txn_account_init_from_funk_readonly( txn_account, txn_ctx->executable_accounts[i].pubkey, txn_ctx->funk, txn_ctx->xid ); + int ret = fd_txn_account_init_from_funk_readonly( txn_account, txn_ctx->accounts.executable_accounts[i].pubkey, txn_ctx->funk, txn_ctx->xid ); if( ret != FD_ACC_MGR_SUCCESS ) { continue; } // Make sure the account doesn't exist in the output accounts yet bool account_exists = false; for( ulong j = 0; j < instr_context->accounts_count; j++ ) { - if( 0 == memcmp( instr_context->accounts[j].address, txn_ctx->executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) ) ) { + if( 0 == memcmp( instr_context->accounts[j].address, txn_ctx->accounts.executable_accounts[i].pubkey->uc, sizeof(fd_pubkey_t) ) ) { account_exists = true; break; } @@ -963,7 +963,7 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * fd_memcpy( instr_context->data->bytes, instr->data, instr->data_sz ); /* Compute Units */ - instr_context->cu_avail = txn_ctx->compute_budget_details.compute_meter; + instr_context->cu_avail = txn_ctx->details.compute_budget.compute_meter; /* Slot Context */ instr_context->has_slot_context = true; @@ -971,7 +971,7 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * /* Epoch Context */ instr_context->has_epoch_context = true; instr_context->epoch_context.has_features = true; - dump_sorted_features( &txn_ctx->features, &instr_context->epoch_context.features, spad ); + dump_sorted_features( fd_bank_features_query( txn_ctx->bank ), &instr_context->epoch_context.features, spad ); } /***** PUBLIC APIs *****/ @@ -980,7 +980,7 @@ void fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fd_instr_info_t * instr, ushort instruction_idx ) { - fd_spad_t * spad = fd_spad_join( fd_spad_new( txn_ctx->dumping_mem, 1UL<<28UL ) ); + fd_spad_t * spad = fd_spad_join( fd_spad_new( txn_ctx->log.dumping_mem, 1UL<<28UL ) ); FD_SPAD_FRAME_BEGIN( spad ) { // Get base58-encoded tx signature @@ -990,11 +990,11 @@ fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, ulong out_size; 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); + if (txn_ctx->log.capture_ctx->dump_proto_sig_filter) { + ulong filter_strlen = (ulong) strlen(txn_ctx->log.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( memcmp( txn_ctx->log.capture_ctx->dump_proto_sig_filter, encoded_signature, filter_strlen < out_size ? filter_strlen : out_size ) ) { return; } } @@ -1008,7 +1008,7 @@ fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, pb_ostream_t stream = pb_ostream_from_buffer( out, out_buf_size ); if (pb_encode(&stream, FD_EXEC_TEST_INSTR_CONTEXT_FIELDS, &instr_context)) { char output_filepath[ PATH_MAX ]; - snprintf( output_filepath, PATH_MAX, "%s/instr-%s-%hu.instrctx", txn_ctx->capture_ctx->dump_proto_output_dir, encoded_signature, instruction_idx ); + snprintf( output_filepath, PATH_MAX, "%s/instr-%s-%hu.instrctx", txn_ctx->log.capture_ctx->dump_proto_output_dir, encoded_signature, instruction_idx ); FILE * file = fopen(output_filepath, "wb"); if( file ) { fwrite( out, 1, stream.bytes_written, file ); @@ -1020,7 +1020,7 @@ fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, void fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t * txn_ctx ) { - fd_spad_t * spad = fd_spad_join( fd_spad_new( txn_ctx->dumping_mem, 1UL<<28UL ) ); + fd_spad_t * spad = fd_spad_join( fd_spad_new( txn_ctx->log.dumping_mem, 1UL<<28UL ) ); FD_SPAD_FRAME_BEGIN( spad ) { // Get base58-encoded tx signature @@ -1030,9 +1030,9 @@ fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t * txn_ctx ) { ulong out_size; fd_base58_encode_64( signature, &out_size, encoded_signature ); - if( txn_ctx->capture_ctx->dump_proto_sig_filter ) { + if( txn_ctx->log.capture_ctx->dump_proto_sig_filter ) { // Terminate early if the signature does not match - if( strcmp( txn_ctx->capture_ctx->dump_proto_sig_filter, encoded_signature ) ) { + if( strcmp( txn_ctx->log.capture_ctx->dump_proto_sig_filter, encoded_signature ) ) { return; } } @@ -1046,7 +1046,7 @@ fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t * txn_ctx ) { pb_ostream_t stream = pb_ostream_from_buffer( out, out_buf_size ); if( pb_encode( &stream, FD_EXEC_TEST_TXN_CONTEXT_FIELDS, &txn_context_msg ) ) { char output_filepath[ PATH_MAX ]; - snprintf( output_filepath, PATH_MAX, "%s/txn-%s.txnctx", txn_ctx->capture_ctx->dump_proto_output_dir, encoded_signature ); + snprintf( output_filepath, PATH_MAX, "%s/txn-%s.txnctx", txn_ctx->log.capture_ctx->dump_proto_output_dir, encoded_signature ); FILE * file = fopen(output_filepath, "wb"); if( file ) { fwrite( out, 1, stream.bytes_written, file ); @@ -1106,7 +1106,7 @@ void fd_dump_vm_syscall_to_protobuf( fd_vm_t const * vm, char const * fn_name ) { - fd_spad_t * spad = fd_spad_join( fd_spad_new( vm->instr_ctx->txn_ctx->dumping_mem, 1UL<<28UL ) ); + fd_spad_t * spad = fd_spad_join( fd_spad_new( vm->instr_ctx->txn_ctx->log.dumping_mem, 1UL<<28UL ) ); FD_SPAD_FRAME_BEGIN( spad ) { @@ -1119,11 +1119,11 @@ FD_SPAD_FRAME_BEGIN( spad ) { snprintf( filename, PATH_MAX, "%s/syscall-%s-%s-%d-%hhu-%lu.sysctx", - vm->instr_ctx->txn_ctx->capture_ctx->dump_proto_output_dir, + vm->instr_ctx->txn_ctx->log.capture_ctx->dump_proto_output_dir, fn_name, encoded_signature, - vm->instr_ctx->txn_ctx->current_instr_idx, - vm->instr_ctx->txn_ctx->instr_stack_sz, + vm->instr_ctx->txn_ctx->instr.current_idx, + vm->instr_ctx->txn_ctx->instr.stack_sz, vm->cu ); /* The generated filename should be unique for every call. Silently return otherwise. */ @@ -1171,14 +1171,14 @@ FD_SPAD_FRAME_BEGIN( spad ) { sys_ctx.vm_ctx.has_return_data = 1; /* SyscallContext -> vm_ctx -> return_data -> data */ - sys_ctx.vm_ctx.return_data.data = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( vm->instr_ctx->txn_ctx->return_data.len ) ); - sys_ctx.vm_ctx.return_data.data->size = (pb_size_t)vm->instr_ctx->txn_ctx->return_data.len; - fd_memcpy( sys_ctx.vm_ctx.return_data.data->bytes, vm->instr_ctx->txn_ctx->return_data.data, vm->instr_ctx->txn_ctx->return_data.len ); + sys_ctx.vm_ctx.return_data.data = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( vm->instr_ctx->txn_ctx->details.return_data.len ) ); + sys_ctx.vm_ctx.return_data.data->size = (pb_size_t)vm->instr_ctx->txn_ctx->details.return_data.len; + fd_memcpy( sys_ctx.vm_ctx.return_data.data->bytes, vm->instr_ctx->txn_ctx->details.return_data.data, vm->instr_ctx->txn_ctx->details.return_data.len ); /* SyscallContext -> vm_ctx -> return_data -> program_id */ sys_ctx.vm_ctx.return_data.program_id = fd_spad_alloc( spad, alignof(pb_bytes_array_t), sizeof(fd_pubkey_t) ); sys_ctx.vm_ctx.return_data.program_id->size = sizeof(fd_pubkey_t); - fd_memcpy( sys_ctx.vm_ctx.return_data.program_id->bytes, vm->instr_ctx->txn_ctx->return_data.program_id.key, sizeof(fd_pubkey_t) ); + fd_memcpy( sys_ctx.vm_ctx.return_data.program_id->bytes, vm->instr_ctx->txn_ctx->details.return_data.program_id.key, sizeof(fd_pubkey_t) ); /* SyscallContext -> vm_ctx -> sbpf_version */ sys_ctx.vm_ctx.sbpf_version = (uint)vm->sbpf_version; @@ -1201,8 +1201,8 @@ FD_SPAD_FRAME_BEGIN( spad ) { /* SyscallContext -> syscall_invocation -> heap_prefix */ sys_ctx.syscall_invocation.heap_prefix = fd_spad_alloc( spad, 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE( vm->heap_max ) ); - sys_ctx.syscall_invocation.heap_prefix->size = (pb_size_t) vm->instr_ctx->txn_ctx->compute_budget_details.heap_size; - fd_memcpy( sys_ctx.syscall_invocation.heap_prefix->bytes, vm->heap, vm->instr_ctx->txn_ctx->compute_budget_details.heap_size ); + sys_ctx.syscall_invocation.heap_prefix->size = (pb_size_t) vm->instr_ctx->txn_ctx->details.compute_budget.heap_size; + fd_memcpy( sys_ctx.syscall_invocation.heap_prefix->bytes, vm->heap, vm->instr_ctx->txn_ctx->details.compute_budget.heap_size ); /* SyscallContext -> syscall_invocation -> stack_prefix */ pb_size_t stack_sz = (pb_size_t)FD_VM_STACK_MAX; @@ -1227,7 +1227,7 @@ FD_SPAD_FRAME_BEGIN( spad ) { void fd_dump_elf_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fd_txn_account_t * program_acc ) { -fd_spad_t * spad = fd_spad_join( fd_spad_new( txn_ctx->dumping_mem, 1UL<<28UL ) ); +fd_spad_t * spad = fd_spad_join( fd_spad_new( txn_ctx->log.dumping_mem, 1UL<<28UL ) ); FD_SPAD_FRAME_BEGIN( spad ) { @@ -1250,10 +1250,10 @@ FD_SPAD_FRAME_BEGIN( spad ) { snprintf( filename, PATH_MAX, "%s/elf-%s-%s-%lu.elfctx", - txn_ctx->capture_ctx->dump_proto_output_dir, + txn_ctx->log.capture_ctx->dump_proto_output_dir, encoded_signature, program_acc_b58, - txn_ctx->slot ); + fd_bank_slot_get( txn_ctx->bank ) ); /* The generated filename should be unique for every call. Silently return otherwise. */ if( FD_UNLIKELY( access( filename, F_OK )!=-1 ) ) { @@ -1270,7 +1270,7 @@ FD_SPAD_FRAME_BEGIN( spad ) { /* ElfLoaderCtx -> features */ elf_ctx.has_features = true; - dump_sorted_features( &txn_ctx->features, &elf_ctx.features, spad ); + dump_sorted_features( fd_bank_features_query( txn_ctx->bank ), &elf_ctx.features, spad ); /* ElfLoaderCtx -> deploy_checks We hardcode this to true and rely the fuzzer to toggle this as it pleases */ diff --git a/src/flamenco/runtime/tests/fd_instr_harness.c b/src/flamenco/runtime/tests/fd_instr_harness.c index 12ee2601b04..73a0774b7ad 100644 --- a/src/flamenco/runtime/tests/fd_instr_harness.c +++ b/src/flamenco/runtime/tests/fd_instr_harness.c @@ -81,25 +81,53 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, uchar * progcache_scratch = fd_spad_alloc_check( runner->spad, FD_PROGCACHE_SCRATCH_ALIGN, FD_PROGCACHE_SCRATCH_FOOTPRINT ); - fd_exec_txn_ctx_setup( runner->bank, - runner->accdb->funk->shmem, - runner->progcache->funk->shmem, - xid, - NULL, - txn_ctx, - NULL, - progcache_scratch, - FD_PROGCACHE_SCRATCH_FOOTPRINT ); - fd_exec_txn_ctx_setup_basic( txn_ctx ); - - txn_ctx->txn = *txn; - txn_ctx->compute_budget_details.compute_unit_limit = test_ctx->cu_avail; - txn_ctx->compute_budget_details.compute_meter = test_ctx->cu_avail; - txn_ctx->instr_info_cnt = 1UL; - txn_ctx->enable_vm_tracing = runner->enable_vm_tracing; - txn_ctx->tracing_mem = runner->enable_vm_tracing ? - fd_spad_alloc_check( runner->spad, FD_RUNTIME_VM_TRACE_STATIC_ALIGN, FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT * FD_MAX_INSTRUCTION_STACK_DEPTH ) : - NULL; + if( FD_UNLIKELY( !fd_funk_join( txn_ctx->funk, runner->accdb->funk->shmem ) ) ) { + FD_LOG_CRIT(( "fd_funk_join(accdb) failed" )); + } + + if( runner->progcache->funk->shmem ) { + txn_ctx->progcache = fd_progcache_join( txn_ctx->_progcache, runner->progcache->funk->shmem, progcache_scratch, FD_PROGCACHE_SCRATCH_FOOTPRINT ); + if( FD_UNLIKELY( !txn_ctx->progcache ) ) { + FD_LOG_CRIT(( "fd_progcache_join() failed" )); + } + } + + txn_ctx->xid[0] = *xid; + txn_ctx->status_cache = NULL; + txn_ctx->bank_hash_cmp = NULL; + txn_ctx->log.enable_exec_recording = !!( runner->bank->flags & FD_BANK_FLAGS_EXEC_RECORDING ); + txn_ctx->bank = runner->bank; + + fd_compute_budget_details_new( &txn_ctx->details.compute_budget ); + txn_ctx->instr.stack_sz = 0; + txn_ctx->accounts.accounts_cnt = 0UL; + txn_ctx->accounts.executable_cnt = 0UL; + + txn_ctx->details.programs_to_reverify_cnt = 0UL; + txn_ctx->details.loaded_accounts_data_size = 0UL; + txn_ctx->details.loaded_accounts_data_size_cost = 0UL; + txn_ctx->details.accounts_resize_delta = 0UL; + + memset( txn_ctx->details.return_data.program_id.key, 0, sizeof(fd_pubkey_t) ); + txn_ctx->details.return_data.len = 0; + + txn_ctx->log.capture_ctx = NULL; + + txn_ctx->instr.info_cnt = 0UL; + txn_ctx->instr.trace_length = 0UL; + + txn_ctx->err.exec_err = 0; + txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE; + txn_ctx->instr.current_idx = 0; + + txn_ctx->txn = *txn; + txn_ctx->details.compute_budget.compute_unit_limit = test_ctx->cu_avail; + txn_ctx->details.compute_budget.compute_meter = test_ctx->cu_avail; + txn_ctx->instr.info_cnt = 1UL; + txn_ctx->log.enable_vm_tracing = runner->enable_vm_tracing; + txn_ctx->log.tracing_mem = runner->enable_vm_tracing ? + fd_spad_alloc_check( runner->spad, FD_RUNTIME_VM_TRACE_STATIC_ALIGN, FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT * FD_MAX_INSTRUCTION_STACK_DEPTH ) : + NULL; /* Set up instruction context */ @@ -112,7 +140,7 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, info->data = test_ctx->data->bytes; } - txn_ctx->instr_infos[ 0UL ] = *info; + txn_ctx->instr.infos[ 0UL ] = *info; /* Prepare borrowed account table (correctly handles aliasing) */ @@ -123,16 +151,16 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, /* Load accounts into database */ - fd_txn_account_t * accts = txn_ctx->accounts; + fd_txn_account_t * accts = txn_ctx->accounts.accounts; fd_memset( accts, 0, test_ctx->accounts_count * sizeof(fd_txn_account_t) ); - txn_ctx->accounts_cnt = test_ctx->accounts_count; + txn_ctx->accounts.accounts_cnt = test_ctx->accounts_count; int has_program_id = 0; for( ulong j=0UL; j < test_ctx->accounts_count; j++ ) { fd_pubkey_t * acc_key = (fd_pubkey_t *)test_ctx->accounts[j].address; - memcpy( &(txn_ctx->account_keys[j]), test_ctx->accounts[j].address, sizeof(fd_pubkey_t) ); + memcpy( &(txn_ctx->accounts.account_keys[j]), test_ctx->accounts[j].address, sizeof(fd_pubkey_t) ); if( !fd_solfuzz_pb_load_account( &accts[j], runner->accdb, xid, &test_ctx->accounts[j], 0 ) ) { return 0; } @@ -150,7 +178,7 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, if( !memcmp( accts[j].pubkey, test_ctx->program_id, sizeof(fd_pubkey_t) ) ) { has_program_id = 1; - info->program_id = (uchar)txn_ctx->accounts_cnt; + info->program_id = (uchar)txn_ctx->accounts.accounts_cnt; } /* Since the instructions sysvar is set as mutable at the txn level, we need to make it mutable here as well. */ @@ -162,7 +190,7 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, /* If the program id is not in the set of accounts it must be added to the set of accounts. */ if( FD_UNLIKELY( !has_program_id ) ) { fd_txn_account_t * program_acc = &accts[ test_ctx->accounts_count ]; - fd_pubkey_t * program_key = &txn_ctx->account_keys[ txn_ctx->accounts_cnt ]; + fd_pubkey_t * program_key = &txn_ctx->accounts.account_keys[ txn_ctx->accounts.accounts_cnt ]; memcpy( program_key, test_ctx->program_id, sizeof(fd_pubkey_t) ); fd_account_meta_t * meta = fd_spad_alloc( runner->spad, alignof(fd_account_meta_t), sizeof(fd_account_meta_t) ); @@ -176,12 +204,12 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, FD_LOG_CRIT(( "Failed to join and new a txn account" )); } - info->program_id = (uchar)txn_ctx->accounts_cnt; - txn_ctx->accounts_cnt++; + info->program_id = (uchar)txn_ctx->accounts.accounts_cnt; + txn_ctx->accounts.accounts_cnt++; } /* Load in executable accounts */ - for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) { + for( ulong i = 0; i < txn_ctx->accounts.accounts_cnt; i++ ) { fd_pubkey_t * acc_key = (fd_pubkey_t *)test_ctx->accounts[i].address; fd_txn_account_t * acc = &accts[i]; @@ -212,13 +240,13 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, } fd_pubkey_t * programdata_acc = &program_loader_state->inner.program.programdata_address; - if( FD_UNLIKELY( fd_txn_account_init_from_funk_readonly( &txn_ctx->executable_accounts[txn_ctx->executable_cnt], + if( FD_UNLIKELY( fd_txn_account_init_from_funk_readonly( &txn_ctx->accounts.executable_accounts[txn_ctx->accounts.executable_cnt], programdata_acc, txn_ctx->funk, txn_ctx->xid ) ) ) { continue; } - txn_ctx->executable_cnt++; + txn_ctx->accounts.executable_cnt++; } } @@ -311,19 +339,25 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner, ctx->instr = info; - /* Refresh the setup from the updated slot and epoch ctx. */ - fd_exec_txn_ctx_setup( runner->bank, - runner->accdb->funk->shmem, - runner->progcache->funk->shmem, - xid, - NULL, - txn_ctx, - NULL, - progcache_scratch, - FD_PROGCACHE_SCRATCH_FOOTPRINT ); + if( FD_UNLIKELY( !fd_funk_join( txn_ctx->funk, runner->accdb->funk->shmem ) ) ) { + FD_LOG_CRIT(( "fd_funk_join(accdb) failed" )); + } + + if( runner->progcache->funk->shmem ) { + txn_ctx->progcache = fd_progcache_join( txn_ctx->_progcache, runner->progcache->funk->shmem, progcache_scratch, FD_PROGCACHE_SCRATCH_FOOTPRINT ); + if( FD_UNLIKELY( !txn_ctx->progcache ) ) { + FD_LOG_CRIT(( "fd_progcache_join() failed" )); + } + } + + txn_ctx->xid[0] = *xid; + txn_ctx->status_cache = NULL; + txn_ctx->bank_hash_cmp = NULL; + txn_ctx->log.enable_exec_recording = !!( runner->bank->flags & FD_BANK_FLAGS_EXEC_RECORDING ); + txn_ctx->bank = runner->bank; - fd_log_collector_init( &ctx->txn_ctx->log_collector, 1 ); - fd_base58_encode_32( txn_ctx->account_keys[ ctx->instr->program_id ].uc, NULL, ctx->program_id_base58 ); + fd_log_collector_init( &ctx->txn_ctx->log.log_collector, 1 ); + fd_base58_encode_32( txn_ctx->accounts.account_keys[ ctx->instr->program_id ].uc, NULL, ctx->program_id_base58 ); return 1; } @@ -374,19 +408,19 @@ fd_solfuzz_pb_instr_run( fd_solfuzz_runner_t * runner, /* Capture error code */ effects->result = -exec_result; - effects->cu_avail = ctx->txn_ctx->compute_budget_details.compute_meter; + effects->cu_avail = ctx->txn_ctx->details.compute_budget.compute_meter; /* Don't capture custom error codes if the program is a precompile */ if( FD_LIKELY( effects->result ) ) { int program_id_idx = ctx->instr[ 0UL ].program_id; if( exec_result==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && - fd_executor_lookup_native_precompile_program( &ctx->txn_ctx->accounts[ program_id_idx ] )==NULL ) { - effects->custom_err = ctx->txn_ctx->custom_err; + fd_executor_lookup_native_precompile_program( &ctx->txn_ctx->accounts.accounts[ program_id_idx ] )==NULL ) { + effects->custom_err = ctx->txn_ctx->err.custom_err; } } /* Allocate space for captured accounts */ - ulong modified_acct_cnt = ctx->txn_ctx->accounts_cnt; + ulong modified_acct_cnt = ctx->txn_ctx->accounts.accounts_cnt; fd_exec_test_acct_state_t * modified_accts = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_acct_state_t), @@ -400,8 +434,8 @@ fd_solfuzz_pb_instr_run( fd_solfuzz_runner_t * runner, /* Capture borrowed accounts */ - for( ulong j=0UL; j < ctx->txn_ctx->accounts_cnt; j++ ) { - fd_txn_account_t * acc = &ctx->txn_ctx->accounts[j]; + for( ulong j=0UL; j < ctx->txn_ctx->accounts.accounts_cnt; j++ ) { + fd_txn_account_t * acc = &ctx->txn_ctx->accounts.accounts[j]; if( !fd_txn_account_get_meta( acc ) ) { continue; } @@ -434,7 +468,7 @@ fd_solfuzz_pb_instr_run( fd_solfuzz_runner_t * runner, } /* Capture return data */ - fd_txn_return_data_t * return_data = &ctx->txn_ctx->return_data; + fd_txn_return_data_t * return_data = &ctx->txn_ctx->details.return_data; if( return_data->len>0UL ) { effects->return_data = FD_SCRATCH_ALLOC_APPEND(l, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( return_data->len ) ); diff --git a/src/flamenco/runtime/tests/fd_txn_harness.c b/src/flamenco/runtime/tests/fd_txn_harness.c index e67a4935002..c3ee3023dfc 100644 --- a/src/flamenco/runtime/tests/fd_txn_harness.c +++ b/src/flamenco/runtime/tests/fd_txn_harness.c @@ -339,7 +339,7 @@ fd_solfuzz_txn_ctx_exec( fd_solfuzz_runner_t * runner, /* Setup the spad for account allocation */ uchar * txn_ctx_mem = fd_spad_alloc_check( runner->spad, FD_EXEC_TXN_CTX_ALIGN, FD_EXEC_TXN_CTX_FOOTPRINT ); fd_exec_txn_ctx_t * txn_ctx = fd_exec_txn_ctx_join( fd_exec_txn_ctx_new( txn_ctx_mem ) ); - txn_ctx->flags = FD_TXN_P_FLAGS_SANITIZE_SUCCESS; + txn_ctx->err.is_committable = 1; if( FD_UNLIKELY( !fd_funk_join( txn_ctx->funk, runner->accdb->funk->shmem ) ) ) { FD_LOG_CRIT(( "fd_funk_join failed" )); } @@ -351,15 +351,14 @@ fd_solfuzz_txn_ctx_exec( fd_solfuzz_runner_t * runner, txn_ctx->bank_hash_cmp = NULL; txn_ctx->xid[0] = *xid; - txn_ctx->enable_vm_tracing = runner->enable_vm_tracing; + txn_ctx->log.enable_vm_tracing = runner->enable_vm_tracing; uchar * tracing_mem = NULL; if( runner->enable_vm_tracing ) { tracing_mem = fd_spad_alloc_check( runner->spad, FD_RUNTIME_VM_TRACE_STATIC_ALIGN, FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT * FD_MAX_INSTRUCTION_STACK_DEPTH ); } *exec_res = fd_runtime_prepare_and_execute_txn( - runner->banks, - 0UL, + runner->bank, txn_ctx, txn, NULL, @@ -415,8 +414,8 @@ fd_solfuzz_pb_txn_run( fd_solfuzz_runner_t * runner, } /* Capture basic results fields */ - txn_result->executed = txn_ctx->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS; - txn_result->sanitization_error = !(txn_ctx->flags & FD_TXN_P_FLAGS_SANITIZE_SUCCESS); + txn_result->executed = txn_ctx->err.is_committable; + txn_result->sanitization_error = !txn_ctx->err.is_committable; txn_result->has_resulting_state = false; txn_result->resulting_state.acct_states_count = 0; txn_result->is_ok = !exec_res; @@ -425,21 +424,21 @@ fd_solfuzz_pb_txn_run( fd_solfuzz_runner_t * runner, txn_result->instruction_error_index = 0; txn_result->custom_error = 0; txn_result->has_fee_details = false; - txn_result->loaded_accounts_data_size = txn_ctx->loaded_accounts_data_size; + txn_result->loaded_accounts_data_size = txn_ctx->details.loaded_accounts_data_size; if( txn_result->sanitization_error ) { /* Collect fees for transactions that failed to load */ - if( txn_ctx->flags & FD_TXN_P_FLAGS_FEES_ONLY ) { + if( txn_ctx->err.is_fees_only ) { txn_result->has_fee_details = true; - txn_result->fee_details.prioritization_fee = txn_ctx->priority_fee; - txn_result->fee_details.transaction_fee = txn_ctx->execution_fee; + txn_result->fee_details.prioritization_fee = txn_ctx->details.priority_fee; + txn_result->fee_details.transaction_fee = txn_ctx->details.execution_fee; } if( exec_res==FD_RUNTIME_TXN_ERR_INSTRUCTION_ERROR ) { - txn_result->instruction_error = (uint32_t) -txn_ctx->exec_err; - txn_result->instruction_error_index = (uint32_t) txn_ctx->instr_err_idx; - if( txn_ctx->exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ) { - txn_result->custom_error = txn_ctx->custom_err; + txn_result->instruction_error = (uint32_t) -txn_ctx->err.exec_err; + txn_result->instruction_error_index = (uint32_t) txn_ctx->err.exec_err_idx; + if( txn_ctx->err.exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ) { + txn_result->custom_error = txn_ctx->err.custom_err; } } @@ -452,42 +451,42 @@ fd_solfuzz_pb_txn_run( fd_solfuzz_runner_t * runner, } else { /* Capture the instruction error code */ if( exec_res==FD_RUNTIME_TXN_ERR_INSTRUCTION_ERROR ) { - int instr_err_idx = txn_ctx->instr_err_idx; - int program_id_idx = txn_ctx->instr_infos[instr_err_idx].program_id; + int instr_err_idx = txn_ctx->err.exec_err_idx; + int program_id_idx = txn_ctx->instr.infos[instr_err_idx].program_id; - txn_result->instruction_error = (uint32_t) -txn_ctx->exec_err; + txn_result->instruction_error = (uint32_t) -txn_ctx->err.exec_err; txn_result->instruction_error_index = (uint32_t) instr_err_idx; /* If the exec err was a custom instr error and came from a precompile instruction, don't capture the custom error code. */ - if( txn_ctx->exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && - fd_executor_lookup_native_precompile_program( &txn_ctx->accounts[ program_id_idx ] )==NULL ) { - txn_result->custom_error = txn_ctx->custom_err; + if( txn_ctx->err.exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && + fd_executor_lookup_native_precompile_program( &txn_ctx->accounts.accounts[ program_id_idx ] )==NULL ) { + txn_result->custom_error = txn_ctx->err.custom_err; } } } txn_result->has_fee_details = true; - txn_result->fee_details.transaction_fee = txn_ctx->execution_fee; - txn_result->fee_details.prioritization_fee = txn_ctx->priority_fee; - txn_result->executed_units = txn_ctx->compute_budget_details.compute_unit_limit - txn_ctx->compute_budget_details.compute_meter; + txn_result->fee_details.transaction_fee = txn_ctx->details.execution_fee; + txn_result->fee_details.prioritization_fee = txn_ctx->details.priority_fee; + txn_result->executed_units = txn_ctx->details.compute_budget.compute_unit_limit - txn_ctx->details.compute_budget.compute_meter; /* Rent is no longer collected */ txn_result->rent = 0UL; - if( txn_ctx->return_data.len > 0 ) { + if( txn_ctx->details.return_data.len > 0 ) { txn_result->return_data = FD_SCRATCH_ALLOC_APPEND( l, alignof(pb_bytes_array_t), - PB_BYTES_ARRAY_T_ALLOCSIZE( txn_ctx->return_data.len ) ); + PB_BYTES_ARRAY_T_ALLOCSIZE( txn_ctx->details.return_data.len ) ); if( FD_UNLIKELY( _l > output_end ) ) { abort(); } - txn_result->return_data->size = (pb_size_t)txn_ctx->return_data.len; - fd_memcpy( txn_result->return_data->bytes, txn_ctx->return_data.data, txn_ctx->return_data.len ); + txn_result->return_data->size = (pb_size_t)txn_ctx->details.return_data.len; + fd_memcpy( txn_result->return_data->bytes, txn_ctx->details.return_data.data, txn_ctx->details.return_data.len ); } /* Allocate space for captured accounts */ - ulong modified_acct_cnt = txn_ctx->accounts_cnt; + ulong modified_acct_cnt = txn_ctx->accounts.accounts_cnt; txn_result->has_resulting_state = true; txn_result->resulting_state.acct_states = @@ -498,18 +497,18 @@ fd_solfuzz_pb_txn_run( fd_solfuzz_runner_t * runner, } /* If the transaction is a fees-only transaction, we have to create rollback accounts to iterate over and save. */ - fd_txn_account_t * accounts_to_save = txn_ctx->accounts; - ulong accounts_cnt = txn_ctx->accounts_cnt; - if( txn_ctx->flags & FD_TXN_P_FLAGS_FEES_ONLY ) { + fd_txn_account_t * accounts_to_save = txn_ctx->accounts.accounts; + ulong accounts_cnt = txn_ctx->accounts.accounts_cnt; + if( txn_ctx->err.is_fees_only ) { accounts_to_save = fd_spad_alloc( runner->spad, alignof(fd_txn_account_t), sizeof(fd_txn_account_t) * 2 ); accounts_cnt = 0UL; - if( FD_LIKELY( txn_ctx->nonce_account_idx_in_txn!=FD_FEE_PAYER_TXN_IDX ) ) { - accounts_to_save[accounts_cnt++] = *txn_ctx->rollback_fee_payer_account; + if( FD_LIKELY( txn_ctx->accounts.nonce_idx_in_txn!=FD_FEE_PAYER_TXN_IDX ) ) { + accounts_to_save[accounts_cnt++] = *txn_ctx->accounts.rollback_fee_payer; } - if( txn_ctx->nonce_account_idx_in_txn!=ULONG_MAX ) { - accounts_to_save[accounts_cnt++] = *txn_ctx->rollback_nonce_account; + if( txn_ctx->accounts.nonce_idx_in_txn!=ULONG_MAX ) { + accounts_to_save[accounts_cnt++] = *txn_ctx->accounts.rollback_nonce; } } diff --git a/src/flamenco/runtime/tests/fd_vm_harness.c b/src/flamenco/runtime/tests/fd_vm_harness.c index d1e449ef106..aa3adaed494 100644 --- a/src/flamenco/runtime/tests/fd_vm_harness.c +++ b/src/flamenco/runtime/tests/fd_vm_harness.c @@ -7,6 +7,7 @@ #include "../../vm/fd_vm.h" #include "../../vm/test_vm_util.h" #include "generated/vm.pb.h" +#include "../fd_bank.h" static int fd_solfuzz_vm_syscall_noop( void * _vm, @@ -150,13 +151,13 @@ do{ fd_vm_input_region_t input_mem_regions[1000] = {0}; /* We can have a max of (3 * num accounts + 1) regions */ fd_vm_acc_region_meta_t acc_region_metas[256] = {0}; /* instr acc idx to idx */ uint input_mem_regions_cnt = 0UL; - int direct_mapping = FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ); - int stricter_abi_and_runtime_constraints = FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ); + int direct_mapping = FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ); + int stricter_abi_and_runtime_constraints = FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ); uchar * input_ptr = NULL; uchar program_id_idx = instr_ctx->instr->program_id; - fd_txn_account_t const * program_acc = &instr_ctx->txn_ctx->accounts[program_id_idx]; - uchar is_deprecated = ( program_id_idx < instr_ctx->txn_ctx->accounts_cnt ) && + fd_txn_account_t const * program_acc = &instr_ctx->txn_ctx->accounts.accounts[program_id_idx]; + uchar is_deprecated = ( program_id_idx < instr_ctx->txn_ctx->accounts.accounts_cnt ) && ( !memcmp( fd_txn_account_get_owner( program_acc ), fd_solana_bpf_loader_deprecated_program_id.key, sizeof(fd_pubkey_t) ) ); /* Push the instruction onto the stack. This may also modify the sysvar instructions account, if its present. */ @@ -210,8 +211,8 @@ do{ /* Setup syscalls. Have them all be no-ops */ fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() ) ); fd_vm_syscall_register_slot( syscalls, - instr_ctx->txn_ctx->slot, - &instr_ctx->txn_ctx->features, + fd_bank_slot_get( instr_ctx->txn_ctx->bank ), + fd_bank_features_query( instr_ctx->txn_ctx->bank ), 0 ); for( ulong i=0; i< fd_sbpf_syscalls_slot_cnt(); i++ ){ @@ -400,8 +401,8 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, if( !fd_solfuzz_pb_instr_ctx_create( runner, ctx, input_instr_ctx, skip_extra_checks ) ) goto error; - ctx->txn_ctx->instr_trace[0].instr_info = (fd_instr_info_t *)ctx->instr; - ctx->txn_ctx->instr_trace[0].stack_height = 1; + ctx->txn_ctx->instr.trace[0].instr_info = (fd_instr_info_t *)ctx->instr; + ctx->txn_ctx->instr.trace[0].stack_height = 1; /* Capture outputs */ ulong output_end = (ulong)output_buf + output_bufsz; @@ -414,12 +415,12 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, } if( input->vm_ctx.return_data.program_id && input->vm_ctx.return_data.program_id->size == sizeof(fd_pubkey_t) ) { - fd_memcpy( ctx->txn_ctx->return_data.program_id.uc, input->vm_ctx.return_data.program_id->bytes, sizeof(fd_pubkey_t) ); + fd_memcpy( ctx->txn_ctx->details.return_data.program_id.uc, input->vm_ctx.return_data.program_id->bytes, sizeof(fd_pubkey_t) ); } if( input->vm_ctx.return_data.data && input->vm_ctx.return_data.data->size>0U ) { - ctx->txn_ctx->return_data.len = input->vm_ctx.return_data.data->size; - fd_memcpy( ctx->txn_ctx->return_data.data, input->vm_ctx.return_data.data->bytes, ctx->txn_ctx->return_data.len ); + ctx->txn_ctx->details.return_data.len = input->vm_ctx.return_data.data->size; + fd_memcpy( ctx->txn_ctx->details.return_data.data, input->vm_ctx.return_data.data->bytes, ctx->txn_ctx->details.return_data.len ); } *effects = (fd_exec_test_syscall_effects_t) FD_EXEC_TEST_SYSCALL_EFFECTS_INIT_ZERO; @@ -459,13 +460,13 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, fd_vm_input_region_t input_mem_regions[1000] = {0}; /* We can have a max of (3 * num accounts + 1) regions */ fd_vm_acc_region_meta_t acc_region_metas[256] = {0}; /* instr acc idx to idx */ uint input_mem_regions_cnt = 0U; - int direct_mapping = FD_FEATURE_ACTIVE( ctx->txn_ctx->slot, &ctx->txn_ctx->features, account_data_direct_mapping ); - int stricter_abi_and_runtime_constraints = FD_FEATURE_ACTIVE( ctx->txn_ctx->slot, &ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ); + int direct_mapping = FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, account_data_direct_mapping ); + int stricter_abi_and_runtime_constraints = FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ); uchar * input_ptr = NULL; uchar program_id_idx = ctx->instr->program_id; - fd_txn_account_t * program_acc = &ctx->txn_ctx->accounts[program_id_idx]; - uchar is_deprecated = ( program_id_idx < ctx->txn_ctx->accounts_cnt ) && + fd_txn_account_t * program_acc = &ctx->txn_ctx->accounts.accounts[program_id_idx]; + uchar is_deprecated = ( program_id_idx < ctx->txn_ctx->accounts.accounts_cnt ) && ( !memcmp( fd_txn_account_get_owner( program_acc ), fd_solana_bpf_loader_deprecated_program_id.key, sizeof(fd_pubkey_t) ) ); /* Push the instruction onto the stack. This may also modify the sysvar instructions account, if its present. */ @@ -494,7 +495,7 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, fd_vm_init( vm, ctx, input->vm_ctx.heap_max, - ctx->txn_ctx->compute_budget_details.compute_meter, + ctx->txn_ctx->details.compute_budget.compute_meter, rodata, rodata_sz, NULL, // TODO @@ -550,7 +551,7 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, } /* There's an instr ctx struct embedded in the txn ctx instr stack. */ - fd_exec_instr_ctx_t * instr_ctx = &ctx->txn_ctx->instr_stack[ ctx->txn_ctx->instr_stack_sz - 1 ]; + fd_exec_instr_ctx_t * instr_ctx = &ctx->txn_ctx->instr.stack[ ctx->txn_ctx->instr.stack_sz - 1 ]; *instr_ctx = (fd_exec_instr_ctx_t) { .instr = ctx->instr, .txn_ctx = ctx->txn_ctx, @@ -568,7 +569,7 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, } /* Capture the effects */ - int exec_err = vm->instr_ctx->txn_ctx->exec_err; + int exec_err = vm->instr_ctx->txn_ctx->err.exec_err; effects->error = 0; if( syscall_err ) { if( exec_err==0 ) { @@ -578,8 +579,8 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, effects->error = (exec_err <= 0) ? -exec_err : -1; /* Map error kind, equivalent to: - effects->error_kind = (fd_exec_test_err_kind_t)(vm->instr_ctx->txn_ctx->exec_err_kind); */ - switch (vm->instr_ctx->txn_ctx->exec_err_kind) { + effects->error_kind = (fd_exec_test_err_kind_t)(vm->instr_ctx->txn_ctx->err.exec_err_kind); */ + switch (vm->instr_ctx->txn_ctx->err.exec_err_kind) { case FD_EXECUTOR_ERR_KIND_EBPF: effects->error_kind = FD_EXEC_TEST_ERR_KIND_EBPF; break; @@ -632,7 +633,7 @@ fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner, effects->frame_count = vm->frame_cnt; - fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log.log_collector; /* Only collect log on valid errors (i.e., != -1). Follows https://github.com/firedancer-io/solfuzz-agave/blob/99758d3c4f3a342d56e2906936458d82326ae9a8/src/utils/err_map.rs#L148 */ if( effects->error != -1 && log->buf_sz ) { diff --git a/src/flamenco/vm/fd_vm_private.h b/src/flamenco/vm/fd_vm_private.h index 0fa64a481a3..dee659da1f9 100644 --- a/src/flamenco/vm/fd_vm_private.h +++ b/src/flamenco/vm/fd_vm_private.h @@ -124,20 +124,20 @@ FD_PROTOTYPES_BEGIN #ifdef FD_RUNTIME_ERR_HANDHOLDING /* Asserts that the error and error kind are populated (non-zero) */ #define FD_VM_TEST_ERR_EXISTS( vm ) \ - FD_TEST( vm->instr_ctx->txn_ctx->exec_err ); \ - FD_TEST( vm->instr_ctx->txn_ctx->exec_err_kind ) + FD_TEST( vm->instr_ctx->txn_ctx->err.exec_err ); \ + FD_TEST( vm->instr_ctx->txn_ctx->err.exec_err_kind ) /* Used prior to a FD_VM_ERR_FOR_LOG_INSTR call to deliberately bypass overwrite handholding checks. Only use this if you know what you're doing. */ #define FD_VM_PREPARE_ERR_OVERWRITE( vm ) \ - vm->instr_ctx->txn_ctx->exec_err = 0; \ - vm->instr_ctx->txn_ctx->exec_err_kind = 0 + vm->instr_ctx->txn_ctx->err.exec_err = 0; \ + vm->instr_ctx->txn_ctx->err.exec_err_kind = 0 /* Asserts that the error and error kind are not populated (zero) */ #define FD_VM_TEST_ERR_OVERWRITE( vm ) \ - FD_TEST( !vm->instr_ctx->txn_ctx->exec_err ); \ - FD_TEST( !vm->instr_ctx->txn_ctx->exec_err_kind ) + FD_TEST( !vm->instr_ctx->txn_ctx->err.exec_err ); \ + FD_TEST( !vm->instr_ctx->txn_ctx->err.exec_err_kind ) #else #define FD_VM_TEST_ERR_EXISTS( vm ) ( ( void )0 ) #define FD_VM_PREPARE_ERR_OVERWRITE( vm ) ( ( void )0 ) @@ -146,22 +146,22 @@ FD_PROTOTYPES_BEGIN /* Log error within the instr_ctx to match Agave/Rust error. */ -#define FD_VM_ERR_FOR_LOG_EBPF( vm, err ) (__extension__({ \ - FD_VM_TEST_ERR_OVERWRITE( vm ); \ - vm->instr_ctx->txn_ctx->exec_err = err; \ - vm->instr_ctx->txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_EBPF; \ +#define FD_VM_ERR_FOR_LOG_EBPF( vm, err_ ) (__extension__({ \ + FD_VM_TEST_ERR_OVERWRITE( vm ); \ + vm->instr_ctx->txn_ctx->err.exec_err = err_; \ + vm->instr_ctx->txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_EBPF; \ })) -#define FD_VM_ERR_FOR_LOG_SYSCALL( vm, err ) (__extension__({ \ - FD_VM_TEST_ERR_OVERWRITE( vm ); \ - vm->instr_ctx->txn_ctx->exec_err = err; \ - vm->instr_ctx->txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_SYSCALL; \ +#define FD_VM_ERR_FOR_LOG_SYSCALL( vm, err_ ) (__extension__({ \ + FD_VM_TEST_ERR_OVERWRITE( vm ); \ + vm->instr_ctx->txn_ctx->err.exec_err = err_; \ + vm->instr_ctx->txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_SYSCALL; \ })) -#define FD_VM_ERR_FOR_LOG_INSTR( vm, err ) (__extension__({ \ - FD_VM_TEST_ERR_OVERWRITE( vm ); \ - vm->instr_ctx->txn_ctx->exec_err = err; \ - vm->instr_ctx->txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_INSTR; \ +#define FD_VM_ERR_FOR_LOG_INSTR( vm, err_ ) (__extension__({ \ + FD_VM_TEST_ERR_OVERWRITE( vm ); \ + vm->instr_ctx->txn_ctx->err.exec_err = err_; \ + vm->instr_ctx->txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_INSTR; \ })) #define FD_VADDR_TO_REGION( _vaddr ) fd_ulong_min( (_vaddr) >> FD_VM_MEM_MAP_REGION_VIRT_ADDR_BITS, FD_VM_HIGH_REGION ) @@ -350,7 +350,7 @@ fd_vm_handle_input_mem_region_oob( fd_vm_t const * vm, https://github.com/anza-xyz/agave/blob/v3.0.1/transaction-context/src/lib.rs#L549-L551 */ ulong remaining_allowed_growth = fd_ulong_sat_sub( FD_MAX_ACCOUNT_DATA_GROWTH_PER_TRANSACTION, - vm->instr_ctx->txn_ctx->accounts_resize_delta ); + vm->instr_ctx->txn_ctx->details.accounts_resize_delta ); /* If the requested length is greater than the size of the region, resize the region @@ -365,8 +365,8 @@ fd_vm_handle_input_mem_region_oob( fd_vm_t const * vm, /* Resize the account and the region https://github.com/anza-xyz/agave/blob/v3.0.1/transaction-context/src/lib.rs#L569-L570 */ if( FD_UNLIKELY( new_region_sz > region->region_sz ) ) { - vm->instr_ctx->txn_ctx->accounts_resize_delta = fd_ulong_sat_sub( - fd_ulong_sat_add( vm->instr_ctx->txn_ctx->accounts_resize_delta, new_region_sz ), + vm->instr_ctx->txn_ctx->details.accounts_resize_delta = fd_ulong_sat_sub( + fd_ulong_sat_add( vm->instr_ctx->txn_ctx->details.accounts_resize_delta, new_region_sz ), region->region_sz ); fd_txn_account_resize( vm->acc_region_metas[ region->acc_region_meta_idx ].acct, new_region_sz ); diff --git a/src/flamenco/vm/syscall/fd_vm_syscall_cpi.c b/src/flamenco/vm/syscall/fd_vm_syscall_cpi.c index 78e4a719386..2d93707115d 100644 --- a/src/flamenco/vm/syscall/fd_vm_syscall_cpi.c +++ b/src/flamenco/vm/syscall/fd_vm_syscall_cpi.c @@ -82,7 +82,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, transactions accounts. */ FD_BASE58_ENCODE_32_BYTES( instr_acct_keys[i].uc, id_b58 ); fd_log_collector_msg_many( instr_ctx, 2, "Instruction references an unknown account ", 42UL, id_b58, id_b58_len ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_MISSING_ACC; } @@ -105,7 +105,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, /* TODO: this code would maybe be easier to read if we inverted the branches */ if( duplicate_index!=ULONG_MAX ) { if ( FD_UNLIKELY( duplicate_index >= deduplicated_instruction_accounts_cnt ) ) { - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS; } @@ -143,7 +143,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, if( FD_UNLIKELY( instruction_account->is_writable && !fd_borrowed_account_is_writable( &borrowed_caller_acct ) ) ) { FD_BASE58_ENCODE_32_BYTES( borrowed_caller_acct.acct->pubkey->uc, id_b58 ); fd_log_collector_msg_many( instr_ctx, 2, id_b58, id_b58_len, "'s writable privilege escalated", 31UL ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION; } @@ -151,7 +151,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, if ( FD_UNLIKELY( instruction_account->is_signer && !( fd_borrowed_account_is_signer( &borrowed_caller_acct ) || fd_vm_syscall_cpi_is_signer( borrowed_caller_acct.acct->pubkey, signers, signers_cnt) ) ) ) { FD_BASE58_ENCODE_32_BYTES( borrowed_caller_acct.acct->pubkey->uc, id_b58 ); fd_log_collector_msg_many( instr_ctx, 2, id_b58, id_b58_len, "'s signer privilege escalated", 29UL ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_PRIVILEGE_ESCALATION; } } @@ -170,7 +170,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, callee_instr->accounts[i].is_writable = !!(instruction_accounts[i].is_writable); callee_instr->accounts[i].is_signer = !!(instruction_accounts[i].is_signer); } else { - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS; } } @@ -181,7 +181,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, if( FD_UNLIKELY( program_idx == -1 ) ) { FD_BASE58_ENCODE_32_BYTES( callee_program_id_pubkey->uc, id_b58 ); fd_log_collector_msg_many( instr_ctx, 2, "Unknown program ", 16UL, id_b58, id_b58_len ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_MISSING_ACC; } @@ -191,7 +191,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, fd_guarded_borrowed_account_t borrowed_program_account = {0}; int err = fd_exec_instr_ctx_try_borrow_instr_account( instr_ctx, (ushort)program_idx, &borrowed_program_account ); if( FD_UNLIKELY( err ) ) { - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, err, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, err, instr_ctx->txn_ctx->err.exec_err_idx ); return err; } @@ -199,17 +199,17 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, /* https://github.com/anza-xyz/agave/blob/a9ac3f55fcb2bc735db0d251eda89897a5dbaaaa/program-runtime/src/invoke_context.rs#L434 */ FD_BASE58_ENCODE_32_BYTES( callee_program_id_pubkey->uc, id_b58 ); fd_log_collector_msg_many( instr_ctx, 2, "Unknown program ", 16UL, id_b58, id_b58_len ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_MISSING_ACC; } /* Check that the program account is executable. We need to ensure that the program account is a valid instruction account. https://github.com/anza-xyz/agave/blob/v2.1.14/program-runtime/src/invoke_context.rs#L438 */ - if( !FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, remove_accounts_executable_flag_checks ) ) { + if( !FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, remove_accounts_executable_flag_checks ) ) { if( FD_UNLIKELY( !fd_borrowed_account_is_executable( &borrowed_program_account ) ) ) { FD_BASE58_ENCODE_32_BYTES( callee_program_id_pubkey->uc, id_b58 ); fd_log_collector_msg_many( instr_ctx, 3, "Account ", 8UL, id_b58, id_b58_len, " is not executable", 18UL ); - FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE, instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE, instr_ctx->txn_ctx->err.exec_err_idx ); return FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE; } } @@ -245,7 +245,7 @@ fd_vm_prepare_instruction( fd_instr_info_t * callee_instr, FD_STATIC_ASSERT( FD_CPI_MAX_ACCOUNT_INFOS==MAX_TX_ACCOUNT_LOCKS, cpi_max_account_info ); static inline ulong get_cpi_max_account_infos( fd_exec_txn_ctx_t const * txn_ctx ) { - return fd_ulong_if( FD_FEATURE_ACTIVE( txn_ctx->slot, &txn_ctx->features, increase_tx_account_lock_limit ), FD_CPI_MAX_ACCOUNT_INFOS, 64UL ); + return fd_ulong_if( FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, increase_tx_account_lock_limit ), FD_CPI_MAX_ACCOUNT_INFOS, 64UL ); } /* Maximum CPI instruction data size. 10 KiB was chosen to ensure that CPI @@ -275,7 +275,7 @@ fd_vm_syscall_cpi_check_instruction( fd_vm_t const * vm, ulong acct_cnt, ulong data_sz ) { /* https://github.com/solana-labs/solana/blob/eb35a5ac1e7b6abe81947e22417f34508f89f091/programs/bpf_loader/src/syscalls/cpi.rs#L958-L959 */ - if( FD_FEATURE_ACTIVE( vm->instr_ctx->txn_ctx->slot, &vm->instr_ctx->txn_ctx->features, loosen_cpi_size_restriction ) ) { + if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->txn_ctx->bank, loosen_cpi_size_restriction ) ) { if( FD_UNLIKELY( data_sz > FD_CPI_MAX_INSTRUCTION_DATA_LEN ) ) { FD_LOG_WARNING(( "cpi: data too long (%#lx)", data_sz )); // SyscallError::MaxInstructionDataLenExceeded @@ -362,7 +362,7 @@ fd_vm_syscall_cpi_is_precompile( fd_pubkey_t const * program_id, fd_exec_txn_ctx return fd_vm_syscall_cpi_check_id(program_id, fd_solana_keccak_secp_256k_program_id.key) | fd_vm_syscall_cpi_check_id(program_id, fd_solana_ed25519_sig_verify_program_id.key) | ( fd_vm_syscall_cpi_check_id(program_id, fd_solana_secp256r1_program_id.key) && - FD_FEATURE_ACTIVE( txn_ctx->slot, &txn_ctx->features, enable_secp256r1_precompile ) ); + FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, enable_secp256r1_precompile ) ); } /* fd_vm_syscall_cpi_check_authorized_program corresponds to @@ -385,9 +385,9 @@ fd_vm_syscall_cpi_check_authorized_program( fd_pubkey_t const * program_id ( fd_vm_syscall_cpi_check_id(program_id, fd_solana_bpf_loader_upgradeable_program_id.key) && !(( instruction_data_len != 0 && instruction_data[0] == fd_bpf_upgradeable_loader_program_instruction_enum_upgrade ) || ( instruction_data_len != 0 && instruction_data[0] == fd_bpf_upgradeable_loader_program_instruction_enum_set_authority ) || - ( FD_FEATURE_ACTIVE( txn_ctx->slot, &txn_ctx->features, enable_bpf_loader_set_authority_checked_ix ) && + ( FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, enable_bpf_loader_set_authority_checked_ix ) && ( instruction_data_len != 0 && instruction_data[0] == fd_bpf_upgradeable_loader_program_instruction_enum_set_authority_checked )) || - ( FD_FEATURE_ACTIVE( txn_ctx->slot, &txn_ctx->features, enable_extend_program_checked ) && + ( FD_FEATURE_ACTIVE_BANK( txn_ctx->bank, enable_extend_program_checked ) && ( instruction_data_len != 0 && instruction_data[0] == fd_bpf_upgradeable_loader_program_instruction_enum_extend_program_checked )) || ( instruction_data_len != 0 && instruction_data[0] == fd_bpf_upgradeable_loader_program_instruction_enum_close ))) || fd_vm_syscall_cpi_is_precompile( program_id, txn_ctx ) ); diff --git a/src/flamenco/vm/syscall/fd_vm_syscall_cpi_common.c b/src/flamenco/vm/syscall/fd_vm_syscall_cpi_common.c index 3f3263c7d59..6684d67d053 100644 --- a/src/flamenco/vm/syscall/fd_vm_syscall_cpi_common.c +++ b/src/flamenco/vm/syscall/fd_vm_syscall_cpi_common.c @@ -60,6 +60,7 @@ VM_SYSCALL_CPI_INSTRUCTION_TO_INSTR_FUNC( fd_vm_t * vm, uchar const * cpi_instr_data, fd_instr_info_t * out_instr, fd_pubkey_t out_instr_acct_keys[ FD_INSTR_ACCT_MAX ] ) { + out_instr->program_id = UCHAR_MAX; out_instr->data_sz = (ushort)VM_SYSCALL_CPI_INSTR_DATA_LEN( cpi_instr ); out_instr->data = (uchar *)cpi_instr_data; @@ -736,7 +737,7 @@ VM_SYSCALL_CPI_ENTRYPOINT( void * _vm, /* Derive PDA signers ************************************************/ fd_pubkey_t signers[ FD_CPI_MAX_SIGNER_CNT ] = {0}; - fd_pubkey_t * caller_program_id = &vm->instr_ctx->txn_ctx->account_keys[ vm->instr_ctx->instr->program_id ]; + fd_pubkey_t * caller_program_id = &vm->instr_ctx->txn_ctx->accounts.account_keys[ vm->instr_ctx->instr->program_id ]; /* This is the equivalent of translate_slice in translate_signers: https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/programs/bpf_loader/src/syscalls/cpi.rs#L595 */ if( FD_LIKELY( signers_seeds_cnt > 0UL ) ) { @@ -779,7 +780,7 @@ VM_SYSCALL_CPI_ENTRYPOINT( void * _vm, /* Create the instruction to execute (in the input format the FD runtime expects) from the translated CPI ABI inputs. */ fd_pubkey_t cpi_instr_acct_keys[ FD_INSTR_ACCT_MAX ]; - fd_instr_info_t * instruction_to_execute = &vm->instr_ctx->txn_ctx->cpi_instr_infos[ vm->instr_ctx->txn_ctx->cpi_instr_info_cnt++ ]; + fd_instr_info_t * instruction_to_execute = &vm->instr_ctx->txn_ctx->instr.infos[ vm->instr_ctx->txn_ctx->instr.info_cnt++ ]; err = VM_SYSCALL_CPI_INSTRUCTION_TO_INSTR_FUNC( vm, cpi_instruction, cpi_account_metas, program_id, data, instruction_to_execute, cpi_instr_acct_keys ); if( FD_UNLIKELY( err ) ) { @@ -865,7 +866,7 @@ VM_SYSCALL_CPI_ENTRYPOINT( void * _vm, /* Set the transaction compute meter to be the same as the VM's compute meter, so that the callee cannot use compute units that the caller has already used. */ - vm->instr_ctx->txn_ctx->compute_budget_details.compute_meter = vm->cu; + vm->instr_ctx->txn_ctx->details.compute_budget.compute_meter = vm->cu; /* Execute the CPI instruction in the runtime */ int err_exec = fd_execute_instr( vm->instr_ctx->txn_ctx, instruction_to_execute ); @@ -873,7 +874,7 @@ VM_SYSCALL_CPI_ENTRYPOINT( void * _vm, /* Set the CU meter to the instruction context's transaction context's compute meter, so that the caller can't use compute units that the callee has already used. */ - vm->cu = vm->instr_ctx->txn_ctx->compute_budget_details.compute_meter; + vm->cu = vm->instr_ctx->txn_ctx->details.compute_budget.compute_meter; *_ret = instr_exec_res; @@ -887,7 +888,7 @@ VM_SYSCALL_CPI_ENTRYPOINT( void * _vm, caller accounts can't be changed during a CPI execution. */ if( fd_instr_acc_is_writable_idx( vm->instr_ctx->instr, callee_account_keys[i] ) ) { ushort idx_in_txn = vm->instr_ctx->instr->accounts[ callee_account_keys[i] ].index_in_transaction; - fd_pubkey_t const * callee = &vm->instr_ctx->txn_ctx->account_keys[ idx_in_txn ]; + fd_pubkey_t const * callee = &vm->instr_ctx->txn_ctx->accounts.account_keys[ idx_in_txn ]; err = VM_SYSCALL_CPI_UPDATE_CALLER_ACC_FUNC(vm, &acc_infos[ caller_accounts_to_update[i] ], caller_accounts + i, (uchar)callee_account_keys[i], callee); if( FD_UNLIKELY( err ) ) { return err; @@ -904,7 +905,7 @@ VM_SYSCALL_CPI_ENTRYPOINT( void * _vm, /* https://github.com/anza-xyz/agave/blob/v3.0.4/syscalls/src/cpi.rs#L1033-L1034 */ fd_guarded_borrowed_account_t borrowed_callee_acc = {0}; ushort idx_in_txn = vm->instr_ctx->instr->accounts[ callee_account_keys[i] ].index_in_transaction; - fd_pubkey_t const * callee = &vm->instr_ctx->txn_ctx->account_keys[ idx_in_txn ]; + fd_pubkey_t const * callee = &vm->instr_ctx->txn_ctx->accounts.account_keys[ idx_in_txn ]; err = fd_exec_instr_ctx_try_borrow_instr_account_with_key( vm->instr_ctx, callee, &borrowed_callee_acc ); if( FD_UNLIKELY( err && ( err != FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT ) ) ) { return 1; diff --git a/src/flamenco/vm/syscall/fd_vm_syscall_crypto.c b/src/flamenco/vm/syscall/fd_vm_syscall_crypto.c index 10ead3e3cc9..503bd8b0017 100644 --- a/src/flamenco/vm/syscall/fd_vm_syscall_crypto.c +++ b/src/flamenco/vm/syscall/fd_vm_syscall_crypto.c @@ -3,6 +3,7 @@ #include "../../../ballet/bn254/fd_bn254.h" #include "../../../ballet/bn254/fd_poseidon.h" #include "../../../ballet/secp256k1/fd_secp256k1.h" +#include "../../runtime/fd_bank.h" int fd_vm_syscall_sol_alt_bn128_group_op( void * _vm, @@ -81,7 +82,7 @@ fd_vm_syscall_sol_alt_bn128_group_op( void * _vm, case FD_VM_SYSCALL_SOL_ALT_BN128_MUL: /* Compute scalar mul */ if( FD_LIKELY( fd_bn254_g1_scalar_mul_syscall( call_result, input, input_sz, - FD_FEATURE_ACTIVE( vm->instr_ctx->txn_ctx->slot, &vm->instr_ctx->txn_ctx->features, fix_alt_bn128_multiplication_input_length ) )==0 ) ) { + FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->txn_ctx->bank, fix_alt_bn128_multiplication_input_length ) )==0 ) ) { ret = 0UL; /* success */ } break; diff --git a/src/flamenco/vm/syscall/fd_vm_syscall_curve.c b/src/flamenco/vm/syscall/fd_vm_syscall_curve.c index 9bbddc28505..69b9e7ea912 100644 --- a/src/flamenco/vm/syscall/fd_vm_syscall_curve.c +++ b/src/flamenco/vm/syscall/fd_vm_syscall_curve.c @@ -434,7 +434,7 @@ fd_vm_syscall_sol_curve_multiscalar_mul( void * _vm, default: /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1262-L1271 */ - if( FD_FEATURE_ACTIVE( vm->instr_ctx->txn_ctx->slot, &vm->instr_ctx->txn_ctx->features, abort_on_invalid_curve ) ) { + if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->txn_ctx->bank, abort_on_invalid_curve ) ) ) { FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE ); return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */ } diff --git a/src/flamenco/vm/syscall/fd_vm_syscall_runtime.c b/src/flamenco/vm/syscall/fd_vm_syscall_runtime.c index 72ca0755fb8..b2cff2fc6b7 100644 --- a/src/flamenco/vm/syscall/fd_vm_syscall_runtime.c +++ b/src/flamenco/vm/syscall/fd_vm_syscall_runtime.c @@ -79,7 +79,7 @@ fd_vm_syscall_sol_get_epoch_schedule_sysvar( /**/ void * _vm, fd_epoch_schedule_t schedule; if( FD_UNLIKELY( !fd_sysvar_cache_epoch_schedule_read( instr_ctx->sysvar_cache, &schedule ) ) ) { - FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->err.exec_err_idx ); return FD_VM_ERR_INVAL; } memcpy( var_query.haddr, &schedule, sizeof(fd_epoch_schedule_t) ); @@ -159,7 +159,7 @@ fd_vm_syscall_sol_get_last_restart_slot_sysvar( /**/ void * _vm, fd_sol_sysvar_last_restart_slot_t last_restart_slot; if( FD_UNLIKELY( !fd_sysvar_cache_last_restart_slot_read( vm->instr_ctx->sysvar_cache, &last_restart_slot ) ) ) { - FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->err.exec_err_idx ); return FD_VM_ERR_INVAL; } @@ -309,7 +309,7 @@ fd_vm_syscall_sol_get_stack_height( /**/ void * _vm, FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST ); - *_ret = vm->instr_ctx->txn_ctx->instr_stack_sz; + *_ret = vm->instr_ctx->txn_ctx->instr.stack_sz; return FD_VM_SUCCESS; } @@ -327,7 +327,7 @@ fd_vm_syscall_sol_get_return_data( /**/ void * _vm, FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST ); /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1467 */ - fd_txn_return_data_t const * return_data = &vm->instr_ctx->txn_ctx->return_data; + fd_txn_return_data_t const * return_data = &vm->instr_ctx->txn_ctx->details.return_data; /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1468 */ ulong length = fd_ulong_min( return_data->len, sz ); @@ -408,7 +408,7 @@ fd_vm_syscall_sol_set_return_data( /**/ void * _vm, return err; } - fd_txn_return_data_t * return_data = &instr_ctx->txn_ctx->return_data; + fd_txn_return_data_t * return_data = &instr_ctx->txn_ctx->details.return_data; return_data->len = src_sz; if( FD_LIKELY( src_sz!=0UL ) ) { @@ -455,11 +455,11 @@ fd_vm_syscall_sol_get_processed_sibling_instruction( /* Get the current instruction stack height. This value is 1-indexed (top level instruction has a stack height of 1). https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1517 */ - ulong stack_height = vm->instr_ctx->txn_ctx->instr_stack_sz; + ulong stack_height = vm->instr_ctx->txn_ctx->instr.stack_sz; /* Reverse iterate through the instruction trace, ignoring anything except instructions on the same level. https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1518-L1522 */ - ulong instruction_trace_length = vm->instr_ctx->txn_ctx->instr_trace_length; + ulong instruction_trace_length = vm->instr_ctx->txn_ctx->instr.trace_length; ulong reverse_index_at_stack_height = 0UL; fd_exec_instr_trace_entry_t * found_instruction_context = NULL; for( ulong index_in_trace=instruction_trace_length; index_in_trace>0UL; index_in_trace-- ) { @@ -468,7 +468,7 @@ fd_vm_syscall_sol_get_processed_sibling_instruction( This error can never happen */ /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1527-L1529 */ - fd_exec_instr_trace_entry_t * instruction_context = &vm->instr_ctx->txn_ctx->instr_trace[ index_in_trace-1UL ]; + fd_exec_instr_trace_entry_t * instruction_context = &vm->instr_ctx->txn_ctx->instr.trace[ index_in_trace-1UL ]; if( FD_LIKELY( instruction_context->stack_heightsysvar_cache, &epoch_rewards ) ) ) { - FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->instr_err_idx ); + FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->err.exec_err_idx ); return FD_VM_ERR_INVAL; } memcpy( out, &epoch_rewards, sizeof(fd_sysvar_epoch_rewards_t) ); diff --git a/src/flamenco/vm/syscall/fd_vm_syscall_util.c b/src/flamenco/vm/syscall/fd_vm_syscall_util.c index 7207c46bc47..bf0d8a07a6d 100644 --- a/src/flamenco/vm/syscall/fd_vm_syscall_util.c +++ b/src/flamenco/vm/syscall/fd_vm_syscall_util.c @@ -207,7 +207,7 @@ fd_vm_syscall_sol_log_data( /**/ void * _vm, /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L156 */ char msg[ FD_LOG_COLLECTOR_MAX ]; - ulong bytes_written = fd_log_collector_check_and_truncate( &vm->instr_ctx->txn_ctx->log_collector, msg_sz ); + ulong bytes_written = fd_log_collector_check_and_truncate( &vm->instr_ctx->txn_ctx->log.log_collector, msg_sz ); if( FD_LIKELY( bytes_written < ULONG_MAX ) ) { fd_memcpy( msg, "Program data: ", 14 ); char * buf = msg + 14; diff --git a/src/flamenco/vm/syscall/test_vm_syscall_curve.c b/src/flamenco/vm/syscall/test_vm_syscall_curve.c index a0ee814c0d6..64d876bfe5b 100644 --- a/src/flamenco/vm/syscall/test_vm_syscall_curve.c +++ b/src/flamenco/vm/syscall/test_vm_syscall_curve.c @@ -1,5 +1,6 @@ #include "fd_vm_syscall.h" #include "../test_vm_util.h" +#include "../../runtime/fd_bank.h" static inline void set_memory_region( uchar * mem, ulong sz ) { for( ulong i=0UL; itxn_ctx)->features ); + fd_bank_t bank[1]; + test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx, bank ); + + fd_features_enable_all( fd_bank_features_modify( txn_ctx->bank ) ); int vm_ok = !!fd_vm_init( /* vm */ vm, @@ -103,8 +106,8 @@ main( int argc, /* mem_regions_cnt */ 0UL, /* mem_regions_accs */ NULL, /* is_deprecated */ 0, - /* direct mapping */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ), - /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ), + /* direct mapping */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ), + /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ), /* dump_syscall_to_pb */ 0 ); FD_TEST( vm_ok ); diff --git a/src/flamenco/vm/syscall/test_vm_syscalls.c b/src/flamenco/vm/syscall/test_vm_syscalls.c index 1f72894ce92..dcb272807bb 100644 --- a/src/flamenco/vm/syscall/test_vm_syscalls.c +++ b/src/flamenco/vm/syscall/test_vm_syscalls.c @@ -1,5 +1,6 @@ #include "fd_vm_syscall.h" #include "../test_vm_util.h" +#include "../../runtime/fd_bank.h" static inline void set_memory_region( uchar * mem, ulong sz ) { for( ulong i=0UL; iinstr_ctx->txn_ctx->features, one_offs, 1U, slot ); + fd_features_enable_one_offs( fd_bank_features_modify( vm_ctx->instr_ctx->txn_ctx->bank ), one_offs, 1U, slot ); vm_ctx->direct_mapping = enable; vm_ctx->stricter_abi_and_runtime_constraints = enable; } @@ -121,7 +122,7 @@ test_vm_syscall_sol_log( char const * test_case_name, int expected_err, uchar * expected_log, ulong expected_log_sz ) { - fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log.log_collector; ulong log_vec_len = fd_log_collector_debug_len( log ); ulong ret = 0UL; @@ -150,7 +151,7 @@ test_vm_syscall_sol_log_64( char const * test_case_name, int expected_err, uchar * expected_log, ulong expected_log_sz ) { - fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log.log_collector; ulong log_vec_len = fd_log_collector_debug_len( log ); ulong ret = 0UL; @@ -176,7 +177,7 @@ test_vm_syscall_sol_log_data( char const * test_case_name, int expected_err, uchar * expected_log, ulong expected_log_sz ) { - fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log_collector; + fd_log_collector_t * log = &vm->instr_ctx->txn_ctx->log.log_collector; ulong log_vec_len = fd_log_collector_debug_len( log ); ulong ret = 0UL; @@ -243,7 +244,8 @@ main( int argc, fd_exec_instr_ctx_t instr_ctx[1]; fd_exec_txn_ctx_t txn_ctx[1]; - test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx ); + fd_bank_t bank[1]; + test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx, bank ); int vm_ok = !!fd_vm_init( /* vm */ vm, @@ -266,8 +268,8 @@ main( int argc, /* mem_regions_cnt */ (uint)mem_regions_cnt, /* mem_regions_accs */ NULL, /* is_deprecated */ 0, - /* direct mapping */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ), - /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ), + /* direct mapping */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ), + /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ), /* dump_syscall_to_pb */ 0 ); FD_TEST( vm_ok ); @@ -703,7 +705,7 @@ main( int argc, expected_log_sz += _cpy_sz; \ } while(0) - fd_log_collector_init( &vm->instr_ctx->txn_ctx->log_collector, 1 ); + fd_log_collector_init( &vm->instr_ctx->txn_ctx->log.log_collector, 1 ); expected_log_sz = 0UL; APPEND( "Program log: hello world", 24UL ); @@ -744,7 +746,7 @@ main( int argc, // test for collecting log_64 at the heap region - fd_log_collector_init( &vm->instr_ctx->txn_ctx->log_collector, 1 ); + fd_log_collector_init( &vm->instr_ctx->txn_ctx->log.log_collector, 1 ); expected_log_sz = 0UL; @@ -764,7 +766,7 @@ main( int argc, // test for collecting log_data at the heap region - fd_log_collector_init( &vm->instr_ctx->txn_ctx->log_collector, 1 ); + fd_log_collector_init( &vm->instr_ctx->txn_ctx->log.log_collector, 1 ); expected_log_sz = 0UL; diff --git a/src/flamenco/vm/test_vm_instr.c b/src/flamenco/vm/test_vm_instr.c index fdb26863ae7..48bf3941ecd 100644 --- a/src/flamenco/vm/test_vm_instr.c +++ b/src/flamenco/vm/test_vm_instr.c @@ -5,6 +5,7 @@ #include "fd_vm_base.h" #include "fd_vm_private.h" #include "test_vm_util.h" +#include "../runtime/fd_bank.h" #include #include #include @@ -446,7 +447,8 @@ run_input( test_input_t const * input, fd_exec_instr_ctx_t instr_ctx[1]; fd_exec_txn_ctx_t txn_ctx[1]; - test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx ); + fd_bank_t bank[1]; + test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx, bank ); int vm_ok = !!fd_vm_init( /* vm */ vm, @@ -469,8 +471,8 @@ run_input( test_input_t const * input, /* mem_regions_cnt */ input->region_boundary_cnt ? input->region_boundary_cnt : 1, /* mem_regions_accs */ NULL, /* is_deprecated */ 0, - /* direct mapping */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ), - /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ), + /* direct mapping */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ), + /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ), /* dump_syscall_to_pb */ 0 ); assert( vm_ok ); diff --git a/src/flamenco/vm/test_vm_interp.c b/src/flamenco/vm/test_vm_interp.c index 302914d3787..fb993d2ed66 100644 --- a/src/flamenco/vm/test_vm_interp.c +++ b/src/flamenco/vm/test_vm_interp.c @@ -2,6 +2,7 @@ #include "fd_vm_base.h" #include "fd_vm_private.h" #include "test_vm_util.h" +#include "../runtime/fd_bank.h" #include /* malloc */ static int @@ -53,8 +54,8 @@ test_program_success( char * test_case_name, /* mem_regions_cnt */ 0UL, /* mem_regions_accs */ NULL, /* is_deprecated */ 0, - /* direct mapping */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ), - /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ), + /* direct mapping */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ), + /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ), /* dump_syscall_to_pb */ 0 ); FD_TEST( vm_ok ); @@ -226,7 +227,8 @@ test_0cu_exit( void ) { fd_exec_instr_ctx_t instr_ctx[1]; fd_exec_txn_ctx_t txn_ctx[1]; - test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx ); + fd_bank_t bank[1]; + test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx, bank ); /* Ensure the VM exits with success if the CU count after the final exit instruction reaches zero. */ @@ -252,8 +254,8 @@ test_0cu_exit( void ) { /* mem_regions_cnt */ 0UL, /* mem_regions_accs */ NULL, /* is_deprecated */ 0, - /* direct mapping */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ), - /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ), + /* direct mapping */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ), + /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ), /* dump_syscall_to_pb */ 0 ); FD_TEST( vm_ok ); @@ -285,8 +287,8 @@ test_0cu_exit( void ) { /* mem_regions_cnt */ 0UL, /* mem_regions_accs */ NULL, /* is_deprecated */ 0, - /* direct mapping */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, account_data_direct_mapping ), - /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot, &instr_ctx->txn_ctx->features, stricter_abi_and_runtime_constraints ), + /* direct mapping */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, account_data_direct_mapping ), + /* stricter_abi_and_runtime_constraints */ FD_FEATURE_ACTIVE_BANK( instr_ctx->txn_ctx->bank, stricter_abi_and_runtime_constraints ), /* dump_syscall_to_pb */ 0 ); FD_TEST( vm_ok ); @@ -452,7 +454,8 @@ main( int argc, fd_exec_instr_ctx_t instr_ctx[1]; fd_exec_txn_ctx_t txn_ctx[1]; - test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx ); + fd_bank_t bank[1]; + test_vm_minimal_exec_instr_ctx( instr_ctx, txn_ctx, bank ); FD_TEST( fd_vm_syscall_register( syscalls, "accumulator", accumulator_syscall )==FD_VM_SUCCESS ); diff --git a/src/flamenco/vm/test_vm_util.c b/src/flamenco/vm/test_vm_util.c index 0dacab1b7d1..ccae5935b62 100644 --- a/src/flamenco/vm/test_vm_util.c +++ b/src/flamenco/vm/test_vm_util.c @@ -1,26 +1,30 @@ #include "test_vm_util.h" #include "../runtime/context/fd_exec_txn_ctx.h" +#include "../runtime/fd_bank.h" /* Generates a minimal instruction context to supply to fd_vm_t. For now, we just need to setup feature flags. */ void test_vm_minimal_exec_instr_ctx( fd_exec_instr_ctx_t * instr_ctx, - fd_exec_txn_ctx_t * txn_ctx ) { + fd_exec_txn_ctx_t * txn_ctx, + fd_bank_t * bank ) { memset( instr_ctx, 0, sizeof(fd_exec_instr_ctx_t) ); memset( txn_ctx, 0, sizeof(fd_exec_txn_ctx_t) ); + txn_ctx->bank = bank; + /* Setup feature flags */ - fd_features_disable_all( &txn_ctx->features ); - fd_features_set( &txn_ctx->features, fd_feature_id_query( TEST_VM_REJECT_CALLX_R10_FEATURE_PREFIX ), 0UL ); + fd_features_disable_all( fd_bank_features_modify( txn_ctx->bank ) ); + fd_features_set( fd_bank_features_modify( txn_ctx->bank ), fd_feature_id_query( TEST_VM_REJECT_CALLX_R10_FEATURE_PREFIX ), 0UL ); - txn_ctx->slot = 1UL; + fd_bank_slot_set( bank, 1UL ); instr_ctx->txn_ctx = txn_ctx; } void test_vm_clear_txn_ctx_err( fd_exec_txn_ctx_t * txn_ctx ) { - txn_ctx->exec_err = 0; - txn_ctx->exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE; + txn_ctx->err.exec_err = 0; + txn_ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE; return; } diff --git a/src/flamenco/vm/test_vm_util.h b/src/flamenco/vm/test_vm_util.h index f26759c7f8a..613a47bec51 100644 --- a/src/flamenco/vm/test_vm_util.h +++ b/src/flamenco/vm/test_vm_util.h @@ -11,7 +11,8 @@ FD_PROTOTYPES_BEGIN void test_vm_minimal_exec_instr_ctx( fd_exec_instr_ctx_t * instr_ctx, - fd_exec_txn_ctx_t * txn_ctx ); + fd_exec_txn_ctx_t * txn_ctx, + fd_bank_t * bank ); void test_vm_clear_txn_ctx_err( fd_exec_txn_ctx_t * txn_ctx );