LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_instructions.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 77 0.0 %
Date: 2025-10-13 04:42:14 Functions: 0 3 0.0 %

          Line data    Source code
       1             : #include "fd_sysvar_instructions.h"
       2             : #include "../fd_borrowed_account.h"
       3             : #include "../fd_system_ids.h"
       4             : 
       5             : static ulong
       6             : instructions_serialized_size( fd_instr_info_t const *   instrs,
       7           0 :                               ushort                    instrs_cnt ) {
       8           0 :   ulong serialized_size = 0;
       9             : 
      10           0 :   serialized_size += sizeof(ushort)       // num_instructions
      11           0 :     + (sizeof(ushort) * instrs_cnt);      // instruction offsets
      12             : 
      13           0 :   for ( ushort i = 0; i < instrs_cnt; ++i ) {
      14           0 :     fd_instr_info_t const * instr = &instrs[i];
      15             : 
      16           0 :     serialized_size += sizeof(ushort); // num_accounts;
      17             : 
      18           0 :     serialized_size += instr->acct_cnt * (
      19           0 :       sizeof(uchar)               // flags (is_signer, is_writeable)
      20           0 :       + sizeof(fd_pubkey_t)         // pubkey
      21           0 :     );
      22             : 
      23           0 :     serialized_size += sizeof(fd_pubkey_t)  // program_id pubkey
      24           0 :         + sizeof(ushort)                    // instr_data_len;
      25           0 :         + instr->data_sz;                   // instr_data;
      26             : 
      27           0 :   }
      28             : 
      29           0 :   serialized_size += sizeof(ushort); // current_instr_idx
      30             : 
      31           0 :   return serialized_size;
      32           0 : }
      33             : 
      34             : /* https://github.com/anza-xyz/agave/blob/v2.1.1/svm/src/account_loader.rs#L547-L576 */
      35             : void
      36             : fd_sysvar_instructions_serialize_account( fd_exec_txn_ctx_t *      txn_ctx,
      37             :                                           fd_instr_info_t const *  instrs,
      38           0 :                                           ushort                   instrs_cnt ) {
      39           0 :   ulong serialized_sz = instructions_serialized_size( instrs, instrs_cnt );
      40             : 
      41           0 :   fd_txn_account_t * rec = NULL;
      42           0 :   int err = fd_exec_txn_ctx_get_account_with_key( txn_ctx,
      43           0 :                                                   &fd_sysvar_instructions_id,
      44           0 :                                                   &rec,
      45           0 :                                                   fd_txn_account_check_exists );
      46           0 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS && rec==NULL ) ) {
      47             :     /* The way we use this, this should NEVER hit since the borrowed accounts should be set up
      48             :        before this is called, and this is only called if the sysvar instructions account is in
      49             :        the borrowed accounts list. */
      50           0 :     FD_LOG_ERR(( "Failed to view sysvar instructions borrowed account. It may not be included in the txn account keys." ));
      51           0 :   }
      52             : 
      53             :   /* This stays within the FD spad allocation bounds because...
      54             :      1. Case 1: rec->meta!=NULL
      55             :         - rec->meta was set up in `fd_executor_setup_accounts_for_txn()` and data was allocated from the spad
      56             :         - No need to allocate meta and data here
      57             :      2. Case 2: rec->meta==NULL
      58             :         - `fd_executor_setup_accounts_for_txn()` did not make an spad allocation for this account
      59             :         - spad memory is sized out for allocations for 128 (max number) accounts
      60             :         - sizeof(fd_account_meta_t) + serialized_sz will always be less than FD_ACC_TOT_SZ_MAX
      61             :         - at most 127 accounts could be using spad memory right now, so this allocation is safe */
      62           0 :   if( !fd_txn_account_is_mutable( rec ) ) {
      63           0 :     uchar *             mem  = fd_spad_alloc( txn_ctx->spad, FD_TXN_ACCOUNT_ALIGN, sizeof(fd_account_meta_t) + serialized_sz );
      64           0 :     fd_account_meta_t * meta = (fd_account_meta_t *)mem;
      65           0 :     fd_txn_account_t *  acc  = fd_txn_account_join( fd_txn_account_new( rec, &fd_sysvar_instructions_id, meta, 1 ), txn_ctx->spad_wksp );
      66           0 :     if( FD_UNLIKELY( !acc ) ) {
      67           0 :       FD_LOG_CRIT(( "Failed to join txn account" ));
      68           0 :     }
      69           0 :   }
      70             : 
      71             :   /* Agave sets up the borrowed account for the instructions sysvar to contain
      72             :      default values except for the data which is serialized into the account. */
      73             : 
      74           0 :   fd_txn_account_set_owner( rec, &fd_sysvar_owner_id );
      75           0 :   fd_txn_account_set_lamports( rec, 0UL );
      76           0 :   fd_txn_account_set_executable( rec, 0 );
      77           0 :   fd_txn_account_set_data_len( rec, serialized_sz );
      78           0 :   rec->starting_lamports = 0UL;
      79             : 
      80           0 :   uchar * serialized_instructions = fd_txn_account_get_data_mut( rec );
      81           0 :   ulong offset = 0;
      82             : 
      83             :   // TODO: do we needs bounds checking?
      84             :   // num_instructions
      85           0 :   FD_STORE( ushort, serialized_instructions + offset, instrs_cnt);
      86           0 :   offset += sizeof(ushort);
      87             : 
      88             :   // instruction offsets
      89           0 :   uchar * serialized_instruction_offsets = serialized_instructions + offset;
      90           0 :   offset += (ushort)(sizeof(ushort) * instrs_cnt);
      91             : 
      92             :   // serialize instructions
      93           0 :   for( ushort i = 0; i < instrs_cnt; ++i ) {
      94             :     // set the instruction offset
      95           0 :     FD_STORE( ushort, serialized_instruction_offsets, (ushort) offset );
      96           0 :     serialized_instruction_offsets += sizeof(ushort);
      97             : 
      98           0 :     fd_instr_info_t const * instr = &instrs[i];
      99             : 
     100             :     // num_accounts
     101           0 :     FD_STORE( ushort, serialized_instructions + offset, instr->acct_cnt );
     102           0 :     offset += sizeof(ushort);
     103             : 
     104           0 :     for ( ushort j = 0; j < instr->acct_cnt; j++ ) {
     105             :       // flags
     106           0 :       FD_STORE( uchar, serialized_instructions + offset, fd_instr_get_acc_flags( instr, j ) );
     107           0 :       offset += sizeof(uchar);
     108             : 
     109             :       // pubkey
     110           0 :       ushort idx_in_txn = instr->accounts[j].index_in_transaction;
     111           0 :       FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_ctx->account_keys[ idx_in_txn ] );
     112           0 :       offset += sizeof(fd_pubkey_t);
     113           0 :     }
     114             : 
     115             :     // program_id_pubkey
     116           0 :     FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_ctx->account_keys[ instr->program_id ] );
     117           0 :     offset += sizeof(fd_pubkey_t);
     118             : 
     119             :     // instr_data_len
     120           0 :     FD_STORE( ushort, serialized_instructions + offset, instr->data_sz );
     121           0 :     offset += sizeof(ushort);
     122             : 
     123             :     // instr_data
     124           0 :     fd_memcpy( serialized_instructions + offset, instr->data, instr->data_sz );
     125           0 :     offset += instr->data_sz;
     126           0 :   }
     127             : 
     128             :   //
     129           0 :   FD_STORE( ushort, serialized_instructions + offset, 0 );
     130           0 :   offset += sizeof(ushort);
     131           0 : }
     132             : 
     133             : /* Stores the current instruction index in the instructions sysvar account.
     134             :    https://github.com/anza-xyz/solana-sdk/blob/instructions-sysvar%40v2.2.1/instructions-sysvar/src/lib.rs#L164-L167 */
     135             : void
     136             : fd_sysvar_instructions_update_current_instr_idx( fd_txn_account_t * rec,
     137           0 :                                                  ushort             current_instr_idx ) {
     138             :   /* Extra safety checks */
     139           0 :   if( FD_UNLIKELY( fd_txn_account_get_data_len( rec )<sizeof(ushort) ) ) {
     140           0 :     return;
     141           0 :   }
     142             : 
     143           0 :   uchar * serialized_current_instr_idx = fd_txn_account_get_data_mut( rec ) + (fd_txn_account_get_data_len( rec ) - sizeof(ushort));
     144           0 :   FD_STORE( ushort, serialized_current_instr_idx, current_instr_idx );
     145           0 : }

Generated by: LCOV version 1.14