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