LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_instructions.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 63 74 85.1 %
Date: 2025-01-08 12:08:44 Functions: 2 3 66.7 %

          Line data    Source code
       1             : #include "fd_sysvar_instructions.h"
       2             : #include "../fd_account.h"
       3             : #include "../fd_system_ids.h"
       4             : 
       5             : static ulong
       6             : instructions_serialized_size( fd_instr_info_t const *   instrs,
       7          93 :                               ushort                    instrs_cnt ) {
       8          93 :   ulong serialized_size = 0;
       9             : 
      10          93 :   serialized_size += sizeof(ushort)       // num_instructions
      11          93 :     + (sizeof(ushort) * instrs_cnt);      // instruction offsets
      12             : 
      13         204 :   for ( ushort i = 0; i < instrs_cnt; ++i ) {
      14         111 :     fd_instr_info_t const * instr = &instrs[i];
      15             : 
      16         111 :     serialized_size += sizeof(ushort); // num_accounts;
      17             : 
      18         111 :     serialized_size += instr->acct_cnt * (
      19         111 :       sizeof(uchar)               // flags (is_signer, is_writeable)
      20         111 :       + sizeof(fd_pubkey_t)         // pubkey
      21         111 :     );
      22             : 
      23         111 :     serialized_size += sizeof(fd_pubkey_t)  // program_id pubkey
      24         111 :         + sizeof(ushort)                    // instr_data_len;
      25         111 :         + instr->data_sz;                   // instr_data;
      26             : 
      27         111 :   }
      28             : 
      29          93 :   serialized_size += sizeof(ushort); // current_instr_idx
      30             : 
      31          93 :   return serialized_size;
      32          93 : }
      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          93 :                                           ushort                   instrs_cnt ) {
      39          93 :   ulong serialized_sz = instructions_serialized_size( instrs, instrs_cnt );
      40             : 
      41          93 :   fd_borrowed_account_t * rec = NULL;
      42          93 :   int err = fd_txn_borrowed_account_view( txn_ctx, &fd_sysvar_instructions_id, &rec );
      43          93 :   if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS && rec == NULL ) ) {
      44             :     /* The way we use this, this should NEVER hit since the borrowed accounts should be set up
      45             :        before this is called, and this is only called if the sysvar instructions account is in
      46             :        the borrowed accounts list. */
      47           0 :     FD_LOG_ERR(( "Failed to view sysvar instructions borrowed account. It may not be included in the txn account keys." ));
      48           0 :   }
      49             :   
      50             :   /* This stays within the FD spad allocation bounds because...
      51             :      1. Case 1: rec->meta!=NULL
      52             :         - rec->meta was set up in `fd_executor_setup_borrowed_accounts_for_txn()` and data was allocated from the spad
      53             :         - No need to allocate meta and data here 
      54             :      2. Case 2: rec->meta==NULL
      55             :         - `fd_executor_setup_borrowed_accounts_for_txn()` did not make an spad allocation for this account
      56             :         - spad memory is sized out for allocations for 128 (max number) accounts 
      57             :         - sizeof(fd_account_meta_t) + serialized_sz will always be less than FD_ACC_TOT_SZ_MAX
      58             :         - at most 127 accounts could be using spad memory right now, so this allocation is safe */
      59          93 :   if( rec->meta==NULL ) {
      60          93 :     fd_account_meta_t * meta = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, sizeof(fd_account_meta_t) + serialized_sz );
      61          93 :     void * data = (uchar *)meta + sizeof(fd_account_meta_t);
      62             : 
      63          93 :     rec->const_meta = rec->meta = meta;
      64          93 :     rec->const_data = rec->data = data;
      65          93 :   }
      66             : 
      67             :   /* Agave sets up the borrowed account for the instructions sysvar to contain
      68             :      default values except for the data which is serialized into the account. */
      69             : 
      70          93 :   memcpy( rec->meta->info.owner, fd_sysvar_owner_id.key, sizeof(fd_pubkey_t) );
      71          93 :   rec->starting_lamports     = 0UL;
      72          93 :   rec->meta->info.lamports   = 0UL; // TODO: This cannot be right... well, it gets destroyed almost instantly...
      73          93 :   rec->meta->info.executable = 0;
      74          93 :   rec->meta->info.rent_epoch = 0UL;
      75          93 :   rec->meta->dlen            = serialized_sz;
      76             : 
      77          93 :   uchar * serialized_instructions = rec->data;
      78          93 :   ulong offset = 0;
      79             : 
      80             :   // TODO: do we needs bounds checking?
      81             :   // num_instructions
      82          93 :   FD_STORE( ushort, serialized_instructions + offset, instrs_cnt);
      83          93 :   offset += sizeof(ushort);
      84             : 
      85             :   // instruction offsets
      86          93 :   uchar * serialized_instruction_offsets = serialized_instructions + offset;
      87          93 :   offset += (ushort)(sizeof(ushort) * instrs_cnt);
      88             : 
      89             :   // serialize instructions
      90         204 :   for( ushort i = 0; i < instrs_cnt; ++i ) {
      91             :     // set the instruction offset
      92         111 :     FD_STORE( ushort, serialized_instruction_offsets, (ushort) offset );
      93         111 :     serialized_instruction_offsets += sizeof(ushort);
      94             : 
      95         111 :     fd_instr_info_t const * instr = &instrs[i];
      96             : 
      97             :     // num_accounts
      98         111 :     FD_STORE( ushort, serialized_instructions + offset, instr->acct_cnt );
      99         111 :     offset += sizeof(ushort);
     100             : 
     101         402 :     for ( ushort j = 0; j < instr->acct_cnt; j++ ) {
     102             :       // flags
     103         291 :       FD_STORE( uchar, serialized_instructions + offset, instr->acct_flags[j] );
     104         291 :       offset += sizeof(uchar);
     105             : 
     106             :       // pubkey
     107         291 :       FD_STORE( fd_pubkey_t, serialized_instructions + offset, instr->acct_pubkeys[j] );
     108         291 :       offset += sizeof(fd_pubkey_t);
     109         291 :     }
     110             : 
     111             :     // program_id_pubkey
     112         111 :     FD_STORE( fd_pubkey_t, serialized_instructions + offset, instr->program_id_pubkey );
     113         111 :     offset += sizeof(fd_pubkey_t);
     114             : 
     115             :     // instr_data_len
     116         111 :     FD_STORE( ushort, serialized_instructions + offset, instr->data_sz );
     117         111 :     offset += sizeof(ushort);
     118             : 
     119             :     // instr_data
     120         111 :     fd_memcpy( serialized_instructions + offset, instr->data, instr->data_sz );
     121         111 :     offset += instr->data_sz;
     122         111 :   }
     123             : 
     124             :   //
     125          93 :   FD_STORE( ushort, serialized_instructions + offset, 0 );
     126          93 :   offset += sizeof(ushort);
     127          93 : }
     128             : 
     129             : int
     130             : fd_sysvar_instructions_update_current_instr_idx( fd_exec_txn_ctx_t *  txn_ctx,
     131           0 :                                                  ushort             current_instr_idx ) {
     132           0 :   fd_borrowed_account_t * rec = NULL;
     133           0 :   int err = fd_txn_borrowed_account_modify( txn_ctx, &fd_sysvar_instructions_id, 0, &rec );
     134           0 :   if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) )
     135           0 :     return FD_ACC_MGR_ERR_READ_FAILED;
     136             : 
     137           0 :   uchar * serialized_current_instr_idx = rec->data + (rec->meta->dlen - sizeof(ushort));
     138           0 :   FD_STORE( ushort, serialized_current_instr_idx, current_instr_idx );
     139             : 
     140           0 :   return FD_ACC_MGR_SUCCESS;
     141           0 : }

Generated by: LCOV version 1.14