Skip to content
Draft
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
31 changes: 17 additions & 14 deletions src/discof/bank/fd_bank_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef struct {
fd_banks_t * banks;
fd_spad_t * exec_spad;

fd_writable_acc_buf_t writable_acc_arr[ FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_TRANSACTION ];

fd_exec_txn_ctx_t txn_ctx[1];

struct {
Expand All @@ -62,11 +64,11 @@ FD_FN_PURE static inline ulong
scratch_footprint( fd_topo_tile_t const * tile ) {
(void)tile;
ulong l = FD_LAYOUT_INIT;
l = FD_LAYOUT_APPEND( l, alignof( fd_bank_ctx_t ), sizeof( fd_bank_ctx_t ) );
l = FD_LAYOUT_APPEND( l, FD_BLAKE3_ALIGN, FD_BLAKE3_FOOTPRINT );
l = FD_LAYOUT_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT(0) );
l = FD_LAYOUT_APPEND( l, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ) );
l = FD_LAYOUT_APPEND( l, fd_txncache_align(), fd_txncache_footprint( tile->bank.max_live_slots ) );
l = FD_LAYOUT_APPEND( l, alignof(fd_bank_ctx_t), sizeof(fd_bank_ctx_t) );
l = FD_LAYOUT_APPEND( l, FD_BLAKE3_ALIGN, FD_BLAKE3_FOOTPRINT );
l = FD_LAYOUT_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT(0) );
l = FD_LAYOUT_APPEND( l, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ) );
l = FD_LAYOUT_APPEND( l, fd_txncache_align(), fd_txncache_footprint( tile->bank.max_live_slots ) );
return FD_LAYOUT_FINI( l, scratch_align() );
}

Expand Down Expand Up @@ -161,7 +163,7 @@ handle_microblock( fd_bank_ctx_t * ctx,

txn->flags &= ~FD_TXN_P_FLAGS_SANITIZE_SUCCESS;

int err = fd_runtime_prepare_and_execute_txn( ctx->banks, ctx->_bank_idx, txn_ctx, txn, ctx->exec_spad, NULL, 0 );
int err = fd_runtime_prepare_and_execute_txn( ctx->banks, ctx->_bank_idx, txn_ctx, txn, ctx->exec_spad, ctx->writable_acc_arr, NULL, 0 );
if( FD_UNLIKELY( !(txn_ctx->flags & FD_TXN_P_FLAGS_SANITIZE_SUCCESS ) ) ) {
ctx->metrics.txn_result[ fd_bank_err_from_runtime_err( err ) ]++;
continue;
Expand Down Expand Up @@ -235,14 +237,14 @@ handle_microblock( fd_bank_ctx_t * ctx,
fork and diverge, so the link from here til PoH mixin must be
completely reliable with nothing dropped.

fd_runtime_finalize_txn checks if the transaction fits into the
fd_runtime_commit_txn checks if the transaction fits into the
block with the cost tracker. If it doesn't fit, flags is set to
zero. A key invariant of the leader pipeline is that pack
ensures all transactions must fit already, so it is a fatal error
if that happens. We cannot reject the transaction here as there
would be no way to undo the partially applied changes to the bank
in finalize anyway. */
fd_runtime_finalize_txn( ctx->txn_ctx->funk, txn_ctx->status_cache, txn_ctx->xid, txn_ctx, bank, NULL );
fd_runtime_commit_txn( ctx->txn_ctx->funk, txn_ctx->status_cache, txn_ctx->xid, txn_ctx, bank, NULL );
FD_TEST( txn->flags );
}

Expand Down Expand Up @@ -304,6 +306,7 @@ handle_bundle( fd_bank_ctx_t * ctx,
ulong sz,
ulong begin_tspub,
fd_stem_context_t * stem ) {

uchar * dst = (uchar *)fd_chunk_to_laddr( ctx->out_mem, ctx->out_chunk );
fd_txn_p_t * txns = (fd_txn_p_t *)dst;

Expand All @@ -326,7 +329,7 @@ handle_bundle( fd_bank_ctx_t * ctx,

fd_exec_txn_ctx_t txn_ctx[ 1 ]; // TODO ... bank manager ?
txn->flags &= ~(FD_TXN_P_FLAGS_SANITIZE_SUCCESS | FD_TXN_P_FLAGS_EXECUTE_SUCCESS);
int err = fd_runtime_prepare_and_execute_txn( NULL, ULONG_MAX, txn_ctx, txn, NULL, NULL, 0 ); /* TODO ... */
int err = fd_runtime_prepare_and_execute_txn( NULL, ULONG_MAX, txn_ctx, txn, NULL, NULL, NULL, 0 ); /* TODO ... */

transaction_err[ i ] = err;
if( FD_UNLIKELY( err ) ) {
Expand Down Expand Up @@ -493,11 +496,11 @@ unprivileged_init( fd_topo_t * topo,
void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );

FD_SCRATCH_ALLOC_INIT( l, scratch );
fd_bank_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_bank_ctx_t ), sizeof( fd_bank_ctx_t ) );
void * blake3 = FD_SCRATCH_ALLOC_APPEND( l, FD_BLAKE3_ALIGN, FD_BLAKE3_FOOTPRINT );
void * bmtree = FD_SCRATCH_ALLOC_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT(0) );
void * exec_spad = FD_SCRATCH_ALLOC_APPEND( l, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ) );
void * _txncache = FD_SCRATCH_ALLOC_APPEND( l, fd_txncache_align(), fd_txncache_footprint( tile->bank.max_live_slots ) );
fd_bank_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_bank_ctx_t ), sizeof( fd_bank_ctx_t ) );
void * blake3 = FD_SCRATCH_ALLOC_APPEND( l, FD_BLAKE3_ALIGN, FD_BLAKE3_FOOTPRINT );
void * bmtree = FD_SCRATCH_ALLOC_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT(0) );
void * exec_spad = FD_SCRATCH_ALLOC_APPEND( l, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_DEFAULT ) );
void * _txncache = FD_SCRATCH_ALLOC_APPEND( l, fd_txncache_align(), fd_txncache_footprint( tile->bank.max_live_slots ) );

