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