Line data Source code
1 : #include "fd_exec_instr_ctx.h"
2 : #include "../fd_runtime.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 4233 : fd_pubkey_t const * pubkey ) {
8 12365 : for( int i=0; i<ctx->instr->acct_cnt; i++ ) {
9 12324 : ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
10 12324 : if( memcmp( pubkey->uc, ctx->txn_out->accounts.keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
11 4192 : return i;
12 4192 : }
13 12324 : }
14 41 : return -1;
15 4233 : }
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 4664 : fd_pubkey_t const * * key ) {
21 4664 : ushort idx_in_txn;
22 4664 : int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
23 4664 : idx_in_instr,
24 4664 : &idx_in_txn );
25 4664 : if( FD_UNLIKELY( err ) ) {
26 23 : return err;
27 23 : }
28 :
29 4641 : return fd_runtime_get_key_of_account_at_index( ctx->txn_out,
30 4641 : idx_in_txn,
31 4641 : key );
32 4664 : }
33 :
34 : int
35 : fd_exec_instr_ctx_get_last_program_key( fd_exec_instr_ctx_t const * ctx,
36 19910 : fd_pubkey_t const * * key ) {
37 19910 : return fd_runtime_get_key_of_account_at_index( ctx->txn_out,
38 19910 : ctx->instr->program_id,
39 19910 : key );
40 19910 : }
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 83061 : 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 83061 : int err = fd_runtime_get_account_at_index( ctx->txn_in,
50 83061 : ctx->txn_out,
51 83061 : idx_in_txn,
52 83061 : NULL );
53 83061 : if( FD_UNLIKELY( err ) ) {
54 : /* Return a MissingAccount error if the account is not found.
55 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L603 */
56 1 : FD_TXN_ERR_FOR_LOG_INSTR( ctx->txn_out, FD_EXECUTOR_INSTR_ERR_MISSING_ACC, ctx->txn_out->err.exec_err_idx );
57 1 : return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
58 1 : }
59 :
60 83060 : fd_account_meta_t * meta = ctx->txn_out->accounts.account[idx_in_txn].meta;
61 :
62 : /* Return an AccountBorrowFailed error if the write is not acquirable.
63 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L605 */
64 83060 : if( FD_UNLIKELY( ctx->runtime->accounts.refcnt[idx_in_txn]!=0UL ) ) {
65 2 : return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
66 2 : }
67 83058 : ctx->runtime->accounts.refcnt[idx_in_txn]++;
68 :
69 : /* Create a BorrowedAccount upon success.
70 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L606 */
71 83058 : fd_borrowed_account_init( account,
72 83058 : &ctx->txn_out->accounts.keys[idx_in_txn],
73 83058 : meta,
74 83058 : ctx,
75 83058 : idx_in_instr,
76 83058 : &ctx->runtime->accounts.refcnt[idx_in_txn] );
77 83058 : return FD_EXECUTOR_INSTR_SUCCESS;
78 83060 : }
79 :
80 : int
81 : fd_exec_instr_ctx_try_borrow_instr_account( fd_exec_instr_ctx_t const * ctx,
82 : ushort idx,
83 72316 : fd_borrowed_account_t * account ) {
84 : /* Find the index of the account in the transaction context.
85 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L649-L650 */
86 72316 : ushort idx_in_txn;
87 72316 : int err = fd_exec_instr_ctx_get_index_of_instr_account_in_transaction( ctx,
88 72316 : idx,
89 72316 : &idx_in_txn );
90 72316 : if( FD_UNLIKELY( err ) ) {
91 124 : return err;
92 124 : }
93 :
94 72192 : return fd_exec_instr_ctx_try_borrow_account( ctx,
95 72192 : idx,
96 72192 : idx_in_txn,
97 72192 : account );
98 72316 : }
99 :
100 : int
101 : fd_exec_instr_ctx_try_borrow_instr_account_with_key( fd_exec_instr_ctx_t const * ctx,
102 : fd_pubkey_t const * pubkey,
103 0 : fd_borrowed_account_t * account ) {
104 0 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
105 0 : ushort idx_in_txn = ctx->instr->accounts[ i ].index_in_transaction;
106 0 : if( memcmp( pubkey->uc, ctx->txn_out->accounts.keys[ idx_in_txn ].uc, sizeof(fd_pubkey_t) )==0 ) {
107 0 : return fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, account );
108 0 : }
109 0 : }
110 :
111 : /* Return a NotEnoughAccountKeys error if the account is not found
112 : in the instruction context to match the error code returned by
113 : fd_exec_instr_ctx_try_borrow_instr_account. */
114 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
115 0 : }
116 :
117 : int
118 : fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * ctx,
119 10908 : fd_borrowed_account_t * account ) {
120 : /* The index_in_instruction for a borrowed program account is invalid,
121 : so it is set to a sentinel value of USHORT_MAX. */
122 10908 : return fd_exec_instr_ctx_try_borrow_account( ctx,
123 10908 : USHORT_MAX,
124 10908 : ctx->instr->program_id,
125 10908 : account );
126 10908 : }
127 :
128 : int
129 : fd_exec_instr_ctx_get_signers( fd_exec_instr_ctx_t const * ctx,
130 : fd_pubkey_t const * signers[static FD_TXN_SIG_MAX],
131 2505 : ulong * signers_cnt ) {
132 2505 : ulong j = 0UL;
133 14127 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
134 11622 : if( fd_instr_acc_is_signer_idx( ctx->instr, i, NULL ) ) {
135 6264 : ushort idx_in_txn = ctx->instr->accounts[i].index_in_transaction;
136 6264 : fd_pubkey_t const * pubkey = NULL;
137 6264 : int err = fd_runtime_get_key_of_account_at_index( ctx->txn_out,
138 6264 : idx_in_txn,
139 6264 : &pubkey );
140 6264 : if( FD_UNLIKELY( err ) ) {
141 0 : return err;
142 0 : }
143 :
144 : /* Skip if duplicate signer */
145 6264 : if( FD_UNLIKELY( fd_signers_contains( signers, j, pubkey ) ) ) {
146 754 : continue;
147 754 : }
148 :
149 : /* This should never be possible */
150 5510 : if( FD_UNLIKELY( j>=FD_TXN_SIG_MAX ) ) {
151 0 : FD_LOG_CRIT(( "invariant violation: too many signers (cnt=%lu, FD_TXN_SIG_MAX=%lu)", j, (ulong)FD_TXN_SIG_MAX ));
152 0 : }
153 :
154 5510 : signers[j++] = pubkey;
155 5510 : }
156 11622 : }
157 :
158 2505 : *signers_cnt = j;
159 2505 : return FD_EXECUTOR_INSTR_SUCCESS;
160 2505 : }
161 :
162 : int
163 : fd_exec_instr_ctx_any_signed( fd_exec_instr_ctx_t const * ctx,
164 2031 : fd_pubkey_t const * pubkey ) {
165 2031 : int is_signer = 0;
166 9122 : for( ushort j=0; j<ctx->instr->acct_cnt; j++ ) {
167 7091 : ushort idx_in_txn = ctx->instr->accounts[ j ].index_in_transaction;
168 7091 : is_signer |=
169 7091 : ( ( !!fd_instr_acc_is_signer_idx( ctx->instr, j, NULL ) ) &
170 7091 : ( 0==memcmp( pubkey->key, ctx->txn_out->accounts.keys[ idx_in_txn ].key, sizeof(fd_pubkey_t) ) ) );
171 7091 : }
172 2031 : return is_signer;
173 2031 : }
|