Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 21 additions & 23 deletions src/discof/bank/fd_bank_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,32 +180,30 @@ 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 );
txn_ctx->err.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 );

/* 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_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_result[ fd_bank_err_from_runtime_err( txn_ctx->err.exec_err ) ]++;
continue;
}

/* 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
Expand All @@ -221,10 +219,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 );
Expand Down Expand Up @@ -273,7 +271,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 ));
}

}
Expand Down Expand Up @@ -364,9 +362,9 @@ handle_bundle( fd_bank_ctx_t * ctx,
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 ) ) {
txn_ctx->err.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->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;
}
Expand All @@ -388,8 +386,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 ));
Expand Down
24 changes: 12 additions & 12 deletions src/discof/exec/fd_exec_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,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] );
ctx->txn_ctx->err.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] );

/* 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 );
}
Expand Down Expand Up @@ -385,9 +385,9 @@ publish_txn_finalized_msg( fd_exec_tile_ctx_t * ctx,
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->err = !ctx->txn_ctx->err.is_committable;
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, 0UL, 0UL );
Expand Down
14 changes: 7 additions & 7 deletions src/flamenco/log_collector/fd_log_collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
} 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 );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/runtime/context/fd_exec_instr_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
5 changes: 2 additions & 3 deletions src/flamenco/runtime/context/fd_exec_txn_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,14 @@ fd_exec_txn_ctx_setup_basic( fd_exec_txn_ctx_t * ctx ) {
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->err.exec_err = 0;
ctx->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE;
ctx->current_instr_idx = 0;
}

Expand Down
39 changes: 19 additions & 20 deletions src/flamenco/runtime/context/fd_exec_txn_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ typedef struct fd_exec_instr_trace_entry fd_exec_instr_trace_entry_t;
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;

fd_exec_stack_t * exec_stack;
Expand Down Expand Up @@ -77,7 +71,6 @@ struct fd_exec_txn_ctx {
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:
Expand Down Expand Up @@ -120,6 +113,16 @@ struct fd_exec_txn_ctx {
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 */

struct {
int is_committable;
int is_fees_only;
int txn_err;
/* These are error fields produced by instruction execution. */
int exec_err;
int exec_err_kind;
int exec_err_idx;
} err;

fd_capture_ctx_t * capture_ctx;

/* The instr_infos for the entire transaction are allocated at the start of
Expand Down Expand Up @@ -147,10 +150,6 @@ struct fd_exec_txn_ctx {

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;

Expand Down Expand Up @@ -184,15 +183,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

Expand All @@ -201,11 +200,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 *
Expand Down
23 changes: 13 additions & 10 deletions src/flamenco/runtime/fd_executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ fd_executor_check_status_cache( fd_exec_txn_ctx_t * txn_ctx ) {

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 );
if( FD_UNLIKELY( found ) ) return FD_RUNTIME_TXN_ERR_ALREADY_PROCESSED;
if( FD_UNLIKELY( found ) ) {
FD_LOG_WARNING(( "transaction already processed: %d", found ));
return FD_RUNTIME_TXN_ERR_ALREADY_PROCESSED;
}

return FD_RUNTIME_EXECUTE_SUCCESS;
}
Expand Down Expand Up @@ -1248,7 +1251,7 @@ 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;
}

Expand All @@ -1266,7 +1269,7 @@ 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;
}

Expand Down Expand Up @@ -1296,7 +1299,7 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx,

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;
}

Expand All @@ -1316,7 +1319,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 );
}

Expand All @@ -1333,14 +1336,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 );
}
}

Expand Down Expand Up @@ -1589,8 +1592,8 @@ fd_execute_txn( fd_exec_txn_ctx_t * txn_ctx ) {

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;
}
Expand Down
Loading
Loading