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