Line data Source code
1 : #include "fd_instr_info.h" 2 : 3 : #include "../fd_borrowed_account.h" 4 : #include "../../../util/bits/fd_uwide.h" 5 : 6 : void 7 : fd_convert_txn_instr_to_instr( fd_exec_txn_ctx_t * txn_ctx, 8 : fd_txn_instr_t const * txn_instr, 9 : fd_txn_account_t * accounts, 10 0 : fd_instr_info_t * instr ) { 11 : 12 0 : fd_txn_t const * txn_descriptor = txn_ctx->txn_descriptor; 13 0 : fd_rawtxn_b_t const * txn_raw = txn_ctx->_txn_raw; 14 0 : const fd_pubkey_t * account_keys = txn_ctx->account_keys; 15 : 16 0 : instr->program_id = txn_instr->program_id; 17 0 : instr->program_id_pubkey = account_keys[txn_instr->program_id]; 18 : 19 : /* See note in fd_instr_info.h. TLDR capping this value at 256 should have 20 : literally 0 effect on program execution, down to the error codes. This 21 : is purely for the sake of not increasing the overall memory footprint of the 22 : transaction context. If this change causes issues, we may need to increase 23 : the array sizes in the instr info. */ 24 0 : instr->acct_cnt = fd_ushort_min( txn_instr->acct_cnt, FD_INSTR_ACCT_MAX ); 25 0 : instr->data_sz = txn_instr->data_sz; 26 0 : instr->data = (uchar *)txn_raw->raw + txn_instr->data_off; 27 : 28 0 : uchar acc_idx_seen[256]; 29 0 : memset(acc_idx_seen, 0, 256); 30 0 : uchar * instr_acc_idxs = (uchar *)txn_raw->raw + txn_instr->acct_off; 31 0 : for( ulong i = 0; i < instr->acct_cnt; i++ ) { 32 0 : if( accounts != NULL ) { 33 0 : instr->accounts[i] = &accounts[instr_acc_idxs[i]]; 34 0 : } else { 35 0 : instr->accounts[i] = NULL; 36 0 : } 37 : 38 0 : uchar acc_idx = instr_acc_idxs[i]; 39 : 40 0 : instr->is_duplicate[i] = acc_idx_seen[acc_idx]; 41 0 : if( FD_LIKELY( !acc_idx_seen[acc_idx] ) ) { 42 : /* This is the first time seeing this account */ 43 0 : acc_idx_seen[acc_idx] = 1; 44 0 : } 45 : 46 0 : instr->acct_txn_idxs[i] = acc_idx; 47 0 : instr->acct_pubkeys[i] = account_keys[instr_acc_idxs[i]]; 48 0 : instr->acct_flags[i] = 0; 49 0 : if( fd_txn_account_is_writable_idx( txn_ctx, (int)instr_acc_idxs[i]) ) { 50 0 : instr->acct_flags[i] |= FD_INSTR_ACCT_FLAGS_IS_WRITABLE; 51 0 : } 52 0 : if( fd_txn_is_signer( txn_descriptor, instr_acc_idxs[i] ) ) { 53 0 : instr->acct_flags[i] |= FD_INSTR_ACCT_FLAGS_IS_SIGNER; 54 0 : } 55 0 : } 56 0 : } 57 : 58 : int 59 : fd_instr_any_signed( fd_instr_info_t const * info, 60 0 : fd_pubkey_t const * pubkey ) { 61 0 : int is_signer = 0; 62 0 : for( ulong j=0UL; j < info->acct_cnt; j++ ) 63 0 : is_signer |= 64 0 : ( ( !!fd_instr_acc_is_signer_idx( info, j ) ) & 65 0 : ( 0==memcmp( pubkey->key, info->acct_pubkeys[j].key, sizeof(fd_pubkey_t) ) ) ); 66 0 : return is_signer; 67 0 : } 68 : 69 : /* https://github.com/anza-xyz/agave/blob/9706a6464665f7ebd6ead47f0d12f853ccacbab9/sdk/src/transaction_context.rs#L40 */ 70 : int 71 : fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr, 72 : ulong * total_lamports_h, 73 0 : ulong * total_lamports_l ) { 74 0 : *total_lamports_h = 0UL; 75 0 : *total_lamports_l = 0UL; 76 0 : for( ulong i=0UL; i<instr->acct_cnt; ++i ) { 77 0 : if( instr->accounts[i] == NULL || 78 0 : instr->is_duplicate[i] || 79 0 : instr->accounts[i]->const_meta == NULL ) { 80 0 : continue; 81 0 : } 82 : 83 : /* Perform a checked add on a fd_uwide */ 84 0 : ulong tmp_total_lamports_h = 0UL; 85 0 : ulong tmp_total_lamports_l = 0UL; 86 : 87 0 : fd_uwide_inc( &tmp_total_lamports_h, &tmp_total_lamports_l, *total_lamports_h, *total_lamports_l, 88 0 : instr->accounts[i]->const_meta->info.lamports ); 89 : 90 0 : if( tmp_total_lamports_h < *total_lamports_h ) { 91 0 : return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW; 92 0 : } 93 : 94 0 : *total_lamports_h = tmp_total_lamports_h; 95 0 : *total_lamports_l = tmp_total_lamports_l; 96 0 : } 97 : 98 0 : return FD_EXECUTOR_INSTR_SUCCESS; 99 0 : }