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 6084 : uchar is_signer ) { 54 6084 : fd_instruction_account_t acc = { 55 6084 : .index_in_transaction = idx_in_txn, 56 6084 : .index_in_caller = idx_in_caller, 57 6084 : .index_in_callee = idx_in_callee, 58 6084 : .is_writable = is_writable, 59 6084 : .is_signer = is_signer, 60 6084 : }; 61 6084 : return acc; 62 6084 : } 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 5790 : uchar is_signer ) { 72 5790 : if( FD_LIKELY( idx_in_txn!=USHORT_MAX ) ) { 73 5790 : instr->is_duplicate[ idx_in_callee ] = acc_idx_seen[ idx_in_txn ]; 74 : 75 5790 : if( FD_LIKELY( !acc_idx_seen[ idx_in_txn ] ) ) { 76 : /* This is the first time seeing this account */ 77 252 : acc_idx_seen[ idx_in_txn ] = 1; 78 252 : } 79 5790 : } 80 : 81 5790 : instr->accounts[ idx_in_callee ] = fd_instruction_account_init( idx_in_txn, 82 5790 : idx_in_caller, 83 5790 : idx_in_callee, 84 5790 : is_writable, 85 5790 : is_signer ); 86 5790 : } 87 : 88 : void 89 : fd_instr_info_init_from_txn_instr( fd_instr_info_t * instr, 90 : fd_txn_in_t const * txn_in, 91 : fd_txn_out_t * txn_out, 92 : fd_txn_instr_t const * txn_instr ); 93 : 94 : /* https://github.com/anza-xyz/solana-sdk/blob/589e6237f203c2719c300dc044f4e00f48e66a8f/message/src/versions/v0/loaded.rs#L152-L157 */ 95 : FD_FN_PURE static inline int 96 : fd_instr_acc_is_writable_idx( fd_instr_info_t const * instr, 97 1140 : ushort idx ) { 98 1140 : if( FD_UNLIKELY( idx>=instr->acct_cnt ) ) { 99 0 : return 0; 100 0 : } 101 : 102 1140 : return !!(instr->accounts[idx].is_writable); 103 1140 : } 104 : 105 : /* fd_instr_acc_is_signer_idx returns: 106 : - 1 if account is signer 107 : - 0 (with *out_opt_err==0) if account is not signer 108 : If an error occurs during query, returns 0 and writes the 109 : error code to *out_opt_err. Possible values for out_opt_err: 110 : - FD_EXECUTOR_INSTR_ERR_MISSING_ACC occurs when the instr account 111 : index provided is invalid (out of bounds). 112 : - 0 if the query was successful. Check the return value to see 113 : if the account is a signer. 114 : 115 : https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L770-L779 */ 116 : static inline int 117 : fd_instr_acc_is_signer_idx( fd_instr_info_t const * instr, 118 : ushort idx, 119 693 : int * out_opt_err ) { 120 693 : if( FD_UNLIKELY( idx>=instr->acct_cnt ) ) { 121 0 : if( out_opt_err ) *out_opt_err = FD_EXECUTOR_INSTR_ERR_MISSING_ACC; 122 0 : return 0; 123 0 : } 124 : 125 693 : if( out_opt_err ) *out_opt_err = 0; 126 693 : return !!(instr->accounts[idx].is_signer); 127 693 : } 128 : 129 : /* fd_instr_info_sum_account_lamports calculates the sum of lamports 130 : account balances of all instruction accounts in the context, 131 : outputting the result in total_lamports_h and total_lamports_l. 132 : 133 : Returns FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW on arithmetic 134 : overflow, otherwise FD_EXECUTOR_INSTR_SUCCESS */ 135 : 136 : int 137 : fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr, 138 : fd_txn_out_t * txn_out, 139 : ulong * total_lamports_h, 140 : ulong * total_lamports_l ); 141 : 142 : FD_PROTOTYPES_END 143 : 144 : #endif /* HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h */