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