LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_bpf_loader_serialization.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 386 429 90.0 %
Date: 2026-11-11 12:40:43 Functions: 8 8 100.0 %

          Line data    Source code
       1             : #include "fd_bpf_loader_serialization.h"
       2             : #include "../fd_borrowed_account.h"
       3             : #include "../fd_runtime.h"
       4             : #include "../../vm/fd_vm_base.h"
       5             : 
       6             : /* This file is responsible for serializing and deserializing
       7             :    the input region of the BPF virtual machine. The input region contains
       8             :    instruction information, account metadata, and account data. The high level
       9             :    format is as follows:
      10             : 
      11             :    [ account 1 metadata, account 1 data, account 2 metadata, account 2 data, ...,
      12             :      account N metadata, account N data, instruction info. ]
      13             : 
      14             :   This format by no means comprehensive, but it should give an idea of how
      15             :   the input region is laid out. When direct mapping is not enabled, the input
      16             :   region is stored as a single contiguous buffer. This buffer in the host
      17             :   address space is then mapped to the VM virtual address space (the range
      18             :   starting with 0x400...). This means to serialize into the input region, we
      19             :   need to copy in the account metadata and account data into the buffer for
      20             :   each account. Everything must get copied out after execution is complete.
      21             :   A consequence of this is that a memcpy for the account data is required
      22             :   for each serialize and deserialize operation: this can potentially become
      23             :   expensive if there are many accounts and many nested CPI calls. Also, the
      24             :   entire memory region is treated as writable even though many accounts are
      25             :   read-only. This means that for all read-only accounts, a memcmp must be done
      26             :   while deserializing to make sure that the account (meta)data has not changed.
      27             : 
      28             :   Direct mapping offers a solution to this by introducing a more sophisticated
      29             :   memory translation protocol. Now the account data is not copied into a single
      30             :   contiguous buffer, but instead a borrowed account's data is directly mapped
      31             :   into the VM's virtual address space. The host memory for the input region is
      32             :   now represented by a list of fragmented memory regions. These sub regions
      33             :   also have different write permissions. This should solve the problem of
      34             :   having to memcpy/memcmp account data regions (which can be up to 10MiB each).
      35             :   There is some nuance to this, as the account data can be resized. This means
      36             :   that memcpys for account data regions can't totally be avoided.
      37             : 
      38             :   SERIALIZATION BEHAVIOR
      39             :   ==========================================
      40             : 
      41             :   This implementation supports three distinct serialization modes based on two
      42             :   feature flags: virtual_address_space_adjustments and
      43             :   account_data_direct_mapping.
      44             : 
      45             :   MODE 1
      46             :   --------------------------------------
      47             :   virtual_address_space_adjustments = false
      48             :   account_data_direct_mapping       = false
      49             : 
      50             :   Memory Layout:
      51             :   - Single contiguous buffer in host memory
      52             :   - Buffer contains: [metadata1, data1, realloc_buffer1, metadata2, data2,
      53             :     realloc_buffer2, ..., metadataN, dataN, realloc_bufferN, instruction_info]
      54             :   - Each account gets: original data + MAX_PERMITTED_DATA_INCREASE (10KiB)
      55             :   - Padding added to maintain 16-byte alignment between accounts
      56             :   - Entire buffer is writable
      57             : 
      58             :   Memory Regions:
      59             :   - The entire input region buffer is mapped as one contiguous VM address
      60             :     space region
      61             : 
      62             :   Serialization Process:
      63             :   - Account data is memcpy'd into the buffer
      64             :   - 10KiB realloc buffer is zeroed out and appended after each account's data
      65             :   - Alignment padding is zeroed and added after realloc buffer
      66             : 
      67             :   Deserialization Process:
      68             :   - Account data must be memcpy'd back from buffer to borrowed account
      69             :   - For writable accounts: always copy data back
      70             :   - For read-only accounts: memcmp to verify data unchanged, error if modified
      71             :   - Account resizing allowed if account permissions permit it
      72             : 
      73             :   MODE 2
      74             :   -------------------------------------------
      75             :   virtual_address_space_adjustments = true
      76             :   account_data_direct_mapping       = false
      77             : 
      78             :   Memory Layout:
      79             :   - Still uses a single contiguous buffer, but organized into fragmented
      80             :     regions.
      81             :   - Each account now has separate regions for metadata and data+realloc.
      82             :   - Buffer contains: [metadata1, data1+realloc1, metadata2, data2+realloc2, ...,
      83             :     metadataN, dataN+reallocN, instruction_info].
      84             :   - Each metadata region and data region tracked separately in
      85             :     input_mem_regions.
      86             : 
      87             :   Memory Regions:
      88             :   - For each account:
      89             :     * Region 0: Account metadata (writable)
      90             :     * Region 1: Account data + realloc space (writable if account is writable)
      91             :   - If the account is owned by the deprecated loader, no realloc region is
      92             :     created as the deprecated loader does not support resizing accounts.
      93             : 
      94             :   Serialization:
      95             :   - Account metadata serialized first, added as a memory region.
      96             :   - Account data memcpy'd into buffer - not directly mapped.
      97             :   - 10KiB realloc buffer zeroed and appended (not direct mapped).
      98             :   - Data region created pointing to copied data in buffer.
      99             : 
     100             :   MODE 3: Direct Mapping (requires virtual_address_space_adjustments)
     101             :   -----------------------------------------------
     102             :   virtual_address_space_adjustments = true
     103             :   account_data_direct_mapping       = true
     104             : 
     105             :   This is very similar to virtual_address_space_adjustments, but account
     106             :   data is NOT copied into the input region buffer.
     107             : 
     108             :   Instead, the data region points directly to the staging area for the
     109             :   account in the transaction account's data. This staging area has enough
     110             :   space to hold the account data and the realloc buffer. Changes to this
     111             :   staging area will be written back to the account database in transaction
     112             :   finalization.
     113             :  */
     114             : 
     115             : /* Add a new memory region to represent the input region. All of the memory
     116             :    regions here have sorted virtual addresses. These regions may or may not
     117             :    correspond to an account's data region. If it corresponds to metadata,
     118             :    the pubkey for the region will be NULL. */
     119             : static void
     120             : new_input_mem_region( fd_vm_input_region_t * input_mem_regions,
     121             :                       uint *                 input_mem_regions_cnt,
     122             :                       const uchar *          buffer,
     123             :                       ulong                  region_sz,
     124             :                       ulong                  address_space_reserved,
     125             :                       uchar                  is_writable,
     126       87233 :                       ulong                  acc_region_meta_idx ) {
     127             : 
     128             :   /* The start vaddr of the new region should be equal to start of the previous
     129             :      region added to the address space reserved for the region. */
     130       87233 :   ulong vaddr_offset = *input_mem_regions_cnt==0UL ? 0UL : input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
     131       74503 :                                                            input_mem_regions[ *input_mem_regions_cnt-1U ].address_space_reserved;
     132       87233 :   input_mem_regions[ *input_mem_regions_cnt ].is_writable            = is_writable;
     133       87233 :   input_mem_regions[ *input_mem_regions_cnt ].haddr                  = (ulong)buffer;
     134       87233 :   input_mem_regions[ *input_mem_regions_cnt ].region_sz              = (uint)region_sz;
     135       87233 :   input_mem_regions[ *input_mem_regions_cnt ].address_space_reserved = address_space_reserved;
     136       87233 :   input_mem_regions[ *input_mem_regions_cnt ].vaddr_offset           = vaddr_offset;
     137       87233 :   input_mem_regions[ *input_mem_regions_cnt ].acc_region_meta_idx    = acc_region_meta_idx;
     138       87233 :   (*input_mem_regions_cnt)++;
     139       87233 : }
     140             : 
     141             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L128-L190 */
     142             : /* This function handles casing for direct mapping being enabled as well as if
     143             :    the alignment is being stored. In the case where direct mapping is not
     144             :    enabled, we copy in the account data and a 10KiB buffer into the input region.
     145             :    These both go into the same memory buffer.  With direct mapping, a
     146             :    single region points to the account data and reserves address space
     147             :    for growth.  In both cases, padding is used to maintain 8 byte
     148             :    alignment. If alignment is not required, then a resizing buffer is not used
     149             :    as the deprecated loader doesn't allow for resizing accounts. */
     150             : static ulong
     151             : write_account( fd_borrowed_account_t *   account,
     152             :                uchar                     instr_acc_idx,
     153             :                uchar * *                 serialized_params,
     154             :                uchar * *                 serialized_params_start,
     155             :                fd_vm_input_region_t *    input_mem_regions,
     156             :                uint *                    input_mem_regions_cnt,
     157             :                fd_vm_acc_region_meta_t * acc_region_metas,
     158             :                int                       is_loader_v1,
     159             :                int                       virtual_address_space_adjustments,
     160      163680 :                int                       direct_mapping ) {
     161             : 
     162      163680 :   uchar const * data = account ? fd_borrowed_account_get_data( account )     : NULL;
     163 >1844*10^16 :   ulong         dlen = account ? fd_borrowed_account_get_data_len( account ) : 0UL;
     164             : 
     165      163680 :   acc_region_metas[instr_acc_idx].original_data_len = dlen;
     166      163680 :   acc_region_metas[instr_acc_idx].acc               = account->acc;
     167      163680 :   acc_region_metas[instr_acc_idx].touched           = account->touched;
     168             : 
     169             :   /* Legacy behavior: no virtual_address_space_adjustments (also implies no direct mapping)
     170             :      https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L132-L142 */
     171      163680 :   if( !virtual_address_space_adjustments ) {
     172             :     /* Copy the account data into input region buffer */
     173      126552 :     fd_memcpy( *serialized_params, data, dlen );
     174      126552 :     *serialized_params += dlen;
     175             : 
     176      126552 :     if( FD_LIKELY( !is_loader_v1 ) ) {
     177             :       /* Zero out padding bytes and max permitted data increase */
     178       81439 :       ulong align_offset = fd_ulong_align_up( dlen, FD_BPF_ALIGN_OF_U128 ) - dlen;
     179       81439 :       fd_memset( *serialized_params, 0, MAX_PERMITTED_DATA_INCREASE + align_offset );
     180       81439 :       *serialized_params += MAX_PERMITTED_DATA_INCREASE + align_offset;
     181       81439 :     }
     182      126552 :     acc_region_metas[instr_acc_idx].region_idx = UINT_MAX;
     183      126552 :   } else { /* virtual_address_space_adjustments == true */
     184             : 
     185             :     /* Set up account region metadata */
     186       37128 :     acc_region_metas[instr_acc_idx].region_idx = *input_mem_regions_cnt;
     187             : 
     188             :     /* First, push on the region for the metadata that has just been serialized.
     189             :        This function will push the metadata in the serialized_params from
     190             :        serialized_params_start to serialized_params as a region to the input
     191             :        memory regions array.
     192             : 
     193             :        https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L143 */
     194       37128 :     ulong region_sz = (ulong)(*serialized_params) - (ulong)(*serialized_params_start);
     195       37128 :     new_input_mem_region( input_mem_regions, input_mem_regions_cnt, *serialized_params_start, region_sz, region_sz, 1U, ULONG_MAX );
     196             : 
     197             :     /* If direct mapping isn't enabled, then copy the account data in directly
     198             :        https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L145-L151 */
     199       37128 :     if( !direct_mapping ) {
     200       18669 :       fd_memcpy( *serialized_params, data, dlen );
     201       18669 :       *serialized_params += dlen;
     202       18669 :       if( FD_LIKELY( !is_loader_v1 ) ) {
     203       12468 :         fd_memset( *serialized_params, 0, MAX_PERMITTED_DATA_INCREASE );
     204       12468 :         *serialized_params += MAX_PERMITTED_DATA_INCREASE;
     205       12468 :       }
     206       18669 :     }
     207             : 
     208             :     /* Calculate address space reserved for account (data + realloc space)
     209             :        https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L152-L159 */
     210       37128 :     ulong address_space_reserved = !is_loader_v1 ?
     211       24044 :       fd_ulong_sat_add( dlen, MAX_PERMITTED_DATA_INCREASE ) : dlen;
     212             : 
     213             :     /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L160-L170 */
     214       37263 :     if( address_space_reserved > 0 ) {
     215       37263 :       int err = 0;
     216       37263 :       uchar is_writable = !!(fd_borrowed_account_can_data_be_changed( account, &err ) && !err);
     217             : 
     218       37263 :       if( !direct_mapping ) {
     219             :         /* Create region pointing to the copied data in buffer
     220             :            https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L161-L165 */
     221       18652 :         uchar * data_start = *serialized_params - address_space_reserved;
     222       18652 :         new_input_mem_region( input_mem_regions, input_mem_regions_cnt, data_start, dlen, address_space_reserved, is_writable, instr_acc_idx );
     223       18652 :       } else {
     224             :         /* Direct mapping: create region pointing directly to account data */
     225       18611 :         new_input_mem_region( input_mem_regions, input_mem_regions_cnt, data, dlen, address_space_reserved, is_writable, instr_acc_idx );
     226       18611 :       }
     227       37263 :     }
     228             : 
     229       37128 :     *serialized_params_start = *serialized_params;
     230             : 
     231             :     /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L171-L187 */
     232       37128 :     if( FD_LIKELY( !is_loader_v1 ) ) {
     233       24041 :       ulong align_offset = fd_ulong_align_up( dlen, FD_BPF_ALIGN_OF_U128 ) - dlen;
     234       24041 :       if( !direct_mapping ) {
     235             :         /* If direct mapping is not enabled, we do not align the start of each
     236             :            region metadata to FD_BPF_ALIGN_OF_U128, but we do align the start
     237             :            of the actual contents of the metadata region.
     238             : 
     239             :            This follows Agave's logic
     240             :            https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L174-L177 */
     241       12468 :         fd_memset( *serialized_params, 0, align_offset );
     242       12468 :         *serialized_params += align_offset;
     243       12468 :       } else {
     244             :         /* If direct mapping is enabled, we align the start of each region
     245             :            metadata to FD_BPF_ALIGN_OF_U128. */
     246       11573 :         fd_memset( *serialized_params, 0, FD_BPF_ALIGN_OF_U128 );
     247       11573 :         *serialized_params       += FD_BPF_ALIGN_OF_U128;
     248       11573 :         *serialized_params_start += fd_ulong_sat_sub( FD_BPF_ALIGN_OF_U128, align_offset );
     249       11573 :       }
     250       24041 :     }
     251             : 
     252       37128 :     return region_sz + address_space_reserved;
     253       37128 :   }
     254             : 
     255      126552 :   return 0UL;
     256      163680 : }
     257             : 
     258             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L473 */
     259             : static int
     260             : fd_bpf_loader_input_serialize_for_abiv1( fd_exec_instr_ctx_t *     ctx,
     261             :                                          ulong *                   pre_lens,
     262             :                                          fd_vm_input_region_t *    input_mem_regions,
     263             :                                          uint *                    input_mem_regions_cnt,
     264             :                                          fd_vm_acc_region_meta_t * acc_region_metas,
     265             :                                          int                       virtual_address_space_adjustments,
     266             :                                          int                       direct_mapping,
     267             :                                          int                       direct_account_pointers_in_program_input,
     268             :                                          ulong *                   instr_data_offset,
     269       10317 :                                          ulong *                   serialized_bytes_written ) {
     270             :   /* Transaction sanitisation limits the number of instruction accounts to
     271             :      FD_TXN_ACCT_ADDR_MAX. */
     272       10317 :   uchar  acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ] = {0};
     273       10317 :   ushort dup_acc_idx[ FD_TXN_ACCT_ADDR_MAX ]  = {0};
     274             : 
     275             :   /* 16-byte aligned buffer from runtime:
     276             :      https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L61 */
     277       10317 :   uchar * serialized_params            = ctx->runtime->bpf_loader_serialization.frame[ ctx->runtime->instr.stack_sz-1UL ];
     278       10317 :   uchar * serialized_params_start      = serialized_params;
     279       10317 :   uchar * curr_serialized_params_start = serialized_params;
     280       10317 :   ulong   curr_region_vaddr            = 0UL;
     281             : 
     282             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L539 */
     283       10317 :   FD_STORE( ulong, serialized_params, ctx->instr->acct_cnt );
     284       10317 :   serialized_params += sizeof(ulong);
     285             : 
     286             :   /* Iterate over accounts in the instruction to populate input region.
     287             :      https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L540-L570 */
     288      180651 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     289      170334 :     uchar         acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     290      170334 :     fd_pubkey_t * acc     = &ctx->txn_out->accounts.keys[acc_idx];
     291             : 
     292      170334 :     if( FD_UNLIKELY( acc_idx_seen[acc_idx] && dup_acc_idx[acc_idx] != i ) ) {
     293             :       /* Duplicate. Store 8 byte buffer to maintain alignment but store the
     294             :          account index in the first byte.
     295             : 
     296             :          https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L564-L568 */
     297       65095 :       FD_STORE( ulong, serialized_params, 0UL );
     298       65095 :       FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
     299       65095 :       serialized_params += sizeof(ulong);
     300             : 
     301             :       /* Clone the account metadata from the original account
     302             :          https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L372 */
     303       65095 :       acc_region_metas[i] = acc_region_metas[dup_acc_idx[acc_idx]];
     304      105239 :     } else {
     305      105239 :       acc_idx_seen[acc_idx] = 1;
     306      105239 :       dup_acc_idx[acc_idx]  = i;
     307             : 
     308      105239 :       acc_region_metas[i].vm_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     309      105239 :         (ulong)(serialized_params - curr_serialized_params_start);
     310             : 
     311             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L376 */
     312      105239 :       FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
     313      105239 :       serialized_params += sizeof(uchar);
     314             : 
     315             :       /* Borrow the account
     316             :          https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L245-L258 */
     317      105239 :       fd_guarded_borrowed_account_t view_acc = {0};
     318      105239 :       int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, &view_acc );
     319      105239 :       if( FD_UNLIKELY( err ) ) {
     320           0 :         return err;
     321           0 :       }
     322             : 
     323             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L544 */
     324      105239 :       uchar is_signer = (uchar)fd_instr_acc_is_signer_idx( ctx->instr, (uchar)i, NULL );
     325      105239 :       FD_STORE( uchar, serialized_params, is_signer );
     326      105239 :       serialized_params += sizeof(uchar);
     327             : 
     328             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L545 */
     329      105239 :       uchar is_writable = (uchar)fd_instr_acc_is_writable_idx( ctx->instr, (uchar)i );
     330      105239 :       FD_STORE( uchar, serialized_params, is_writable );
     331      105239 :       serialized_params += sizeof(uchar);
     332             : 
     333             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L546-L547 */
     334      105239 :       uchar is_executable = (uchar)view_acc.acc->executable;
     335      105239 :       FD_STORE( uchar, serialized_params, is_executable );
     336      105239 :       serialized_params += sizeof(uchar);
     337             : 
     338             :       /* The original data len field is intentionally NOT populated. */
     339             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L548 */
     340      105239 :       uint padding_0 = 0U;
     341      105239 :       FD_STORE( uint, serialized_params, padding_0 );
     342      105239 :       serialized_params += sizeof(uint);
     343             : 
     344             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L549 */
     345      105239 :       fd_pubkey_t key = *acc;
     346      105239 :       acc_region_metas[i].vm_key_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     347      105239 :         (ulong)(serialized_params - curr_serialized_params_start);
     348      105239 :       FD_STORE( fd_pubkey_t, serialized_params, key );
     349      105239 :       serialized_params += sizeof(fd_pubkey_t);
     350             : 
     351             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L550 */
     352      105239 :       fd_pubkey_t owner = *(fd_pubkey_t *)&view_acc.acc->owner;
     353      105239 :       acc_region_metas[i].vm_owner_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     354      105239 :         (ulong)(serialized_params - curr_serialized_params_start);
     355      105239 :       FD_STORE( fd_pubkey_t, serialized_params, owner );
     356      105239 :       serialized_params += sizeof(fd_pubkey_t);
     357             : 
     358             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L551 */
     359      105239 :       ulong lamports = view_acc.acc->lamports;
     360      105239 :       acc_region_metas[i].vm_lamports_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     361      105239 :         (ulong)(serialized_params - curr_serialized_params_start);
     362      105239 :       FD_STORE( ulong, serialized_params, lamports );
     363      105239 :       serialized_params += sizeof(ulong);
     364             : 
     365      105239 :       ulong acc_data_len = view_acc.acc->data_len;
     366      105239 :       pre_lens[i] = acc_data_len;
     367             : 
     368             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L552 */
     369      105239 :       ulong data_len = acc_data_len;
     370      105239 :       FD_STORE( ulong, serialized_params, data_len );
     371      105239 :       serialized_params += sizeof(ulong);
     372             : 
     373             :       /* vm_data_addr: data is written immediately after the data_len field */
     374      105239 :       acc_region_metas[i].vm_data_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     375      105239 :         (ulong)(serialized_params - curr_serialized_params_start);
     376             : 
     377             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L553 */
     378      105239 :       write_account(
     379      105239 :         &view_acc,
     380      105239 :         (uchar)i,
     381      105239 :         &serialized_params,
     382      105239 :         &curr_serialized_params_start,
     383      105239 :         input_mem_regions,
     384      105239 :         input_mem_regions_cnt,
     385      105239 :         acc_region_metas,
     386      105239 :         0,
     387      105239 :         virtual_address_space_adjustments,
     388      105239 :         direct_mapping );
     389             : 
     390             :       /* write_account may have pushed a new region(s) */
     391      105239 :       curr_region_vaddr = *input_mem_regions_cnt == 0U ? 0UL :
     392      105239 :         input_mem_regions[*input_mem_regions_cnt-1U].vaddr_offset +
     393       23819 :         input_mem_regions[*input_mem_regions_cnt-1U].address_space_reserved;
     394             : 
     395             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L554-L555 */
     396      105239 :       FD_STORE( ulong, serialized_params, ULONG_MAX );
     397      105239 :       serialized_params += sizeof(ulong);
     398      105239 :     }
     399             : 
     400      170334 :   }
     401             : 
     402             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L571 */
     403       10317 :   ulong instr_data_len = ctx->instr->data_sz;
     404       10317 :   FD_STORE( ulong, serialized_params, instr_data_len );
     405       10317 :   serialized_params += sizeof(ulong);
     406             : 
     407             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L572 */
     408       10317 :   *instr_data_offset = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     409       10317 :     (ulong)(serialized_params - curr_serialized_params_start);
     410             : 
     411             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L571 */
     412       10317 :   fd_memcpy( serialized_params, ctx->instr->data, instr_data_len );
     413       10317 :   serialized_params += instr_data_len;
     414             : 
     415             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L400 */
     416       10317 :   FD_STORE( fd_pubkey_t, serialized_params, ctx->txn_out->accounts.keys[ctx->instr->program_id] );
     417       10317 :   serialized_params += sizeof(fd_pubkey_t);
     418             : 
     419             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-rc.0/program-runtime/src/serialization.rs#L522-L529 */
     420       10317 :   if( direct_account_pointers_in_program_input ) {
     421         449 :     ulong cur_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     422         449 :       (ulong)(serialized_params - curr_serialized_params_start);
     423         449 :     ulong padding = FD_ULONG_ALIGN_UP( cur_vaddr, FD_BPF_ALIGN_OF_U128 ) - cur_vaddr;
     424         449 :     fd_memset( serialized_params, 0, padding );
     425         449 :     serialized_params += padding;
     426       28694 :     for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     427       28245 :       FD_STORE( ulong, serialized_params, acc_region_metas[i].vm_addr );
     428       28245 :       serialized_params += sizeof(ulong);
     429       28245 :     }
     430         449 :   }
     431             : 
     432             :   /* Write out the final region. */
     433       10317 :   ulong region_sz = (ulong)(serialized_params - curr_serialized_params_start);
     434       10317 :   new_input_mem_region( input_mem_regions, input_mem_regions_cnt, curr_serialized_params_start,
     435       10317 :                         region_sz, region_sz, 1U, ULONG_MAX );
     436             : 
     437       10317 :   *serialized_bytes_written = (ulong)(serialized_params - serialized_params_start);
     438       10317 :   return FD_EXECUTOR_INSTR_SUCCESS;
     439       10317 : }
     440             : 
     441             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L594-L681 */
     442             : static int
     443             : fd_bpf_loader_input_deserialize_for_abiv1( fd_exec_instr_ctx_t * ctx,
     444             :                                            ulong const *         pre_lens,
     445             :                                            uchar *               buffer,
     446             :                                            ulong                 buffer_sz,
     447             :                                            int                   virtual_address_space_adjustments,
     448        1038 :                                            int                   direct_mapping ) {
     449             :   /* TODO: An optimization would be to skip ahead through non-writable accounts */
     450             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L601 */
     451        1038 :   ulong start = 0UL;
     452             : 
     453        1038 :   uchar acc_idx_seen[256] = {0};
     454             : 
     455        1038 :   start += sizeof(ulong); // number of accounts
     456             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L602-L679 */
     457       38849 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     458       37819 :     uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     459             : 
     460       37819 :     start++; // position
     461             : 
     462             :     /* get the borrowed account
     463             :        https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L612-L613 */
     464       37819 :     fd_guarded_borrowed_account_t view_acc = {0};
     465       37819 :     FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, i, &view_acc );
     466             : 
     467       37819 :     if( FD_UNLIKELY( acc_idx_seen[acc_idx] ) ) {
     468             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L610 */
     469       14987 :       start += 7UL;
     470       22832 :     } else {
     471             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L614-L618 */
     472       22832 :       acc_idx_seen[acc_idx] = 1;
     473       22832 :       start += sizeof(uchar)        // is_signer
     474       22832 :              + sizeof(uchar)        // is_writable
     475       22832 :              + sizeof(uchar)        // executable
     476       22832 :              + sizeof(uint)         // original_data_len
     477       22832 :              + sizeof(fd_pubkey_t); // key
     478             : 
     479             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L619-L621 */
     480             : 
     481       22832 :       fd_pubkey_t * owner = (fd_pubkey_t *)(buffer+start);
     482       22832 :       start += sizeof(fd_pubkey_t); // owner
     483             : 
     484       22832 :       ulong lamports = FD_LOAD( ulong, buffer+start );
     485       22832 :       if( lamports!=fd_borrowed_account_get_lamports( &view_acc ) ) {
     486          38 :         int err = fd_borrowed_account_set_lamports( &view_acc, lamports );
     487          38 :         if( FD_UNLIKELY( err ) ) {
     488           4 :           return err;
     489           4 :         }
     490          38 :       }
     491       22828 :       start += sizeof(ulong); // lamports
     492             : 
     493       22828 :       ulong post_len = FD_LOAD( ulong, buffer+start );
     494       22828 :       start += sizeof(ulong); // data length
     495             : 
     496       22828 :       ulong pre_len = pre_lens[i];
     497       22828 :       ulong alignment_offset = fd_ulong_align_up( pre_len, FD_BPF_ALIGN_OF_U128 ) - pre_len;
     498             : 
     499       22828 :       uchar * post_data = buffer+start;
     500             : 
     501             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L640-L644 */
     502       22828 :       if( FD_UNLIKELY( fd_ulong_sat_sub( post_len, pre_len )>MAX_PERMITTED_DATA_INCREASE ||
     503       22828 :                        post_len>MAX_PERMITTED_DATA_LENGTH ) ) {
     504           4 :         return FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     505           4 :       }
     506             : 
     507       22824 :       int can_data_be_changed_err = 0;
     508       22824 :       if( !virtual_address_space_adjustments ) {
     509             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L645-L655 */
     510             : 
     511             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L646-L648 */
     512       16793 :         if( FD_UNLIKELY( start + post_len > buffer_sz ) ) {
     513           0 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     514           0 :         }
     515             : 
     516             :         /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/program-runtime/src/serialization.rs#L648-L652 */
     517       16793 :         int can_data_be_resized_err = 0;
     518       16793 :         if( fd_borrowed_account_can_data_be_resized( &view_acc, post_len, &can_data_be_resized_err ) ) {
     519         147 :           int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, post_len );
     520         147 :           if( FD_UNLIKELY( set_data_err ) ) {
     521           0 :             return set_data_err;
     522           0 :           }
     523       16646 :         } else {
     524       16646 :           if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &view_acc )!=post_len ||
     525       16646 :                            memcmp( fd_borrowed_account_get_data( &view_acc ), post_data, post_len ) ) ) {
     526           0 :             return can_data_be_resized_err;
     527           0 :           }
     528       16646 :         }
     529             : 
     530       16793 :       } else if( !direct_mapping && fd_borrowed_account_can_data_be_changed( &view_acc, &can_data_be_changed_err ) ) {
     531             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L657-L659 */
     532           4 :         if( FD_UNLIKELY( start + post_len > buffer_sz ) ) {
     533           0 :           return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     534           0 :         }
     535             : 
     536             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L655-L661 */
     537           4 :         int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, post_len );
     538           4 :         if( FD_UNLIKELY( set_data_err ) ) {
     539           0 :           return set_data_err;
     540           0 :         }
     541        6027 :       } else if( fd_borrowed_account_get_data_len( &view_acc ) != post_len ) {
     542             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L661-L663 */
     543           0 :         int set_data_length_err = fd_borrowed_account_set_data_length( &view_acc, post_len );
     544           0 :         if( FD_UNLIKELY( set_data_length_err ) ) {
     545           0 :           return set_data_length_err;
     546           0 :         }
     547           0 :       }
     548             : 
     549             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L664-L672 */
     550       22824 :       if( !( virtual_address_space_adjustments && direct_mapping ) ) {
     551       19747 :         start += fd_ulong_sat_add( MAX_PERMITTED_DATA_INCREASE, fd_ulong_sat_add( pre_len, alignment_offset ) );
     552       19747 :       } else {
     553        3077 :         start += FD_BPF_ALIGN_OF_U128;
     554        3077 :       }
     555             : 
     556             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L673 */
     557       22824 :       start += sizeof(ulong); // rent epoch
     558       22824 :       if( memcmp( fd_borrowed_account_get_owner( &view_acc ), owner, sizeof(fd_pubkey_t) ) ) {
     559           1 :         int err = fd_borrowed_account_set_owner( &view_acc, owner );
     560           1 :         if( FD_UNLIKELY( err ) ) {
     561           0 :           return err;
     562           0 :         }
     563           1 :       }
     564       22824 :     }
     565       37819 :   }
     566             : 
     567        1030 :   return FD_EXECUTOR_INSTR_SUCCESS;
     568        1038 : }
     569             : 
     570             : static int
     571             : fd_bpf_loader_input_serialize_for_abiv0( fd_exec_instr_ctx_t *     ctx,
     572             :                                          ulong *                   pre_lens,
     573             :                                          fd_vm_input_region_t *    input_mem_regions,
     574             :                                          uint *                    input_mem_regions_cnt,
     575             :                                          fd_vm_acc_region_meta_t * acc_region_metas,
     576             :                                          int                       virtual_address_space_adjustments,
     577             :                                          int                       direct_mapping,
     578             :                                          ulong *                   instr_data_offset,
     579        2384 :                                          ulong *                   serialized_bytes_written ) {
     580             :   /* Transaction sanitisation limits the number of instruction accounts to
     581             :      FD_TXN_ACCT_ADDR_MAX. */
     582        2384 :   uchar  acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ] = {0};
     583        2384 :   ushort dup_acc_idx[ FD_TXN_ACCT_ADDR_MAX ]  = {0};
     584             : 
     585             :   /* 16-byte aligned buffer:
     586             :      https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L61 */
     587        2384 :   uchar * serialized_params            = ctx->runtime->bpf_loader_serialization.frame[ ctx->runtime->instr.stack_sz-1UL ];
     588        2384 :   uchar * serialized_params_start      = serialized_params;
     589        2384 :   uchar * curr_serialized_params_start = serialized_params;
     590        2384 :   ulong   curr_region_vaddr            = 0UL;
     591             : 
     592        2384 :   FD_STORE( ulong, serialized_params, ctx->instr->acct_cnt );
     593        2384 :   serialized_params += sizeof(ulong);
     594             : 
     595       99124 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     596       96740 :     uchar               acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     597       96740 :     fd_pubkey_t const * acc     = &ctx->txn_out->accounts.keys[acc_idx];
     598             : 
     599       96740 :     if( FD_UNLIKELY( acc_idx_seen[acc_idx] && dup_acc_idx[acc_idx] != i ) ) {
     600             :       // Duplicate
     601       38308 :       FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
     602       38308 :       serialized_params += sizeof(uchar);
     603             : 
     604             :       /* Clone the account metadata from the original account
     605             :          https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L382 */
     606       38308 :       acc_region_metas[i] = acc_region_metas[dup_acc_idx[acc_idx]];
     607       58432 :     } else {
     608       58432 :       acc_idx_seen[acc_idx] = 1;
     609       58432 :       dup_acc_idx[acc_idx]  = i;
     610             : 
     611       58432 :       acc_region_metas[i].vm_addr = 0UL; /* abiv0 has no account pointer table */
     612             : 
     613       58432 :       FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
     614       58432 :       serialized_params += sizeof(uchar);
     615             : 
     616             :       /* Borrow the account
     617             :          https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L253 */
     618       58432 :       fd_guarded_borrowed_account_t view_acc = {0};
     619       58432 :       int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, &view_acc );
     620       58432 :       if( FD_UNLIKELY( err ) ) {
     621           0 :         return err;
     622           0 :       }
     623             : 
     624       58432 :       pre_lens[ i ] = view_acc.acc->data_len;
     625             : 
     626       58432 :       uchar is_signer = (uchar)fd_instr_acc_is_signer_idx( ctx->instr, (uchar)i, NULL );
     627       58432 :       FD_STORE( uchar, serialized_params, is_signer );
     628       58432 :       serialized_params += sizeof(uchar);
     629             : 
     630       58432 :       uchar is_writable = (uchar)fd_instr_acc_is_writable_idx( ctx->instr, (uchar)i );
     631       58432 :       FD_STORE( uchar, serialized_params, is_writable );
     632       58432 :       serialized_params += sizeof(uchar);
     633             : 
     634       58432 :       fd_pubkey_t key = *acc;
     635       58432 :       acc_region_metas[i].vm_key_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     636       58432 :         (ulong)(serialized_params - curr_serialized_params_start);
     637       58432 :       FD_STORE( fd_pubkey_t, serialized_params, key );
     638       58432 :       serialized_params += sizeof(fd_pubkey_t);
     639             : 
     640       58432 :       ulong lamports = view_acc.acc->lamports;
     641       58432 :       acc_region_metas[i].vm_lamports_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     642       58432 :         (ulong)(serialized_params - curr_serialized_params_start);
     643       58432 :       FD_STORE( ulong, serialized_params, lamports );
     644       58432 :       serialized_params += sizeof(ulong);
     645             : 
     646       58432 :       ulong acc_data_len = view_acc.acc->data_len;
     647       58432 :       FD_STORE( ulong, serialized_params, acc_data_len );
     648       58432 :       serialized_params += sizeof(ulong);
     649             : 
     650             :       /* vm_data_addr: data is written immediately after the data_len field */
     651       58432 :       acc_region_metas[i].vm_data_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     652       58432 :         (ulong)(serialized_params - curr_serialized_params_start);
     653             : 
     654       58432 :       write_account( &view_acc, (uchar)i,
     655       58432 :         &serialized_params, &curr_serialized_params_start,
     656       58432 :         input_mem_regions, input_mem_regions_cnt, acc_region_metas, 1,
     657       58432 :         virtual_address_space_adjustments, direct_mapping );
     658             : 
     659             :       /* write_account may have pushed a new region(s) */
     660       58432 :       curr_region_vaddr = *input_mem_regions_cnt == 0U ? 0UL :
     661       58432 :         input_mem_regions[*input_mem_regions_cnt-1U].vaddr_offset +
     662       13162 :         input_mem_regions[*input_mem_regions_cnt-1U].address_space_reserved;
     663             : 
     664       58432 :       fd_pubkey_t owner = *(fd_pubkey_t *)&view_acc.acc->owner;
     665       58432 :       acc_region_metas[i].vm_owner_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     666       58432 :         (ulong)(serialized_params - curr_serialized_params_start);
     667       58432 :       FD_STORE( fd_pubkey_t, serialized_params, owner );
     668       58432 :       serialized_params += sizeof(fd_pubkey_t);
     669             : 
     670       58432 :       uchar is_executable = (uchar)view_acc.acc->executable;
     671       58432 :       FD_STORE( uchar, serialized_params, is_executable );
     672       58432 :       serialized_params += sizeof(uchar);
     673             : 
     674       58432 :       FD_STORE( ulong, serialized_params, ULONG_MAX );
     675       58432 :       serialized_params += sizeof(ulong);
     676       58432 :     }
     677       96740 :   }
     678             : 
     679        2384 :   ulong instr_data_len = ctx->instr->data_sz;
     680        2384 :   FD_STORE( ulong, serialized_params, instr_data_len );
     681        2384 :   serialized_params += sizeof(ulong);
     682             : 
     683             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L399 */
     684        2384 :   *instr_data_offset = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     685        2384 :     (ulong)(serialized_params - curr_serialized_params_start);
     686             : 
     687        2384 :   fd_memcpy( serialized_params, ctx->instr->data, instr_data_len );
     688        2384 :   serialized_params += instr_data_len;
     689             : 
     690        2384 :   FD_STORE( fd_pubkey_t, serialized_params, ctx->txn_out->accounts.keys[ctx->instr->program_id] );
     691        2384 :   serialized_params += sizeof(fd_pubkey_t);
     692             : 
     693        2384 :   *serialized_bytes_written = (ulong)(serialized_params - serialized_params_start);
     694             : 
     695        2384 :   ulong region_sz = (ulong)(serialized_params - curr_serialized_params_start);
     696        2384 :   new_input_mem_region( input_mem_regions, input_mem_regions_cnt, curr_serialized_params_start,
     697        2384 :     region_sz, region_sz, 1U, ULONG_MAX );
     698             : 
     699        2384 :   return FD_EXECUTOR_INSTR_SUCCESS;
     700        2384 : }
     701             : 
     702             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L411 */
     703             : static int
     704             : fd_bpf_loader_input_deserialize_for_abiv0( fd_exec_instr_ctx_t * ctx,
     705             :                                            ulong const *         pre_lens,
     706             :                                            uchar *               input,
     707             :                                            ulong                 input_sz,
     708             :                                            int                   virtual_address_space_adjustments,
     709         550 :                                            int                   direct_mapping ) {
     710         550 :   uchar *       input_cursor      = input;
     711         550 :   uchar         acc_idx_seen[256] = {0};
     712             : 
     713         550 :   input_cursor += sizeof(ulong);
     714             : 
     715       14198 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     716       13651 :     uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     717             : 
     718       13651 :     input_cursor++; /* is_dup */
     719       13651 :     if( FD_UNLIKELY( acc_idx_seen[acc_idx] ) ) {
     720             :       /* no-op */
     721        8331 :     } else {
     722        8331 :       acc_idx_seen[acc_idx] = 1;
     723        8331 :       input_cursor += sizeof(uchar) +      /* is_signer */
     724        8331 :                       sizeof(uchar) +      /* is_writable */
     725        8331 :                       sizeof(fd_pubkey_t); /* key */
     726             : 
     727             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L427-L428 */
     728        8331 :       fd_guarded_borrowed_account_t view_acc = {0};
     729        8331 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, i, &view_acc );
     730             : 
     731        8331 :       ulong lamports = FD_LOAD( ulong, input_cursor );
     732        8331 :       if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &view_acc )!=lamports ) ) {
     733           0 :         int err = fd_borrowed_account_set_lamports( &view_acc, lamports );
     734           0 :         if( FD_UNLIKELY( err ) ) {
     735           0 :           return err;
     736           0 :         }
     737           0 :       }
     738             : 
     739        8331 :       input_cursor += sizeof(ulong); /* lamports */
     740        8331 :       input_cursor += sizeof(ulong); /* data length */
     741             : 
     742        8331 :       ulong   pre_len   = pre_lens[i];
     743        8331 :       uchar * post_data = input_cursor;
     744             : 
     745             :       /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/program-runtime/src/serialization.rs#L446-L450 */
     746        8331 :       int can_data_be_changed_err = 0;
     747        8331 :       if( !virtual_address_space_adjustments ) {
     748        6343 :         int can_data_be_resized_err = 0;
     749        6343 :         if( fd_borrowed_account_can_data_be_resized( &view_acc, pre_len, &can_data_be_resized_err ) ) {
     750           0 :           int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, pre_len );
     751           0 :           if( FD_UNLIKELY( set_data_err ) ) {
     752           0 :             return set_data_err;
     753           0 :           }
     754        6343 :         } else if( fd_borrowed_account_get_data_len( &view_acc ) != pre_len ||
     755        6343 :                    memcmp( post_data, fd_borrowed_account_get_data( &view_acc ), pre_len ) ) {
     756           3 :           return can_data_be_resized_err;
     757           3 :         }
     758        6343 :       } else if( !direct_mapping && fd_borrowed_account_can_data_be_changed( &view_acc, &can_data_be_changed_err ) ) {
     759             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L453-L459 */
     760           0 :         int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, pre_len );
     761           0 :         if( FD_UNLIKELY( set_data_err ) ) {
     762           0 :           return set_data_err;
     763           0 :         }
     764        1988 :       } else if( fd_borrowed_account_get_data_len( &view_acc ) != pre_len ) {
     765             :         /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L459-L461 */
     766           0 :         int set_data_length_err = fd_borrowed_account_set_data_length( &view_acc, pre_len );
     767           0 :         if( FD_UNLIKELY( set_data_length_err ) ) {
     768           0 :           return set_data_length_err;
     769           0 :         }
     770           0 :       }
     771             : 
     772             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L462-L464 */
     773        8328 :       if( !( virtual_address_space_adjustments && direct_mapping ) ) {
     774        7382 :         input_cursor += pre_len;
     775        7382 :       }
     776        8328 :       input_cursor += sizeof(fd_pubkey_t) + /* owner */
     777        8328 :                       sizeof(uchar) +       /* executable */
     778        8328 :                       sizeof(ulong);        /* rent_epoch*/
     779        8328 :     }
     780       13651 :   }
     781             : 
     782         547 :   if( FD_UNLIKELY( input_cursor>input+input_sz ) ) {
     783           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     784           0 :   }
     785             : 
     786         547 :   return 0;
     787         547 : }
     788             : 
     789             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L222 */
     790             : int
     791             : fd_bpf_loader_input_serialize_parameters( fd_exec_instr_ctx_t *     instr_ctx,
     792             :                                           ulong *                   pre_lens,
     793             :                                           fd_vm_input_region_t *    input_mem_regions,
     794             :                                           uint *                    input_mem_regions_cnt,
     795             :                                           fd_vm_acc_region_meta_t * acc_region_metas,
     796             :                                           int                       virtual_address_space_adjustments,
     797             :                                           int                       direct_mapping,
     798             :                                           int                       direct_account_pointers_in_program_input,
     799             :                                           uchar                     is_deprecated,
     800             :                                           ulong *                   instr_data_offset,
     801       12702 :                                           ulong *                   serialized_bytes_written ) {
     802             : 
     803             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L236-L239 */
     804       12702 :   ulong num_ix_accounts = instr_ctx->instr->acct_cnt;
     805       12702 :   if( FD_UNLIKELY( num_ix_accounts>FD_TXN_INSTR_ACCT_MAX ) ) {
     806           0 :     return FD_EXECUTOR_INSTR_ERR_MAX_ACCS_EXCEEDED;
     807           0 :   }
     808             : 
     809             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L265-L285 */
     810       12702 :   if( FD_UNLIKELY( is_deprecated ) ) {
     811        2384 :     return fd_bpf_loader_input_serialize_for_abiv0( instr_ctx, pre_lens,
     812        2384 :                                                     input_mem_regions, input_mem_regions_cnt,
     813        2384 :                                                     acc_region_metas, virtual_address_space_adjustments,
     814        2384 :                                                     direct_mapping, instr_data_offset, serialized_bytes_written );
     815       10318 :   } else {
     816       10318 :     return fd_bpf_loader_input_serialize_for_abiv1( instr_ctx, pre_lens,
     817       10318 :                                                     input_mem_regions, input_mem_regions_cnt,
     818       10318 :                                                     acc_region_metas, virtual_address_space_adjustments,
     819       10318 :                                                     direct_mapping, direct_account_pointers_in_program_input,
     820       10318 :                                                     instr_data_offset, serialized_bytes_written );
     821       10318 :   }
     822       12702 : }
     823             : 
     824             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L288-L317 */
     825             : int
     826             : fd_bpf_loader_input_deserialize_parameters( fd_exec_instr_ctx_t * ctx,
     827             :                                             ulong const *         pre_lens,
     828             :                                             uchar *               input,
     829             :                                             ulong                 input_sz,
     830             :                                             int                   virtual_address_space_adjustments,
     831             :                                             int                   direct_mapping,
     832        1588 :                                             uchar                 is_deprecated ) {
     833        1588 :   if( FD_UNLIKELY( is_deprecated ) ) {
     834         550 :     return fd_bpf_loader_input_deserialize_for_abiv0(
     835         550 :       ctx, pre_lens, input, input_sz, virtual_address_space_adjustments, direct_mapping );
     836        1038 :   } else {
     837        1038 :     return fd_bpf_loader_input_deserialize_for_abiv1(
     838        1038 :       ctx, pre_lens, input, input_sz, virtual_address_space_adjustments, direct_mapping );
     839        1038 :   }
     840        1588 : }

Generated by: LCOV version 1.14