Skip to content
Merged
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
59 changes: 37 additions & 22 deletions src/flamenco/runtime/fd_account.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ fd_account_get_data( fd_account_meta_t * m ) {
return ((char *) m) + m->hlen;
}

/* Assert that enough ccounts were supplied to this instruction. Returns
FD_EXECUTOR_INSTR_SUCCESS if the number of accounts is as expected and
/* Assert that enough ccounts were supplied to this instruction. Returns
FD_EXECUTOR_INSTR_SUCCESS if the number of accounts is as expected and
FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS otherwise.
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L492-L503 */
static inline int
Expand All @@ -80,7 +80,7 @@ fd_account_check_num_insn_accounts( fd_exec_instr_ctx_t * ctx,
return FD_EXECUTOR_INSTR_SUCCESS;
}

/* fd_account_get_owner mirrors Anza function
/* fd_account_get_owner mirrors Anza function
solana_sdk::transaction_context:Borrowed_account::get_owner. Returns 0
iff the owner is retrieved successfully.
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L734-L738 */
Expand All @@ -98,7 +98,7 @@ fd_account_get_owner( fd_exec_instr_ctx_t const * ctx,
return (fd_pubkey_t const *) account->const_meta->info.owner;
}

/* fd_account_set_owner mirrors Anza function
/* fd_account_set_owner mirrors Anza function
solana_sdk::transaction_context:Borrowed_account::set_owner. Returns 0
iff the owner is set successfully. Acquires a writable handle. */
int
Expand Down Expand Up @@ -143,12 +143,12 @@ fd_account_set_lamports( fd_exec_instr_ctx_t const * ctx,
ulong instr_acc_idx,
ulong lamports );

/*
fd_account_checked_{add,sub}_lamports mirros Anza
/*
fd_account_checked_{add,sub}_lamports mirros Anza
add/removes lamports to/from an
account. Does not update global capitalization. Returns 0 on
success or an FD_EXECUTOR_INSTR_ERR_{...} code on failure.
Gracefully handles underflow. Acquires a writable handle.
Gracefully handles underflow. Acquires a writable handle.
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L798-L817 */

