Line data Source code
1 : #include "fd_exec_instr_ctx.h"
2 : #include "fd_exec_txn_ctx.h"
3 : #include "../fd_borrowed_account.h"
4 :
5 : int
6 : fd_exec_instr_ctx_find_idx_of_instr_account( fd_exec_instr_ctx_t const * ctx,
7 0 : fd_pubkey_t const * pubkey ) {
8 0 : for( int i=0; i<ctx->instr->acct_cnt; i++ ) {
9 0 : ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
10 0 : if( memcmp( pubkey->uc, ctx->txn_ctx->account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
11 0 : return i;
12 0 : }
13 0 : }
14 0 : return -1;
15 0 : }
16 :
17 : int
18 : fd_exec_instr_ctx_get_key_of_account_at_index( fd_exec_instr_ctx_t const * ctx,
19 : ushort idx_in_instr,
20 0 : fd_pubkey_t const * * key ) {
21 0 : ushort idx_in_txn;
22 0 : int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
23 0 : idx_in_instr,
24 0 : &idx_in_txn );
25 0 : if( FD_UNLIKELY( err ) ) {
26 0 : return err;
27 0 : }
28 :
29 0 : return fd_exec_txn_ctx_get_key_of_account_at_index( ctx->txn_ctx,
30 0 : idx_in_txn,
31 0 : key );
32 0 : }
33 :
34 : int
35 : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx,
36 0 : fd_pubkey_t const * * key ) {
37 0 : return fd_exec_txn_ctx_get_key_of_account_at_index( ctx->txn_ctx,
38 0 : ctx->instr->program_id,
39 0 : key );
40 0 : }
41 :
42 : int
43 : fd_exec_instr_ctx_try_borrow_account( fd_exec_instr_ctx_t const * ctx,
44 : ushort idx_in_instr,
45 : ushort idx_in_txn,
46 0 : fd_borrowed_account_t * account ) {
47 : /* Get the account from the transaction context using idx_in_txn.
48 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L600-L602 */
49 0 : fd_txn_account_t * txn_account = NULL;
50 0 : int err = fd_exec_txn_ctx_get_account_at_index( ctx->txn_ctx,
51 0 : idx_in_txn,
52 0 : &txn_account,
53 0 : NULL );
54 0 : if( FD_UNLIKELY( err ) ) {
55 : /* Return a MissingAccount error if the account is not found.
56 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L603 */
57 0 : FD_TXN_ERR_FOR_LOG_INSTR( ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, ctx->txn_ctx->instr_err_idx );
58 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
59 0 : }
60 :
61 : /* Return an AccountBorrowFailed error if the write is not acquirable.
62 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L605 */
63 0 : int borrow_res = fd_txn_account_try_borrow_mut( txn_account );
64 0 : if( FD_UNLIKELY( !borrow_res ) ) {
65 0 : return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
66 0 : }
67 :
68 : /* Create a BorrowedAccount upon success.
69 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L606 */
70 0 : fd_borrowed_account_init( account,
71 0 : txn_account,
72 0 : ctx,
73 0 : idx_in_instr );
74 0 : return FD_EXECUTOR_INSTR_SUCCESS;
75 0 : }
76 :
77 : int
78 : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx,
79 : ushort idx,
80 0 : fd_borrowed_account_t * account ) {
81 : /* Find the index of the account in the transaction context.
82 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L649-L650 */
83 0 : ushort idx_in_txn;
84 0 : int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
85 0 : idx,
86 0 : &idx_in_txn );
87 0 : if( FD_UNLIKELY( err ) ) {
88 0 : return err;
89 0 : }
90 :
91 0 : return fd_exec_instr_ctx_try_borrow_account( ctx,
92 0 : idx,
93 0 : idx_in_txn,
94 0 : account );
95 0 : }
96 :
97 : int
98 : fd_exec_instr_ctx_try_borrow_instr_account_with_key( fd_exec_instr_ctx_t const * ctx,
99 : fd_pubkey_t const * pubkey,
100 0 : fd_borrowed_account_t * account ) {
101 0 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
102 0 : ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
103 0 : if( memcmp( pubkey->uc, ctx->txn_ctx->account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
104 0 : return fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, account );
105 0 : }
106 0 : }
107 :
108 : /* Return a NotEnoughAccountKeys error if the account is not found
109 : in the instruction context to match the error code returned by
110 : fd_exec_instr_ctx_try_borrow_instr_account. */
111 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
112 0 : }
113 :
114 : int
115 : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx,
116 0 : fd_borrowed_account_t * account ) {
117 : /* The index_in_instruction for a borrowed program account is invalid,
118 : so it is set to a sentinel value of USHORT_MAX. */
119 0 : return fd_exec_instr_ctx_try_borrow_account( ctx,
120 0 : USHORT_MAX,
121 0 : ctx->instr->program_id,
122 0 : account );
123 0 : }
124 :
125 : int
126 : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx,
127 0 : fd_pubkey_t const * signers[static FD_TXN_SIG_MAX] ) {
128 0 : ulong j = 0UL;
129 0 : for( ushort i=0; i<ctx->instr->acct_cnt && j<FD_TXN_SIG_MAX; i++ )
130 0 : if( fd_instr_acc_is_signer_idx( ctx->instr, i ) ) {
131 0 : ushort idx_in_txn = ctx->instr->accounts[i].index_in_transaction;
132 0 : int err = fd_exec_txn_ctx_get_key_of_account_at_index( ctx->txn_ctx,
133 0 : idx_in_txn,
134 0 : &signers[j++] );
135 0 : if( FD_UNLIKELY( err ) ) {
136 0 : return err;
137 0 : }
138 0 : }
139 0 : return FD_EXECUTOR_INSTR_SUCCESS;
140 0 : }
141 :
142 : int
143 : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx,
144 0 : fd_pubkey_t const * pubkey ) {
145 0 : int is_signer = 0;
146 0 : for( ushort j=0; j<ctx->instr->acct_cnt; j++ ) {
147 0 : ushort idx_in_txn = ctx->instr->accounts[ j ].index_in_transaction;
148 0 : is_signer |=
149 0 : ( ( !!fd_instr_acc_is_signer_idx( ctx->instr, j ) ) &
150 0 : ( 0==memcmp( pubkey->key, ctx->txn_ctx->account_keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) );
151 0 : }
152 0 : return is_signer;
153 0 : }
|