Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h 2 : #define HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h 3 : 4 : #include "../fd_executor_err.h" 5 : #include "../fd_runtime_const.h" 6 : #include "../../../ballet/txn/fd_txn.h" 7 : 8 0 : #define FD_INSTR_ACCT_FLAGS_IS_SIGNER (0x01U) 9 0 : #define FD_INSTR_ACCT_FLAGS_IS_WRITABLE (0x02U) 10 : 11 : /* The maximum possible size for the instruction data for any 12 : instruction, which is bounded by FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN 13 : (which is 10KB). */ 14 : #define FD_INSTR_DATA_MAX FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN 15 : 16 : struct fd_instruction_account { 17 : ushort index_in_transaction; 18 : ushort index_in_caller; 19 : ushort index_in_callee; 20 : uchar is_writable; 21 : uchar is_signer; 22 : }; 23 : 24 : typedef struct fd_instruction_account fd_instruction_account_t; 25 : 26 : struct fd_instr_info { 27 : uchar program_id; 28 : ushort acct_cnt; 29 : 30 : uchar data[ FD_INSTR_DATA_MAX ]; 31 : ushort data_sz; 32 : 33 : fd_instruction_account_t accounts[ FD_INSTR_ACCT_MAX ]; 34 : uchar is_duplicate[ FD_INSTR_ACCT_MAX ]; 35 : 36 : /* Stack height when this instruction was pushed onto the stack (including itself) */ 37 : uchar stack_height; 38 : 39 : /* TODO: convert to fd_uwide_t representation of uint_128 */ 40 : ulong starting_lamports_h; 41 : ulong starting_lamports_l; 42 : }; 43 : 44 : typedef struct fd_instr_info fd_instr_info_t; 45 : 46 : FD_PROTOTYPES_BEGIN 47 : 48 : static inline fd_instruction_account_t 49 : fd_instruction_account_init( ushort idx_in_txn, 50 : ushort idx_in_caller, 51 : ushort idx_in_callee, 52 : uchar is_writable, 53 5262 : uchar is_signer ) { 54 5262 : fd_instruction_account_t acc = { 55 5262 : .index_in_transaction = idx_in_txn, 56 5262 : .index_in_caller = idx_in_caller, 57 5262 : .index_in_callee = idx_in_callee, 58 5262 : .is_writable = is_writable, 59 5262 : .is_signer = is_signer, 60 5262 : }; 61 5262 : return acc; 62 5262 : } 63 : 64 : static inline void 65 : fd_instr_info_setup_instr_account( fd_instr_info_t * instr, 66 : uchar acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ], 67 : ushort idx_in_txn, 68 : ushort idx_in_caller, 69 : ushort idx_in_callee, 70 : uchar is_writable, 71 4968 : uchar is_signer ) { 72 4968 : if( FD_LIKELY( idx_in_txn!=USHORT_MAX ) ) { 73 4968 : instr->is_duplicate[ idx_in_callee ] = acc_idx_seen[ idx_in_txn ]; 74 : 75 4968 : if( FD_LIKELY( !acc_idx_seen[ idx_in_txn ] ) ) { 76 : /* This is the first time seeing this account */ 77 192 : acc_idx_seen[ idx_in_txn ] = 1; 78 192 : } 79 4968 : } 80 : 81 4968 : instr->accounts[ idx_in_callee ] = fd_instruction_account_init( idx_in_txn, 82 4968 : idx_in_caller, 83 4968 : idx_in_callee, 84 4968 : is_writable, 85 4968 : is_signer ); 86 4968 : } 87 : 88 : void 89 : fd_instr_info_init_from_txn_instr( fd_instr_info_t * instr, 90 : fd_bank_t * bank, 91 : fd_txn_in_t const * txn_in, 92 : fd_txn_out_t * txn_out, 93 : fd_txn_instr_t const * txn_instr ); 94 : 95 : /* https://github.com/anza-xyz/solana-sdk/blob/589e6237f203c2719c300dc044f4e00f48e66a8f/message/src/versions/v0/loaded.rs#L152-L157 */ 96 : FD_FN_PURE static inline int 97 : fd_instr_acc_is_writable_idx( fd_instr_info_t const * instr, 98 1065 : ushort idx ) { 99 1065 : if( FD_UNLIKELY( idx>=instr->acct_cnt ) ) { 100 0 : return 0; 101 0 : } 102 : 103 1065 : return !!(instr->accounts[idx].is_writable); 104 1065 : } 105 : 106 : /* fd_instr_acc_is_signer_idx returns: 107 : - 1 if account is signer 108 : - 0 (with *out_opt_err==0) if account is not signer 109 : If an error occurs during query, returns 0 and writes the 110 : error code to *out_opt_err. Possible values for out_opt_err: 111 : - FD_EXECUTOR_INSTR_ERR_MISSING_ACC occurs when the instr account 112 : index provided is invalid (out of bounds). 113 : - 0 if the query was successful. Check the return value to see 114 : if the account is a signer. 115 : 116 : https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L770-L779 */ 117 : static inline int 118 : fd_instr_acc_is_signer_idx( fd_instr_info_t const * instr, 119 : ushort idx, 120 582 : int * out_opt_err ) { 121 582 : if( FD_UNLIKELY( idx>=instr->acct_cnt ) ) { 122 0 : if( out_opt_err ) *out_opt_err = FD_EXECUTOR_INSTR_ERR_MISSING_ACC; 123 0 : return 0; 124 0 : } 125 : 126 582 : if( out_opt_err ) *out_opt_err = 0; 127 582 : return !!(instr->accounts[idx].is_signer); 128 582 : } 129 : 130 : /* fd_instr_info_sum_account_lamports calculates the sum of lamports 131 : account balances of all instruction accounts in the context, 132 : outputting the result in total_lamports_h and total_lamports_l. 133 : 134 : Returns FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW on arithmetic 135 : overflow, otherwise FD_EXECUTOR_INSTR_SUCCESS */ 136 : 137 : int 138 : fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr, 139 : fd_txn_out_t * txn_out, 140 : ulong * total_lamports_h, 141 : ulong * total_lamports_l ); 142 : 143 : FD_PROTOTYPES_END 144 : 145 : #endif /* HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h */