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