#define NONNULL( x ) (__extension__({ \
__typeof__((x)) __x = (x); \
Expand Down
12 changes: 9 additions & 3 deletions src/discof/exec/fd_exec_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,16 @@ typedef struct fd_exec_tile_ctx {

/* A transaction can be executed as long as there is a valid handle to
a funk_txn and a bank. These are queried from fd_banks_t and
fd_funk_t.
TODO: These should probably be made read-only handles. */
fd_funk_t. */
fd_banks_t * banks;
fd_funk_t funk[ 1 ];

/* An array for writable accounts. This is a staging buffer for
transactions. The buffer is sized to be large enough to hold all
writable accounts for a transaction with 10MiB for each account
and up to 64 writable accounts. */
fd_writable_acc_buf_t writable_accounts_arr[ FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_TRANSACTION ];

fd_txncache_t * txncache;

fd_vote_tracker_t * vote_tracker;
Expand Down Expand Up @@ -121,6 +126,7 @@ during_frag( fd_exec_tile_ctx_t * ctx,
ctx->txn_ctx,
&txn->txn,
ctx->exec_spad,
ctx->writable_accounts_arr,
ctx->capture_ctx,
1 );
} else {
Expand Down Expand Up @@ -172,7 +178,7 @@ after_frag( fd_exec_tile_ctx_t * ctx,
}

if( FD_LIKELY( ctx->txn_ctx->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS ) ) {
fd_runtime_finalize_txn(
fd_runtime_commit_txn(
ctx->funk,
ctx->txncache,
&xid,
Expand Down
2 changes: 0 additions & 2 deletions src/flamenco/runtime/Local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ $(call add-objs, tests/fd_dump_pb,fd_flamenco)

$(call add-hdrs,fd_txn_account.h)
$(call add-objs,fd_txn_account,fd_flamenco)
$(call make-unit-test,test_txn_account,test_txn_account,fd_flamenco fd_funk fd_ballet fd_util)
$(call run-unit-test,test_txn_account,)

$(call add-hdrs,fd_bank.h)
$(call add-objs,fd_bank,fd_flamenco)
Expand Down
9 changes: 9 additions & 0 deletions src/flamenco/runtime/context/fd_exec_txn_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "../../../funk/fd_funk.h"
#include "../fd_compute_budget_details.h"
#include "../../../disco/pack/fd_microblock.h"
#include "../fd_runtime_const.h"

/* Return data for syscalls */

Expand All @@ -21,6 +22,12 @@ struct fd_txn_return_data {

typedef struct fd_txn_return_data fd_txn_return_data_t;

/* TODO:FIXME: magic number for alignment*/
struct __attribute__((aligned(8UL))) fd_writable_acc_buf {
uchar mem[ FD_RUNTIME_ACC_SZ_MAX ];
};
typedef struct fd_writable_acc_buf fd_writable_acc_buf_t;

/* fd_exec_txn_ctx_t is the context needed to execute a transaction. */

/* An entry in the instruction trace */
Expand Down Expand Up @@ -63,6 +70,8 @@ struct fd_exec_txn_ctx {
fd_spad_t * spad; /* Sized out to handle the worst case footprint of single transaction execution. */
fd_wksp_t * spad_wksp; /* Workspace for the spad. */

fd_writable_acc_buf_t * writable_accounts_arr;

fd_compute_budget_details_t compute_budget_details; /* Compute budget details */

/* Fields below here are not guaranteed to be local joins in txn execution. */
Expand Down
14 changes: 5 additions & 9 deletions src/flamenco/runtime/fd_executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,11 +952,11 @@ fd_executor_create_rollback_fee_payer_account( fd_exec_txn_ctx_t * txn_ctx,
ulong data_len = fd_txn_account_get_data_len( &txn_ctx->accounts[FD_FEE_PAYER_TXN_IDX] );
void * fee_payer_data = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, sizeof(fd_account_meta_t) + data_len );
fd_memcpy( fee_payer_data, (uchar *)meta, sizeof(fd_account_meta_t) + data_len );
if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new(
if( FD_UNLIKELY( !fd_txn_account_new(
txn_ctx->rollback_fee_payer_account,
fee_payer_key,
(fd_account_meta_t *)fee_payer_data,
1 ), txn_ctx->spad_wksp ) ) ) {
1 ) ) ) {
FD_LOG_CRIT(( "Failed to join txn account" ));
}

Expand Down Expand Up @@ -1420,15 +1420,14 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx,

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;
fd_wksp_t * data_wksp = NULL;

if( is_writable ) {
/* If the account is writable or a fee payer, then we need to create
staging regions for the account. If the account exists, we need to
copy the account data into the staging area; otherwise, we need to
initialize a new metadata. */

uchar * new_raw_data = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, FD_ACC_TOT_SZ_MAX );
uchar * new_raw_data = txn_ctx->writable_accounts_arr[idx].mem;
ulong dlen = !!meta ? meta->dlen : 0UL;

if( FD_LIKELY( meta ) ) {
Expand All @@ -1440,7 +1439,6 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx,
}

account_meta = (fd_account_meta_t *)new_raw_data;
data_wksp = txn_ctx->spad_wksp;

} else {
/* If the account is not writable, then we can simply initialize
Expand All @@ -1450,20 +1448,18 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx,

if( FD_LIKELY( err==FD_ACC_MGR_SUCCESS ) ) {
account_meta = (fd_account_meta_t *)meta;
data_wksp = fd_funk_wksp( txn_ctx->funk );
} else {
uchar * mem = fd_spad_alloc( txn_ctx->spad, FD_TXN_ACCOUNT_ALIGN, sizeof(fd_account_meta_t) );
account_meta = (fd_account_meta_t *)mem;
data_wksp = txn_ctx->spad_wksp;
fd_account_meta_init( account_meta );
}
}

if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new(
if( FD_UNLIKELY( !fd_txn_account_new(
txn_account,
acc,
account_meta,
is_writable ), data_wksp ) ) ) {
is_writable ) ) ) {
FD_LOG_CRIT(( "Failed to join txn account" ));
}

Expand Down
49 changes: 19 additions & 30 deletions src/flamenco/runtime/fd_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,14 +1033,8 @@ fd_runtime_save_account( fd_funk_t * funk,
fd_funk_txn_xid_t const * xid,
fd_txn_account_t * account,
fd_bank_t * bank,
fd_wksp_t * acc_data_wksp,
fd_capture_ctx_t * capture_ctx ) {

/* Join the transaction account */
if( FD_UNLIKELY( !fd_txn_account_join( account, acc_data_wksp ) ) ) {
FD_LOG_CRIT(( "fd_runtime_save_account: failed to join account" ));
}

/* Look up the previous version of the account from Funk */
FD_TXN_ACCOUNT_DECL( previous_account_version );
int err = fd_txn_account_init_from_funk_readonly( previous_account_version, account->pubkey, funk, xid );
Expand Down Expand Up @@ -1071,18 +1065,14 @@ fd_runtime_save_account( fd_funk_t * funk,
fd_runtime_finalize_account( funk, xid, account );
}

/* fd_runtime_finalize_txn is a helper used by the non-tpool transaction
executor to finalize borrowed account changes back into funk. It also
handles txncache insertion and updates to the vote/stake cache.
TODO: This function should probably be moved to fd_executor.c. */

void
fd_runtime_finalize_txn( fd_funk_t * funk,
fd_txncache_t * txncache,
fd_funk_txn_xid_t const * xid,
fd_exec_txn_ctx_t * txn_ctx,
fd_bank_t * bank,
fd_capture_ctx_t * capture_ctx ) {
fd_runtime_commit_txn( fd_funk_t * funk,
fd_txncache_t * txncache,
fd_funk_txn_xid_t const * xid,
fd_exec_txn_ctx_t * txn_ctx,
fd_bank_t * bank,
fd_capture_ctx_t * capture_ctx ) {

/* Collect fees */
FD_ATOMIC_FETCH_AND_ADD( fd_bank_txn_count_modify( bank ), 1UL );
Expand All @@ -1107,12 +1097,12 @@ fd_runtime_finalize_txn( fd_funk_t * funk,

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, txn_ctx->spad_wksp, capture_ctx );
fd_runtime_save_account( funk, xid, txn_ctx->rollback_nonce_account, 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, txn_ctx->spad_wksp, capture_ctx );
fd_runtime_save_account( funk, xid, txn_ctx->rollback_fee_payer_account, bank, capture_ctx );
}
} else {

Expand All @@ -1125,10 +1115,7 @@ fd_runtime_finalize_txn( fd_funk_t * funk,
continue;
}

fd_txn_account_t * acc_rec = fd_txn_account_join( &txn_ctx->accounts[i], txn_ctx->spad_wksp );
if( FD_UNLIKELY( !acc_rec ) ) {
FD_LOG_CRIT(( "fd_runtime_finalize_txn: failed to join account at idx %u", i ));
}
fd_txn_account_t * acc_rec = &txn_ctx->accounts[i];

if( dirty_vote_acc && 0==memcmp( fd_txn_account_get_owner( acc_rec ), &fd_solana_vote_program_id, sizeof(fd_pubkey_t) ) ) {
fd_vote_store_account( acc_rec, bank );
Expand All @@ -1142,7 +1129,7 @@ fd_runtime_finalize_txn( fd_funk_t * funk,
cache updates have been applied. */
fd_executor_reclaim_account( txn_ctx, &txn_ctx->accounts[i] );

fd_runtime_save_account( funk, xid, &txn_ctx->accounts[i], bank, txn_ctx->spad_wksp, capture_ctx );
fd_runtime_save_account( funk, xid, &txn_ctx->accounts[i], bank, capture_ctx );
}

/* We need to queue any existing program accounts that may have
Expand Down Expand Up @@ -1196,13 +1183,14 @@ fd_runtime_finalize_txn( fd_funk_t * funk,
}

int
fd_runtime_prepare_and_execute_txn( fd_banks_t * banks,
ulong bank_idx,
fd_exec_txn_ctx_t * txn_ctx,
fd_txn_p_t * txn,
fd_spad_t * exec_spad,
fd_capture_ctx_t * capture_ctx,
uchar do_sigverify ) {
fd_runtime_prepare_and_execute_txn( fd_banks_t * banks,
ulong bank_idx,
fd_exec_txn_ctx_t * txn_ctx,
fd_txn_p_t * txn,
fd_spad_t * exec_spad,
fd_writable_acc_buf_t * writable_accounts_arr,
fd_capture_ctx_t * capture_ctx,
uchar do_sigverify ) {
FD_SPAD_FRAME_BEGIN( exec_spad ) {
int exec_res = 0;

Expand All @@ -1222,6 +1210,7 @@ fd_runtime_prepare_and_execute_txn( fd_banks_t * banks,
txn_ctx->xid[0] = (fd_funk_txn_xid_t){ .ul = { slot, slot } };
txn_ctx->capture_ctx = capture_ctx;
txn_ctx->txn = *txn;
txn_ctx->writable_accounts_arr = writable_accounts_arr;

txn_ctx->flags = FD_TXN_P_FLAGS_SANITIZE_SUCCESS;
fd_exec_txn_ctx_setup_basic( txn_ctx );
Expand Down
27 changes: 14 additions & 13 deletions src/flamenco/runtime/fd_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -451,21 +451,22 @@ 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_exec_txn_ctx_t * txn_ctx,
fd_txn_p_t * txn,
fd_spad_t * exec_spad,
fd_capture_ctx_t * capture_ctx,
uchar do_sigverify );
fd_runtime_prepare_and_execute_txn( fd_banks_t * banks,
ulong bank_idx,
fd_exec_txn_ctx_t * txn_ctx,
fd_txn_p_t * txn,
fd_spad_t * exec_spad,
fd_writable_acc_buf_t * writable_accounts_arr,
fd_capture_ctx_t * capture_ctx,
uchar do_sigverify );

void
fd_runtime_finalize_txn( fd_funk_t * funk,
fd_txncache_t * txncache,
fd_funk_txn_xid_t const * xid,
fd_exec_txn_ctx_t * txn_ctx,
fd_bank_t * bank,
fd_capture_ctx_t * capture_ctx );
fd_runtime_commit_txn( fd_funk_t * funk,
fd_txncache_t * txncache,
fd_funk_txn_xid_t const * xid,
fd_exec_txn_ctx_t * txn_ctx,
fd_bank_t * bank,
fd_capture_ctx_t * capture_ctx );

/* Epoch Boundary *************************************************************/

Expand Down
Loading
Loading