LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_instructions.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 76 80 95.0 %
Date: 2026-03-19 18:19:27 Functions: 3 3 100.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          31 : instructions_serialized_size( fd_txn_t const * txn ) {
       7          31 :   ushort instr_cnt = txn->instr_cnt;
       8          31 :   ulong  serialized_size = sizeof(ushort)                // num_instructions
       9          31 :                            + (sizeof(ushort)*instr_cnt); // instruction offsets
      10             : 
      11          76 :   for( ushort i=0; i<instr_cnt; i++ ) {
      12          45 :     ushort data_sz  = txn->instr[i].data_sz;
      13          45 :     ushort acct_cnt = txn->instr[i].acct_cnt;
      14             : 
      15          45 :     serialized_size += sizeof(ushort); // num_accounts;
      16             : 
      17          45 :     serialized_size += acct_cnt * (
      18          45 :       sizeof(uchar)               // flags (is_signer, is_writeable)
      19          45 :       + sizeof(fd_pubkey_t)       // pubkey
      20          45 :     );
      21             : 
      22          45 :     serialized_size += sizeof(fd_pubkey_t)  // program_id pubkey
      23          45 :         + sizeof(ushort)                    // instr_data_len;
      24          45 :         + data_sz;                          // instr_data;
      25             : 
      26          45 :   }
      27             : 
      28          31 :   serialized_size += sizeof(ushort); // current_instr_idx
      29             : 
      30          31 :   return serialized_size;
      31          31 : }
      32             : 
      33             : /* https://github.com/anza-xyz/agave/blob/v2.1.1/svm/src/account_loader.rs#L547-L576 */
      34             : void
      35             : fd_sysvar_instructions_serialize_account( fd_runtime_t *      runtime,
      36             :                                           fd_bank_t *         bank,
      37             :                                           fd_txn_in_t const * txn_in,
      38             :                                           fd_txn_out_t *      txn_out,
      39          31 :                                           ulong               txn_idx ) {
      40          31 :   fd_txn_t const * txn           = TXN( txn_in->txn );
      41          31 :   ulong            serialized_sz = instructions_serialized_size( txn );
      42             : 
      43          31 :   int index;
      44          31 :   int err = fd_runtime_get_account_with_key( txn_in,
      45          31 :                                              txn_out,
      46          31 :                                              &fd_sysvar_instructions_id,
      47          31 :                                              &index,
      48          31 :                                              fd_runtime_account_check_exists );
      49          31 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS && index==-1 ) ) {
      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          31 :   fd_account_meta_t * meta = txn_out->accounts.account[ txn_idx ].meta;
      57             :   /* Agave sets up the borrowed account for the instructions sysvar to contain
      58             :      default values except for the data which is serialized into the account. */
      59             : 
      60          31 :   fd_memcpy( meta->owner, &fd_sysvar_owner_id, sizeof(fd_pubkey_t) );
      61          31 :   meta->lamports   = 0UL;
      62          31 :   meta->executable = 0;
      63          31 :   meta->dlen       = (uint)serialized_sz;
      64             : 
      65          31 :   runtime->accounts.starting_lamports[txn_idx] = 0UL;
      66          31 :   runtime->accounts.starting_dlen[txn_idx]     = serialized_sz;
      67             : 
      68          31 :   uchar * serialized_instructions = fd_account_data( meta );
      69          31 :   ulong offset = 0;
      70             : 
      71             :   // num_instructions
      72          31 :   ushort instr_cnt = txn->instr_cnt;
      73          31 :   FD_STORE( ushort, serialized_instructions + offset, instr_cnt);
      74          31 :   offset += sizeof(ushort);
      75             : 
      76             :   // instruction offsets
      77          31 :   uchar * serialized_instruction_offsets = serialized_instructions + offset;
      78          31 :   offset += (ushort)(sizeof(ushort) * instr_cnt);
      79             : 
      80             :   // serialize instructions
      81          76 :   for( ushort i=0; i<instr_cnt; ++i ) {
      82             :     // set the instruction offset
      83          45 :     FD_STORE( ushort, serialized_instruction_offsets, (ushort) offset );
      84          45 :     serialized_instruction_offsets += sizeof(ushort);
      85             : 
      86          45 :     fd_txn_instr_t const * instr = &txn->instr[i];
      87             : 
      88             :     // num_accounts
      89          45 :     FD_STORE( ushort, serialized_instructions + offset, instr->acct_cnt );
      90          45 :     offset += sizeof(ushort);
      91             : 
      92          45 :     uchar const * instr_accts = fd_txn_get_instr_accts( instr, txn_in->txn->payload );
      93         970 :     for( ushort j=0; j<instr->acct_cnt; j++ ) {
      94         925 :       uchar idx_in_txn          = instr_accts[j];
      95         925 :       uchar is_writable         = (uchar)fd_runtime_account_is_writable_idx( txn_in, txn_out, bank, idx_in_txn );
      96         925 :       uchar is_signer           = (uchar)fd_txn_is_signer( txn, idx_in_txn );
      97         925 :       uchar flags               = (uchar)( ((!!is_signer)*FD_INSTR_ACCT_FLAGS_IS_SIGNER) | ((!!is_writable)*FD_INSTR_ACCT_FLAGS_IS_WRITABLE) );
      98             : 
      99             :       // flags
     100         925 :       FD_STORE( uchar, serialized_instructions + offset, flags );
     101         925 :       offset += sizeof(uchar);
     102             : 
     103             :       // pubkey
     104         925 :       FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_out->accounts.keys[ idx_in_txn ] );
     105         925 :       offset += sizeof(fd_pubkey_t);
     106         925 :     }
     107             : 
     108             :     // program_id_pubkey
     109          45 :     FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_out->accounts.keys[ instr->program_id ] );
     110          45 :     offset += sizeof(fd_pubkey_t);
     111             : 
     112             :     // instr_data_len
     113          45 :     FD_STORE( ushort, serialized_instructions + offset, instr->data_sz );
     114          45 :     offset += sizeof(ushort);
     115             : 
     116             :     // instr_data
     117          45 :     uchar const * instr_data = fd_txn_get_instr_data( instr, txn_in->txn->payload );
     118          45 :     fd_memcpy( serialized_instructions + offset, instr_data, instr->data_sz );
     119          45 :     offset += instr->data_sz;
     120          45 :   }
     121             : 
     122          31 :   FD_STORE( ushort, serialized_instructions + offset, 0 );
     123          31 :   offset += sizeof(ushort);
     124          31 : }
     125             : 
     126             : /* Stores the current instruction index in the instructions sysvar account.
     127             :    https://github.com/anza-xyz/solana-sdk/blob/instructions-sysvar%40v2.2.1/instructions-sysvar/src/lib.rs#L164-L167 */
     128             : void
     129             : fd_sysvar_instructions_update_current_instr_idx( fd_account_meta_t * meta,
     130          68 :                                                  ushort              current_instr_idx ) {
     131             :   /* Extra safety checks */
     132          68 :   if( FD_UNLIKELY( meta->dlen<sizeof(ushort) ) ) {
     133           0 :     return;
     134           0 :   }
     135             : 
     136          68 :   uchar * serialized_current_instr_idx = fd_account_data( meta ) + (meta->dlen - sizeof(ushort));
     137          68 :   FD_STORE( ushort, serialized_current_instr_idx, current_instr_idx );
     138          68 : }

Generated by: LCOV version 1.14