Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_context_fd_exec_instr_ctx_h 2 : #define HEADER_fd_src_flamenco_runtime_context_fd_exec_instr_ctx_h 3 : 4 : #include "../info/fd_instr_info.h" 5 : #include "../fd_executor_err.h" 6 : #include "../sysvar/fd_sysvar_cache.h" 7 : 8 : /* Avoid circular include dependency with forward declaration */ 9 : struct fd_borrowed_account; 10 : typedef struct fd_borrowed_account fd_borrowed_account_t; 11 : 12 : /* fd_exec_instr_ctx_t is the context needed to execute a single 13 : instruction (program invocation). */ 14 : 15 : struct fd_exec_instr_ctx { 16 : fd_instr_info_t const * instr; /* The instruction info for this instruction */ 17 : fd_exec_txn_ctx_t * txn_ctx; /* The transaction context for this instruction */ 18 : fd_sysvar_cache_t const * sysvar_cache; 19 : 20 : /* Most instructions log the base58 program id multiple times, so it's 21 : convenient to compute it once and reuse it. */ 22 : char program_id_base58[ FD_BASE58_ENCODED_32_SZ ]; 23 : }; 24 : 25 : #define FD_EXEC_INSTR_CTX_ALIGN (alignof(fd_exec_instr_ctx_t)) 26 : #define FD_EXEC_INSTR_CTX_FOOTPRINT (sizeof (fd_exec_instr_ctx_t)) 27 : 28 : /* Be careful when using this macro. There may be places where the error 29 : will need to be handled differently. */ 30 0 : #define FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, idx, acc ) do { \ 31 0 : int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, idx, acc ); \ 32 0 : if( FD_UNLIKELY( err ) ) return err; \ 33 0 : } while (0) 34 : 35 : FD_PROTOTYPES_BEGIN 36 : 37 : /* Operators */ 38 : 39 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::check_number_of_instruction_accounts 40 : 41 : Assert that enough accounts were supplied to this instruction. Returns 42 : FD_EXECUTOR_INSTR_SUCCESS if the number of accounts is as expected and 43 : FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS otherwise. 44 : 45 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L490 */ 46 : 47 : static inline int 48 : fd_exec_instr_ctx_check_num_insn_accounts( fd_exec_instr_ctx_t const * ctx, 49 0 : uint expected_accounts ) { 50 : 51 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt<expected_accounts ) ) { 52 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS; 53 0 : } 54 0 : return FD_EXECUTOR_INSTR_SUCCESS; 55 0 : } 56 : 57 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::find_index_of_instruction_account. 58 : 59 : Returns the index of the instruction account given the account pubkey 60 : or -1 if the account is not found. 61 : 62 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L524-L538 */ 63 : 64 : int 65 : fd_exec_instr_ctx_find_idx_of_instr_account( fd_exec_instr_ctx_t const * ctx, 66 : fd_pubkey_t const * pubkey ); 67 : 68 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_index_of_instruction_account_in_transaction 69 : 70 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L552 */ 71 : 72 : static inline int 73 : fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( fd_exec_instr_ctx_t const * ctx, 74 : ushort idx_in_instr, 75 0 : ushort * idx_in_txn ) { 76 0 : if( FD_UNLIKELY( idx_in_instr==USHORT_MAX ) ) { 77 0 : *idx_in_txn = USHORT_MAX; 78 0 : return FD_EXECUTOR_INSTR_SUCCESS; 79 0 : } 80 : 81 : /* Return a NotEnoughAccountKeys error if the idx is out of bounds. 82 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L559 */ 83 0 : if( FD_UNLIKELY( idx_in_instr>=ctx->instr->acct_cnt ) ) { 84 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS; 85 0 : } 86 : 87 0 : *idx_in_txn = ctx->instr->accounts[ idx_in_instr ].index_in_transaction; 88 0 : return FD_EXECUTOR_INSTR_SUCCESS; 89 0 : } 90 : 91 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_number_of_program_accounts. 92 : 93 : Strictly returns 1, as we only support one program account per instruction. 94 : 95 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L480-L482 */ 96 : 97 : static inline ushort 98 0 : fd_exec_instr_ctx_get_number_of_program_accounts( fd_exec_instr_ctx_t const * ctx ) { 99 0 : (void) ctx; 100 0 : return 1U; 101 0 : } 102 : 103 : /* A helper function to get the pubkey of an account using its instruction context index */ 104 : int 105 : fd_exec_instr_ctx_get_key_of_account_at_index( fd_exec_instr_ctx_t const * ctx, 106 : ushort idx_in_instr, 107 : fd_pubkey_t const * * key ); 108 : 109 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_last_program_key. 110 : 111 : There can only be one program per instruction, so this function simply retrieves 112 : that program's pubkey, despite the name implying multiple programs per instruction. 113 : The function exists to match semantics with Agave. 114 : 115 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L582 */ 116 : 117 : int 118 : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx, 119 : fd_pubkey_t const * * key ); 120 : 121 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::try_borrow_account. 122 : 123 : Borrows an account from the instruction context with a given account index. 124 : 125 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L594 */ 126 : 127 : int 128 : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx, 129 : ushort idx, 130 : fd_borrowed_account_t * account ); 131 : 132 : /* A wrapper around fd_exec_instr_ctx_try_borrow_account that accepts an account pubkey. 133 : 134 : Borrows an account from the instruction context with a given pubkey. */ 135 : 136 : int 137 : fd_exec_instr_ctx_try_borrow_instr_account_with_key( fd_exec_instr_ctx_t const * ctx, 138 : fd_pubkey_t const * pubkey, 139 : fd_borrowed_account_t * account ); 140 : 141 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::try_borrow_last_program_account 142 : 143 : Borrows the instruction's program account. Since there is only one program account per 144 : instruction, this function simply borrows the instruction's only program account, despite the name. 145 : 146 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L616 */ 147 : 148 : int 149 : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx, 150 : fd_borrowed_account_t * account ); 151 : 152 : /* Mirrors Agave function solana_sdk::transaction_context::InstructionContext::get_signers 153 : 154 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L684 */ 155 : 156 : int 157 : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx, 158 : fd_pubkey_t const * signers[ static FD_TXN_SIG_MAX ] ); 159 : 160 : /* fd_exec_instr_ctx_any_signed matches 161 : solana_system_program::system_processor::Address::is_signer 162 : 163 : Scans instruction accounts for matching signer. 164 : 165 : Returns 1 if *any* instruction account with the given pubkey is a 166 : signer and 0 otherwise. Note that the same account/pubkey can be 167 : specified as multiple different instruction accounts that might not 168 : all have the signer bit. 169 : 170 : https://github.com/anza-xyz/agave/blob/v2.1.14/programs/system/src/system_processor.rs#L35-L41 */ 171 : 172 : FD_FN_PURE int 173 : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx, 174 : fd_pubkey_t const * pubkey ); 175 : 176 : /* Although fd_signers_contains does not take an instruction context, 177 : it is included here for relevance to signer helper functions 178 : 179 : Loop conditions could be optimized to allow for unroll/vectorize */ 180 : 181 : static inline int 182 : fd_signers_contains( fd_pubkey_t const * signers[ static FD_TXN_SIG_MAX ], 183 0 : fd_pubkey_t const * pubkey ) { 184 0 : for( ulong i=0; i<FD_TXN_SIG_MAX && signers[i]; i++ ) 185 0 : if( 0==memcmp( signers[i], pubkey, sizeof( fd_pubkey_t ) ) ) return 1; 186 0 : return 0; 187 0 : } 188 : 189 : FD_PROTOTYPES_END 190 : 191 : #endif /* HEADER_fd_src_flamenco_runtime_context_fd_exec_instr_ctx_h */