Line data Source code
1 : #include "fd_exec_instr_ctx.h"
2 : #include "../fd_borrowed_account.h"
3 :
4 : void *
5 7665 : fd_exec_instr_ctx_new( void * mem ) {
6 7665 : if( FD_UNLIKELY( !mem ) ) {
7 0 : FD_LOG_WARNING(( "NULL mem" ));
8 0 : return NULL;
9 0 : }
10 :
11 7665 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_INSTR_CTX_ALIGN ) ) ) {
12 0 : FD_LOG_WARNING(( "misaligned mem" ));
13 0 : return NULL;
14 0 : }
15 :
16 7665 : fd_memset(mem, 0, FD_EXEC_INSTR_CTX_FOOTPRINT);
17 :
18 7665 : fd_exec_instr_ctx_t * self = (fd_exec_instr_ctx_t *) mem;
19 :
20 7665 : FD_COMPILER_MFENCE();
21 7665 : self->magic = FD_EXEC_INSTR_CTX_MAGIC;
22 7665 : FD_COMPILER_MFENCE();
23 :
24 7665 : return mem;
25 7665 : }
26 :
27 : fd_exec_instr_ctx_t *
28 7665 : fd_exec_instr_ctx_join( void * mem ) {
29 7665 : if( FD_UNLIKELY( !mem ) ) {
30 0 : FD_LOG_WARNING(( "NULL block" ));
31 0 : return NULL;
32 0 : }
33 :
34 7665 : fd_exec_instr_ctx_t * ctx = (fd_exec_instr_ctx_t *) mem;
35 :
36 7665 : if( FD_UNLIKELY( ctx->magic!=FD_EXEC_INSTR_CTX_MAGIC ) ) {
37 0 : FD_LOG_WARNING(( "bad magic" ));
38 0 : return NULL;
39 0 : }
40 :
41 7665 : return ctx;
42 7665 : }
43 :
44 : void *
45 7665 : fd_exec_instr_ctx_leave( fd_exec_instr_ctx_t * ctx) {
46 7665 : if( FD_UNLIKELY( !ctx ) ) {
47 0 : FD_LOG_WARNING(( "NULL block" ));
48 0 : return NULL;
49 0 : }
50 :
51 7665 : if( FD_UNLIKELY( ctx->magic!=FD_EXEC_INSTR_CTX_MAGIC ) ) {
52 0 : FD_LOG_WARNING(( "bad magic" ));
53 0 : return NULL;
54 0 : }
55 :
56 7665 : return (void *) ctx;
57 7665 : }
58 :
59 : void *
60 7665 : fd_exec_instr_ctx_delete( void * mem ) {
61 7665 : if( FD_UNLIKELY( !mem ) ) {
62 0 : FD_LOG_WARNING(( "NULL mem" ));
63 0 : return NULL;
64 0 : }
65 :
66 7665 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_INSTR_CTX_ALIGN) ) ) {
67 0 : FD_LOG_WARNING(( "misaligned mem" ));
68 0 : return NULL;
69 0 : }
70 :
71 7665 : fd_exec_instr_ctx_t * hdr = (fd_exec_instr_ctx_t *)mem;
72 7665 : if( FD_UNLIKELY( hdr->magic!=FD_EXEC_INSTR_CTX_MAGIC ) ) {
73 0 : FD_LOG_WARNING(( "bad magic" ));
74 0 : return NULL;
75 0 : }
76 :
77 7665 : FD_COMPILER_MFENCE();
78 7665 : FD_VOLATILE( hdr->magic ) = 0UL;
79 7665 : FD_COMPILER_MFENCE();
80 :
81 7665 : return mem;
82 7665 : }
83 :
84 : int
85 : fd_exec_instr_ctx_find_idx_of_instr_account( fd_exec_instr_ctx_t const * ctx,
86 0 : fd_pubkey_t const * pubkey ) {
87 0 : for( int i=0; i<ctx->instr->acct_cnt; i++ ) {
88 0 : ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
89 0 : if( memcmp( pubkey->uc, ctx->txn_ctx->account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
90 0 : return i;
91 0 : }
92 0 : }
93 0 : return -1;
94 0 : }
95 :
96 : int
97 : fd_exec_instr_ctx_get_key_of_account_at_index( fd_exec_instr_ctx_t const * ctx,
98 : ushort idx_in_instr,
99 0 : fd_pubkey_t const * * key ) {
100 0 : ushort idx_in_txn;
101 0 : int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
102 0 : idx_in_instr,
103 0 : &idx_in_txn );
104 0 : if( FD_UNLIKELY( err ) ) {
105 0 : return err;
106 0 : }
107 :
108 0 : return fd_exec_txn_ctx_get_key_of_account_at_index( ctx->txn_ctx,
109 0 : idx_in_txn,
110 0 : key );
111 0 : }
112 :
113 : int
114 : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx,
115 0 : fd_pubkey_t const * * key ) {
116 0 : return fd_exec_txn_ctx_get_key_of_account_at_index( ctx->txn_ctx,
117 0 : ctx->instr->program_id,
118 0 : key );
119 0 : }
120 :
121 : int
122 : fd_exec_instr_ctx_try_borrow_account( fd_exec_instr_ctx_t const * ctx,
123 : ushort idx_in_instr,
124 : ushort idx_in_txn,
125 0 : fd_borrowed_account_t * account ) {
126 : /* Get the account from the transaction context using idx_in_txn.
127 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L600-L602 */
128 0 : fd_txn_account_t * txn_account = NULL;
129 0 : int err = fd_exec_txn_ctx_get_account_at_index( ctx->txn_ctx,
130 0 : idx_in_txn,
131 0 : &txn_account,
132 0 : NULL );
133 0 : if( FD_UNLIKELY( err ) ) {
134 : /* Return a MissingAccount error if the account is not found.
135 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L603 */
136 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
137 0 : }
138 :
139 : /* Return an AccountBorrowFailed error if the write is not acquirable.
140 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L605 */
141 0 : int borrow_res = txn_account->vt->try_borrow_mut( txn_account );
142 0 : if( FD_UNLIKELY( !borrow_res ) ) {
143 0 : return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
144 0 : }
145 :
146 : /* Create a BorrowedAccount upon success.
147 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L606 */
148 0 : fd_borrowed_account_init( account,
149 0 : txn_account,
150 0 : ctx,
151 0 : idx_in_instr );
152 0 : return FD_EXECUTOR_INSTR_SUCCESS;
153 0 : }
154 :
155 : int
156 : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx,
157 : ushort idx,
158 0 : fd_borrowed_account_t * account ) {
159 : /* Find the index of the account in the transaction context.
160 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L649-L650 */
161 0 : ushort idx_in_txn;
162 0 : int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
163 0 : idx,
164 0 : &idx_in_txn );
165 0 : if( FD_UNLIKELY( err ) ) {
166 0 : return err;
167 0 : }
168 :
169 0 : return fd_exec_instr_ctx_try_borrow_account( ctx,
170 0 : idx,
171 0 : idx_in_txn,
172 0 : account );
173 0 : }
174 :
175 : int
176 : fd_exec_instr_ctx_try_borrow_instr_account_with_key( fd_exec_instr_ctx_t const * ctx,
177 : fd_pubkey_t const * pubkey,
178 0 : fd_borrowed_account_t * account ) {
179 0 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
180 0 : ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
181 0 : if( memcmp( pubkey->uc, ctx->txn_ctx->account_keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
182 0 : return fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, account );
183 0 : }
184 0 : }
185 :
186 : /* Return a NotEnoughAccountKeys error if the account is not found
187 : in the instruction context to match the error code returned by
188 : fd_exec_instr_ctx_try_borrow_instr_account. */
189 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
190 0 : }
191 :
192 : int
193 : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx,
194 0 : fd_borrowed_account_t * account ) {
195 : /* The index_in_instruction for a borrowed program account is invalid,
196 : so it is set to a sentinel value of USHORT_MAX. */
197 0 : return fd_exec_instr_ctx_try_borrow_account( ctx,
198 0 : USHORT_MAX,
199 0 : ctx->instr->program_id,
200 0 : account );
201 0 : }
202 :
203 : int
204 : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx,
205 0 : fd_pubkey_t const * signers[static FD_TXN_SIG_MAX] ) {
206 0 : ulong j = 0UL;
207 0 : for( ushort i=0; i<ctx->instr->acct_cnt && j<FD_TXN_SIG_MAX; i++ )
208 0 : if( fd_instr_acc_is_signer_idx( ctx->instr, i ) ) {
209 0 : ushort idx_in_txn = ctx->instr->accounts[i].index_in_transaction;
210 0 : int err = fd_exec_txn_ctx_get_key_of_account_at_index( ctx->txn_ctx,
211 0 : idx_in_txn,
212 0 : &signers[j++] );
213 0 : if( FD_UNLIKELY( err ) ) {
214 0 : return err;
215 0 : }
216 0 : }
217 0 : return FD_EXECUTOR_INSTR_SUCCESS;
218 0 : }
219 :
220 : int
221 : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx,
222 0 : fd_pubkey_t const * pubkey ) {
223 0 : int is_signer = 0;
224 0 : for( ushort j=0; j<ctx->instr->acct_cnt; j++ ) {
225 0 : ushort idx_in_txn = ctx->instr->accounts[ j ].index_in_transaction;
226 0 : is_signer |=
227 0 : ( ( !!fd_instr_acc_is_signer_idx( ctx->instr, j ) ) &
228 0 : ( 0==memcmp( pubkey->key, ctx->txn_ctx->account_keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) );
229 0 : }
230 0 : return is_signer;
231 0 : }
|