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 78 0.0 %
Date: 2025-11-25 04:50:41 Functions: 0 3 0.0 %

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

Generated by: LCOV version 1.14