static inline int
Expand All @@ -159,7 +159,7 @@ fd_account_checked_add_lamports( fd_exec_instr_ctx_t const * ctx,
fd_borrowed_account_t * account = NULL;
do {
int err = fd_instr_borrowed_account_modify_idx( ctx, (uchar)instr_acc_idx, 0UL, &account );
if( FD_UNLIKELY( err ) ) {
if( FD_UNLIKELY( err ) ) {
FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
}
} while(0);
Expand All @@ -181,7 +181,7 @@ fd_account_checked_sub_lamports( fd_exec_instr_ctx_t const * ctx,
fd_borrowed_account_t * account = NULL;
do {
int err = fd_instr_borrowed_account_modify_idx( ctx, (uchar)instr_acc_idx, 0UL, &account );
if( FD_UNLIKELY( err ) ) {
if( FD_UNLIKELY( err ) ) {
FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
}
} while(0);
Expand All @@ -195,18 +195,18 @@ fd_account_checked_sub_lamports( fd_exec_instr_ctx_t const * ctx,
return fd_account_set_lamports( ctx, instr_acc_idx, balance_post );
}

/* fd_account_get_data_mut mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::set_lamports.
/* fd_account_get_data_mut mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::set_lamports.
Returns a writable slice of the account data (transaction wide).
Acquires a writable handle. This function assumes that the relevant
borrowed has already acquired exclusive write access.
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L824-L831 */
int
fd_account_get_data_mut( fd_exec_instr_ctx_t const * ctx,
int
fd_account_get_data_mut( fd_exec_instr_ctx_t const * ctx,
ulong instr_acc_idx,
uchar * * data_out,
ulong * dlen_out );

/* TODO: Implement fd_account_spare_data_capacity_mut which is used in direct mapping */

/* fd_account_set_data_from_slice mirrors Anza function
Expand Down Expand Up @@ -244,7 +244,7 @@ fd_account_is_rent_exempt_at_data_length( fd_exec_instr_ctx_t const * ctx,
assert( meta != NULL );
fd_rent_t rent = ctx->epoch_ctx->epoch_bank.rent;
ulong min_balance = fd_rent_exempt_minimum_balance( &rent, meta->dlen );
return meta->info.lamports >= min_balance;
return meta->info.lamports >= min_balance;
}

/* fd_account_is_executable returns 1 if the given account has the
Expand All @@ -260,7 +260,7 @@ fd_account_is_executable( fd_account_meta_t const * meta ) {
/* fd_account_is_executable_internal was introduced to move towards deprecating the `is_executable` flag.
It returns true if the `remove_accounts_executable_flag_checks` feature is inactive AND fd_account_is_executable
return true. This is newly used in account modification logic to eventually allow "executable" accounts to be
modified.
modified.
https://github.com/anza-xyz/agave/blob/89872fdb074e6658646b2b57a299984f0059cc84/sdk/transaction-context/src/lib.rs#L1052-L1060 */

FD_FN_PURE static inline int
Expand All @@ -280,8 +280,8 @@ fd_account_set_executable( fd_exec_instr_ctx_t const * ctx,
ulong instr_acc_idx,
int is_executable );

/* fd_account_get_rent_epoch mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::get_rent_epoch.
/* fd_account_get_rent_epoch mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::get_rent_epoch.
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1040-1042 */

static inline ulong
Expand Down Expand Up @@ -325,7 +325,7 @@ fd_account_is_owned_by_current_program( fd_instr_info_t const * info,
return 0==memcmp( info->program_id_pubkey.key, acct->info.owner, sizeof(fd_pubkey_t) );
}

/* fd_account_can_data_be changed mirrors Anza function
/* fd_account_can_data_be changed mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::can_data_be_changed.
https://github.com/anza-xyz/agave/blob/89872fdb074e6658646b2b57a299984f0059cc84/sdk/transaction-context/src/lib.rs#L1136-L1152 */
static inline int
Expand Down Expand Up @@ -356,8 +356,8 @@ fd_account_can_data_be_changed( fd_exec_instr_ctx_t const * ctx,
return 1;
}

/* fd_account_can_data_be_resized mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::can_data_be_resized
/* fd_account_can_data_be_resized mirrors Anza function
solana_sdk::transaction_context::BorrowedAccount::can_data_be_resized
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1096-L1119
*/
static inline int
Expand Down Expand Up @@ -392,7 +392,7 @@ fd_account_can_data_be_resized( fd_exec_instr_ctx_t const * instr_ctx,
}

/* fd_account_update_acounts_resize_delta mirrors Anza function
solana_sdk::transaction_context:BorrowedAccount::update_accounts_resize_delta.
solana_sdk::transaction_context:BorrowedAccount::update_accounts_resize_delta.
https://github.com/anza-xyz/agave/blob/b5f5c3cdd3f9a5859c49ebc27221dc27e143d760/sdk/src/transaction_context.rs#L1128-L1138 */

int
Expand Down Expand Up @@ -426,6 +426,21 @@ fd_account_find_idx_of_insn_account( fd_exec_instr_ctx_t const * ctx,
return -1;
}

/* Backward scan over transaction accounts
Returns -1 if not found
https://github.com/anza-xyz/agave/blob/228d3b3427abcf3ecfe9757bfa5de411fc020773/sdk/src/transaction_context.rs#L249
*/
static inline int
fd_account_find_index_of_program_account( fd_exec_txn_ctx_t const * ctx,
fd_pubkey_t * pubkey ) {
for( ulong i=ctx->accounts_cnt; i>0UL; i-- ) {
if( 0==memcmp( pubkey, &ctx->accounts[ i-1UL ], sizeof(fd_pubkey_t) ) ) {
return (int)((ushort)i);
}
}
return -1;
}

FD_PROTOTYPES_END

#endif /* HEADER_fd_src_flamenco_runtime_fd_account_h */
66 changes: 38 additions & 28 deletions src/flamenco/vm/syscall/fd_vm_syscall_cpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,37 +201,47 @@ fd_vm_prepare_instruction( fd_instr_info_t const * caller_instr,
}
}

/* Check that the program account is executable. We need to ensure that the
program account is a valid instruction account.
https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/program-runtime/src/invoke_context.rs#L635-L648 */
fd_borrowed_account_t * program_rec = NULL;

/* Caller is in charge of setting an appropriate sentinel value (i.e., UCHAR_MAX) for callee_instr->program_id if not found. */
/* We allow dead accounts to be borrowed here because that's what agave currently does.
https://github.com/anza-xyz/agave/blob/838c1952595809a31520ff1603a13f2c9123aa51/program-runtime/src/invoke_context.rs#L453 */
int err = fd_txn_borrowed_account_view_idx_allow_dead( instr_ctx->txn_ctx, callee_instr->program_id, &program_rec );
if( FD_UNLIKELY( err ) ) {
/* https://github.com/anza-xyz/agave/blob/a9ac3f55fcb2bc735db0d251eda89897a5dbaaaa/program-runtime/src/invoke_context.rs#L434 */
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
}
if( FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot_ctx, lift_cpi_caller_restriction ) ) {
if( FD_UNLIKELY( -1==fd_account_find_index_of_program_account( instr_ctx->txn_ctx, &callee_instr->program_id_pubkey ) ) ) {
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
}
} else {
/* Check that the program account is executable. We need to ensure that the
program account is a valid instruction account.
https://github.com/solana-labs/solana/blob/dbf06e258ae418097049e845035d7d5502fe1327/program-runtime/src/invoke_context.rs#L635-L648 */
fd_borrowed_account_t * program_rec = NULL;

if( FD_UNLIKELY( fd_account_find_idx_of_insn_account( instr_ctx, &callee_instr->program_id_pubkey )==-1 ) ) {
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
}
/* Caller is in charge of setting an appropriate sentinel value (i.e., UCHAR_MAX) for callee_instr->program_id if not found. */
/* We allow dead accounts to be borrowed here because that's what agave currently does.
*/
int err = fd_txn_borrowed_account_view_idx_allow_dead( instr_ctx->txn_ctx, callee_instr->program_id, &program_rec );
if( FD_UNLIKELY( err ) ) {
/* https://github.com/anza-xyz/agave/blob/a9ac3f55fcb2bc735db0d251eda89897a5dbaaaa/program-runtime/src/invoke_context.rs#L434 */
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
}

fd_account_meta_t const * program_meta = program_rec->const_meta;
if( FD_UNLIKELY( fd_account_find_idx_of_insn_account( instr_ctx, &callee_instr->program_id_pubkey )==-1 ) ) {
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
}

if( FD_UNLIKELY( !fd_account_is_executable( program_meta ) ) ) {
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE;
if( !FD_FEATURE_ACTIVE( instr_ctx->txn_ctx->slot_ctx, remove_accounts_executable_flag_checks ) ) {
fd_account_meta_t const * program_meta = program_rec->const_meta;
if( FD_UNLIKELY( !fd_account_is_executable( program_meta ) ) ) {
FD_BASE58_ENCODE_32_BYTES( callee_instr->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 );
return FD_EXECUTOR_INSTR_ERR_ACC_NOT_EXECUTABLE;
}
}
}

*instruction_accounts_cnt = duplicate_indicies_cnt;
Expand Down