LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_instructions.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 25 75 33.3 %
Date: 2026-09-17 04:28:31 Functions: 2 3 66.7 %

          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           3 : instructions_serialized_size( fd_txn_t const * txn ) {
       7           3 :   ushort instr_cnt = txn->instr_cnt;
       8           3 :   ulong  serialized_size = sizeof(ushort)                // num_instructions
       9           3 :                            + (sizeof(ushort)*instr_cnt); // instruction offsets
      10             : 
      11           9 :   for( ushort i=0; i<instr_cnt; i++ ) {
      12           6 :     ushort data_sz  = txn->instr[i].data_sz;
      13           6 :     ushort acct_cnt = txn->instr[i].acct_cnt;
      14             : 
      15           6 :     serialized_size += sizeof(ushort); // num_accounts;
      16             : 
      17           6 :     serialized_size += acct_cnt * (
      18           6 :       sizeof(uchar)               // flags (is_signer, is_writeable)
      19           6 :       + sizeof(fd_pubkey_t)       // pubkey
      20           6 :     );
      21             : 
      22           6 :     serialized_size += sizeof(fd_pubkey_t)  // program_id pubkey
      23           6 :         + sizeof(ushort)                    // instr_data_len;
      24           6 :         + data_sz;                          // instr_data;
      25             : 
      26           6 :   }
      27             : 
      28           3 :   serialized_size += sizeof(ushort); // current_instr_idx
      29             : 
      30           3 :   return serialized_size;
      31           3 : }
      32             : 
      33             : /* https://github.com/anza-xyz/agave/blob/v2.1.1/svm/src/account_loader.rs#L547-L576 */
      34             : int
      35             : fd_sysvar_instructions_serialize_account( fd_txn_in_t const * txn_in,
      36             :                                           fd_txn_out_t *      txn_out,
      37           3 :                                           ulong               txn_idx ) {
      38           3 :   fd_txn_t const * txn           = TXN( txn_in->txn );
      39           3 :   ulong            serialized_sz = instructions_serialized_size( txn );
      40             : 
      41             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.1/svm/src/account_loader.rs#L660-L665 */
      42           3 :   if( FD_UNLIKELY( fd_sysvar_instructions_offsets_overflow( txn ) ) ) {
      43           3 :     return FD_RUNTIME_TXN_ERR_MAX_LOADED_ACCOUNTS_DATA_SIZE_EXCEEDED;
      44           3 :   }
      45           0 :   FD_TEST( serialized_sz<=FD_SYSVAR_INSTRUCTIONS_FOOTPRINT );
      46             : 
      47           0 :   fd_acc_t * acc = txn_out->accounts.account[ txn_idx ];
      48             :   /* Agave sets up the borrowed account for the instructions sysvar to contain
      49             :      default values except for the data which is serialized into the account.
      50             :      The accdb returns data=NULL for the sysvar instructions account because
      51             :      it is constructed on the fly and never persisted; point it at the
      52             :      dedicated scratch buffer in txn_out. */
      53             : 
      54           0 :   fd_memcpy( acc->owner, &fd_sysvar_owner_id, sizeof(fd_pubkey_t) );
      55           0 :   acc->lamports   = 0UL;
      56           0 :   acc->executable = 0;
      57           0 :   acc->data       = txn_out->accounts.sysvar_instructions_data;
      58           0 :   acc->data_len   = serialized_sz;
      59             : 
      60           0 :   uchar * serialized_instructions = acc->data;
      61           0 :   ulong offset = 0;
      62             : 
      63             :   // num_instructions
      64           0 :   ushort instr_cnt = txn->instr_cnt;
      65           0 :   FD_STORE( ushort, serialized_instructions + offset, instr_cnt);
      66           0 :   offset += sizeof(ushort);
      67             : 
      68             :   // instruction offsets
      69           0 :   uchar * serialized_instruction_offsets = serialized_instructions + offset;
      70           0 :   offset += (ushort)(sizeof(ushort) * instr_cnt);
      71             : 
      72             :   // serialize instructions
      73           0 :   for( ushort i=0; i<instr_cnt; ++i ) {
      74             :     // set the instruction offset
      75           0 :     FD_STORE( ushort, serialized_instruction_offsets, (ushort)offset );
      76           0 :     serialized_instruction_offsets += sizeof(ushort);
      77             : 
      78           0 :     fd_txn_instr_t const * instr = &txn->instr[i];
      79             : 
      80             :     // num_accounts
      81           0 :     FD_STORE( ushort, serialized_instructions + offset, instr->acct_cnt );
      82           0 :     offset += sizeof(ushort);
      83             : 
      84           0 :     uchar const * instr_accts = fd_txn_get_instr_accts( instr, txn_in->txn->payload );
      85           0 :     for( ushort j=0; j<instr->acct_cnt; j++ ) {
      86           0 :       uchar idx_in_txn          = instr_accts[j];
      87           0 :       uchar is_writable         = (uchar)fd_runtime_account_is_writable_idx( txn_in, txn_out, idx_in_txn );
      88           0 :       uchar is_signer           = (uchar)fd_txn_is_signer( txn, idx_in_txn );
      89           0 :       uchar flags               = (uchar)( ((!!is_signer)*FD_INSTR_ACCT_FLAGS_IS_SIGNER) | ((!!is_writable)*FD_INSTR_ACCT_FLAGS_IS_WRITABLE) );
      90             : 
      91             :       // flags
      92           0 :       FD_STORE( uchar, serialized_instructions + offset, flags );
      93           0 :       offset += sizeof(uchar);
      94             : 
      95             :       // pubkey
      96           0 :       FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_out->accounts.keys[ idx_in_txn ] );
      97           0 :       offset += sizeof(fd_pubkey_t);
      98           0 :     }
      99             : 
     100             :     // program_id_pubkey
     101           0 :     FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_out->accounts.keys[ instr->program_id ] );
     102           0 :     offset += sizeof(fd_pubkey_t);
     103             : 
     104             :     // instr_data_len
     105           0 :     FD_STORE( ushort, serialized_instructions + offset, instr->data_sz );
     106           0 :     offset += sizeof(ushort);
     107             : 
     108             :     // instr_data
     109           0 :     uchar const * instr_data = fd_txn_get_instr_data( instr, txn_in->txn->payload );
     110           0 :     fd_memcpy( serialized_instructions + offset, instr_data, instr->data_sz );
     111           0 :     offset += instr->data_sz;
     112           0 :   }
     113             : 
     114           0 :   FD_STORE( ushort, serialized_instructions + offset, 0 );
     115           0 :   offset += sizeof(ushort);
     116             : 
     117           0 :   return FD_RUNTIME_EXECUTE_SUCCESS;
     118           0 : }
     119             : 
     120             : /* Stores the current instruction index in the instructions sysvar account.
     121             :    https://github.com/anza-xyz/solana-sdk/blob/instructions-sysvar%40v2.2.1/instructions-sysvar/src/lib.rs#L164-L167 */
     122             : void
     123             : fd_sysvar_instructions_update_current_instr_idx( fd_acc_t * acc,
     124           0 :                                                  ushort     current_instr_idx ) {
     125             :   /* Extra safety checks */
     126           0 :   if( FD_UNLIKELY( acc->data_len<sizeof(ushort) ) ) {
     127           0 :     return;
     128           0 :   }
     129             : 
     130           0 :   uchar * serialized_current_instr_idx = acc->data + (acc->data_len - sizeof(ushort));
     131           0 :   FD_STORE( ushort, serialized_current_instr_idx, current_instr_idx );
     132           0 : }

Generated by: LCOV version 1.14