Line data Source code
1 : #include "fd_native_cpi.h" 2 : #include "../fd_account.h" 3 : #include "../fd_executor.h" 4 : #include "../../vm/syscall/fd_vm_syscall.h" 5 : #include "../../../util/bits/fd_uwide.h" 6 : 7 : int 8 : fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx, 9 : fd_system_program_instruction_t const * instr, 10 : fd_vm_rust_account_meta_t const * acct_metas, 11 : ulong acct_metas_len, 12 : fd_pubkey_t const * signers, 13 666 : ulong signers_cnt ) { 14 666 : fd_instr_info_t * instr_info = &ctx->txn_ctx->instr_infos[ ctx->txn_ctx->instr_info_cnt ]; 15 666 : ctx->txn_ctx->instr_info_cnt++; 16 666 : if( FD_UNLIKELY( ctx->txn_ctx->instr_info_cnt>FD_MAX_INSTRUCTION_TRACE_LENGTH ) ) { 17 0 : return FD_EXECUTOR_INSTR_ERR_MAX_INSN_TRACE_LENS_EXCEEDED; 18 0 : } 19 : 20 666 : fd_instruction_account_t instruction_accounts[256]; 21 666 : ulong instruction_accounts_cnt; 22 : 23 : /* fd_vm_prepare_instruction will handle missing/invalid account case */ 24 666 : instr_info->program_id_pubkey = fd_solana_system_program_id; 25 666 : instr_info->program_id = UCHAR_MAX; 26 : 27 4122 : for( ulong i = 0UL; i < ctx->txn_ctx->accounts_cnt; i++ ) { 28 3996 : if( !memcmp( fd_solana_system_program_id.key, ctx->txn_ctx->accounts[i].key, sizeof(fd_pubkey_t) ) ) { 29 540 : instr_info->program_id = (uchar)i; 30 540 : break; 31 540 : } 32 3996 : } 33 : 34 : /* TODO: Lamport check may be redundant */ 35 666 : ulong starting_lamports_h = 0; 36 666 : ulong starting_lamports_l = 0; 37 666 : uchar acc_idx_seen[256]; 38 666 : memset( acc_idx_seen, 0, 256 ); 39 : 40 666 : instr_info->acct_cnt = (ushort)acct_metas_len; 41 2106 : for ( ulong j = 0; j < acct_metas_len; j++ ) { 42 1440 : fd_vm_rust_account_meta_t const * acct_meta = &acct_metas[j]; 43 : 44 3039 : for ( ulong k = 0; k < ctx->instr->acct_cnt; k++ ) { 45 3039 : if ( memcmp( acct_meta->pubkey, ctx->instr->acct_pubkeys[k].uc, sizeof(fd_pubkey_t) ) == 0 ) { 46 1440 : instr_info->acct_pubkeys[j] = ctx->instr->acct_pubkeys[k]; 47 1440 : instr_info->acct_txn_idxs[j] = ctx->instr->acct_txn_idxs[k]; 48 1440 : instr_info->acct_flags[j] = 0; 49 1440 : instr_info->borrowed_accounts[j] = ctx->instr->borrowed_accounts[k]; 50 : 51 1440 : instr_info->is_duplicate[j] = acc_idx_seen[k]; 52 1440 : if( FD_LIKELY( !acc_idx_seen[k] ) ) { 53 : /* This is the first time seeing this account */ 54 1419 : acc_idx_seen[k] = 1; 55 1419 : if( instr_info->borrowed_accounts[j]->const_meta != NULL ) { 56 1419 : fd_uwide_inc( &starting_lamports_h, &starting_lamports_l, 57 1419 : starting_lamports_h, starting_lamports_l, 58 1419 : instr_info->borrowed_accounts[j]->const_meta->info.lamports ); 59 1419 : } 60 1419 : } 61 : 62 1440 : if( acct_meta->is_writable ) { 63 1440 : instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_WRITABLE; 64 1440 : } 65 1440 : if( acct_meta->is_signer ) { 66 828 : instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_SIGNER; 67 828 : } 68 1440 : break; 69 1440 : } 70 3039 : } 71 : 72 1440 : instr_info->starting_lamports_h = starting_lamports_h; 73 1440 : instr_info->starting_lamports_l = starting_lamports_l; 74 1440 : } 75 : 76 666 : fd_bincode_encode_ctx_t ctx2; 77 666 : uchar buf[4096UL]; // Size that is large enough for the instruction 78 666 : ctx2.data = buf; 79 666 : ctx2.dataend = (uchar*)ctx2.data + sizeof(buf); 80 666 : int err = fd_system_program_instruction_encode( instr, &ctx2 ); 81 666 : if( err ) { 82 0 : FD_LOG_WARNING(( "Encode failed" )); 83 0 : return FD_EXECUTOR_INSTR_ERR_FATAL; 84 0 : } 85 : 86 666 : instr_info->data = buf; 87 666 : instr_info->data_sz = sizeof(buf); 88 666 : int exec_err = fd_vm_prepare_instruction( ctx->instr, instr_info, ctx, instruction_accounts, 89 666 : &instruction_accounts_cnt, signers, signers_cnt ); 90 666 : if( exec_err != FD_EXECUTOR_INSTR_SUCCESS ) { 91 180 : FD_LOG_WARNING(("Preparing instruction failed")); 92 180 : return exec_err; 93 180 : } 94 : 95 486 : return fd_execute_instr( ctx->txn_ctx, instr_info ); 96 666 : } 97 : 98 : void 99 : fd_native_cpi_create_account_meta( fd_pubkey_t const * key, uchar is_signer, 100 1416 : uchar is_writable, fd_vm_rust_account_meta_t * meta ) { 101 1416 : meta->is_signer = is_signer; 102 1416 : meta->is_writable = is_writable; 103 1416 : fd_memcpy( meta->pubkey, key->key, sizeof(fd_pubkey_t) ); 104 1416 : }