Skip to content

Commit

Permalink
CPI: check if callee program exists
Browse files Browse the repository at this point in the history
  • Loading branch information
ravyu-jump committed Sep 6, 2024
1 parent 3c67d90 commit fc277e8
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 5 deletions.
1 change: 1 addition & 0 deletions contrib/test/syscall-fixtures/cpi.list
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dump/test-vectors/syscall/fixtures/cpi/cpi_callee_prog_in_txn_check.fix
5 changes: 4 additions & 1 deletion src/flamenco/runtime/program/fd_native_cpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx,
fd_instruction_account_t instruction_accounts[256];
ulong instruction_accounts_cnt;

/* fd_vm_prepare_instruction will handle missing/invalid account case */
instr_info->program_id_pubkey = fd_solana_system_program_id;
instr_info->program_id = UCHAR_MAX;

for( ulong i = 0UL; i < ctx->txn_ctx->accounts_cnt; i++ ) {
if( !memcmp( fd_solana_system_program_id.key, ctx->txn_ctx->accounts[i].key, sizeof(fd_pubkey_t) ) ) {
instr_info->program_id = (uchar)i;
Expand All @@ -33,7 +37,6 @@ fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx,
uchar acc_idx_seen[256];
memset( acc_idx_seen, 0, 256 );

instr_info->program_id_pubkey = fd_solana_system_program_id;
instr_info->acct_cnt = (ushort)acct_metas_len;
for ( ulong j = 0; j < acct_metas_len; j++ ) {
fd_vm_rust_account_meta_t const * acct_meta = &acct_metas[j];
Expand Down
12 changes: 10 additions & 2 deletions src/flamenco/vm/syscall/fd_vm_syscall_cpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@ TODO: instruction calling convention: const parameters after non-const.
serialization format.
- callee_instr is not null.
- callee_instr->acct_pubkeys is at least as long as callee_instr->acct_cnt
- instr_ctx->txn_ctx->accounts_cnt is less than USHORT_MAX.
- instr_ctx->txn_ctx->accounts_cnt is less than UCHAR_MAX.
This is likely because the transaction is limited to 256 accounts.
- callee_instr->program_id is set to UCHAR_MAX if account is not in instr_ctx->txn_ctx.
- instruction_accounts is a 256-length empty array.
Parameters:
Expand Down Expand Up @@ -315,8 +316,15 @@ fd_vm_prepare_instruction( fd_instr_info_t const * caller_instr,
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;
int err = fd_txn_borrowed_account_view( instr_ctx->txn_ctx, &callee_instr->program_id_pubkey, &program_rec );

/* Caller is in charge of setting an appropriate sentinel value (i.e., UCHAR_MAX) for callee_instr->program_id if not found. */
int err = fd_txn_borrowed_account_view_idx( 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 */
char id_b58[45]; ulong id_b58_len;
fd_base58_encode_32( callee_instr->program_id_pubkey.uc, &id_b58_len, id_b58 );
fd_log_collector_msg_many( instr_ctx, "Unknown program ", 16, 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;
}

Expand Down
5 changes: 3 additions & 2 deletions src/flamenco/vm/syscall/fd_vm_syscall_cpi_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ VM_SYSCALL_CPI_INSTRUCTION_TO_INSTR_FUNC( fd_vm_t * vm,
fd_pubkey_t const * program_id,
uchar const * cpi_instr_data,
fd_instr_info_t * out_instr ) {
/* fd_vm_prepare_instruction will handle the case where pubkey is missing */
out_instr->program_id_pubkey = *program_id;
out_instr->program_id = UCHAR_MAX;

/* Find the index of the CPI instruction's program account in the transaction */
/* TODO: what if this is not present? */
fd_pubkey_t * txn_accs = vm->instr_ctx->txn_ctx->accounts;
for( ulong i=0UL; i < vm->instr_ctx->txn_ctx->accounts_cnt; i++ ) {
if( !memcmp( program_id, &txn_accs[i], sizeof( fd_pubkey_t ) ) ) {
out_instr->program_id = (uchar)i;
out_instr->program_id_pubkey = txn_accs[i];
break;
}
}
Expand Down

0 comments on commit fc277e8

Please sign in to comment.