LCOV - code coverage report
Current view: top level - flamenco/runtime/info - fd_instr_info.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 39 0.0 %
Date: 2025-12-06 04:45:29 Functions: 0 420 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h
       2             : #define HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h
       3             : 
       4             : #include "../fd_txn_account.h"
       5             : #include "../fd_executor_err.h"
       6             : #include "../fd_runtime_const.h"
       7             : #include "../../../ballet/txn/fd_txn.h"
       8             : 
       9             : /* While the maximum number of instruction accounts allowed for instruction
      10             :    execution is 256, it is entirely possible to have a transaction with more
      11             :    than 256 instruction accounts that passes transaction loading checks and enters
      12             :    `fd_execute_instr` (See mainnet transaction
      13             :    3eDdfZE6HswPxFKrtnQPsEmTkyL1iP57gRPEXwaqNGAqF1paGXCYYMwh7z4uQDUMgFor742sikVSQZW1gFRDhPNh
      14             :    for an example). An instruction that goes into the VM with more than 256 instruction accounts
      15             :    will fail, but you could also theoretically invoke a native program with over 256 random
      16             :    unreferenced instruction accounts that will execute successfully. The true bound for the
      17             :    maximum number of instruction accounts you can pass in is slighly lower than the maximum
      18             :    possible size for a serialized transaction (1232).
      19             : 
      20             :    HOWEVER... to keep our memory footprint low, we cap the `acct_cnt` at 256 during setup since
      21             :    any extra accounts should (ideally) have literally 0 impact on program execution, whether
      22             :    or not they are present in the instr info. This keeps the transaction context size from
      23             :    blowing up to around 3MB in size. */
      24           0 : #define FD_INSTR_ACCT_FLAGS_IS_SIGNER   (0x01U)
      25           0 : #define FD_INSTR_ACCT_FLAGS_IS_WRITABLE (0x02U)
      26             : 
      27             : /* The maximum possible size for the instruction data for any
      28             :    instruction, which is bounded by FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN
      29             :    (which is 10KB). */
      30             : #define FD_INSTR_DATA_MAX FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN
      31             : 
      32             : struct fd_instruction_account {
      33             :   ushort index_in_transaction;
      34             :   ushort index_in_caller;
      35             :   ushort index_in_callee;
      36             :   uchar is_writable;
      37             :   uchar is_signer;
      38             : };
      39             : 
      40             : typedef struct fd_instruction_account fd_instruction_account_t;
      41             : 
      42             : struct fd_instr_info {
      43             :   uchar                    program_id;
      44             :   ushort                   acct_cnt;
      45             : 
      46             :   uchar                    data[ FD_INSTR_DATA_MAX ];
      47             :   ushort                   data_sz;
      48             : 
      49             :   fd_instruction_account_t accounts[ FD_INSTR_ACCT_MAX ];
      50             :   uchar                    is_duplicate[ FD_INSTR_ACCT_MAX ];
      51             : 
      52             :   /* Stack height when this instruction was pushed onto the stack (including itself) */
      53             :   uchar stack_height;
      54             : 
      55             :   /* TODO: convert to fd_uwide_t representation of uint_128 */
      56             :   ulong                    starting_lamports_h;
      57             :   ulong                    starting_lamports_l;
      58             : };
      59             : 
      60             : typedef struct fd_instr_info fd_instr_info_t;
      61             : 
      62             : FD_PROTOTYPES_BEGIN
      63             : 
      64             : static inline fd_instruction_account_t
      65             : fd_instruction_account_init( ushort idx_in_txn,
      66             :                              ushort idx_in_caller,
      67             :                              ushort idx_in_callee,
      68             :                              uchar  is_writable,
      69           0 :                              uchar  is_signer ) {
      70           0 :   fd_instruction_account_t acc = {
      71           0 :     .index_in_transaction = idx_in_txn,
      72           0 :     .index_in_caller      = idx_in_caller,
      73           0 :     .index_in_callee      = idx_in_callee,
      74           0 :     .is_writable          = is_writable,
      75           0 :     .is_signer            = is_signer,
      76           0 :   };
      77           0 :   return acc;
      78           0 : }
      79             : 
      80             : static inline void
      81             : fd_instr_info_setup_instr_account( fd_instr_info_t * instr,
      82             :                                    uchar             acc_idx_seen[ FD_INSTR_ACCT_MAX ],
      83             :                                    ushort            idx_in_txn,
      84             :                                    ushort            idx_in_caller,
      85             :                                    ushort            idx_in_callee,
      86             :                                    uchar             is_writable,
      87           0 :                                    uchar             is_signer ) {
      88           0 :   if( FD_LIKELY( idx_in_txn!=USHORT_MAX ) ) {
      89           0 :     instr->is_duplicate[ idx_in_callee ] = acc_idx_seen[ idx_in_txn ];
      90             : 
      91           0 :     if( FD_LIKELY( !acc_idx_seen[ idx_in_txn ] ) ) {
      92             :       /* This is the first time seeing this account */
      93           0 :       acc_idx_seen[ idx_in_txn ] = 1;
      94           0 :     }
      95           0 :   }
      96             : 
      97           0 :   instr->accounts[ idx_in_callee ] = fd_instruction_account_init( idx_in_txn,
      98           0 :                                                                   idx_in_caller,
      99           0 :                                                                   idx_in_callee,
     100           0 :                                                                   is_writable,
     101           0 :                                                                   is_signer );
     102           0 : }
     103             : 
     104             : /* fd_instr_info_accumulate_starting_lamports accumulates the starting lamports fields
     105             :    when setting up an fd_instr_info_t object.
     106             :    Note that the caller must zero out the starting lamports fields in fd_instr_info_t
     107             :    beforehand. */
     108             : 
     109             : void
     110             : fd_instr_info_accumulate_starting_lamports( fd_instr_info_t * instr,
     111             :                                             fd_txn_out_t *    txn_out,
     112             :                                             ushort            idx_in_callee,
     113             :                                             ushort            idx_in_txn );
     114             : 
     115             : void
     116             : fd_instr_info_init_from_txn_instr( fd_instr_info_t *      instr,
     117             :                                    fd_bank_t *            bank,
     118             :                                    fd_txn_in_t const *    txn_in,
     119             :                                    fd_txn_out_t *         txn_out,
     120             :                                    fd_txn_instr_t const * txn_instr );
     121             : 
     122             : /* https://github.com/anza-xyz/solana-sdk/blob/589e6237f203c2719c300dc044f4e00f48e66a8f/message/src/versions/v0/loaded.rs#L152-L157 */
     123             : FD_FN_PURE static inline int
     124             : fd_instr_acc_is_writable_idx( fd_instr_info_t const * instr,
     125           0 :                               ushort                  idx ) {
     126           0 :   if( FD_UNLIKELY( idx>=instr->acct_cnt ) ) {
     127           0 :     return 0;
     128           0 :   }
     129             : 
     130           0 :   return !!(instr->accounts[idx].is_writable);
     131           0 : }
     132             : 
     133             : /* fd_instr_acc_is_signer_idx returns:
     134             :     - 1 if account is signer
     135             :     - 0 (with *out_opt_err==0) if account is not signer
     136             :   If an error occurs during query, returns 0 and writes the
     137             :   error code to *out_opt_err. Possible values for out_opt_err:
     138             :     - FD_EXECUTOR_INSTR_ERR_MISSING_ACC occurs when the instr account
     139             :       index provided is invalid (out of bounds).
     140             :     - 0 if the query was successful. Check the return value to see
     141             :       if the account is a signer.
     142             : 
     143             :   https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L782-L791    */
     144             : FD_FN_PURE static inline int
     145             : fd_instr_acc_is_signer_idx( fd_instr_info_t const * instr,
     146             :                             ushort                  idx,
     147           0 :                             int *                   out_opt_err ) {
     148           0 :   if( FD_UNLIKELY( idx>=instr->acct_cnt ) ) {
     149           0 :     if( out_opt_err ) *out_opt_err = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     150           0 :     return 0;
     151           0 :   }
     152             : 
     153           0 :   if( out_opt_err ) *out_opt_err = 0;
     154           0 :   return !!(instr->accounts[idx].is_signer);
     155           0 : }
     156             : 
     157             : /* fd_instr_info_sum_account_lamports returns the sum of lamport account
     158             :    balances of all instruction accounts in the context.
     159             : 
     160             :    Aborts on integer overflow. */
     161             : 
     162             : int
     163             : fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr,
     164             :                                     fd_txn_out_t *          txn_out,
     165             :                                     ulong *                 total_lamports_h,
     166             :                                     ulong *                 total_lamports_l );
     167             : 
     168             : FD_PROTOTYPES_END
     169             : 
     170             : #endif /* HEADER_fd_src_flamenco_runtime_info_fd_instr_info_h */

Generated by: LCOV version 1.14