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