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: 383 429 89.3 %
Date: 2026-10-22 18:10: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       87186 :                       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       87186 :   ulong vaddr_offset = *input_mem_regions_cnt==0UL ? 0UL : input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
     131       74405 :                                                            input_mem_regions[ *input_mem_regions_cnt-1U ].address_space_reserved;
     132       87186 :   input_mem_regions[ *input_mem_regions_cnt ].is_writable            = is_writable;
     133       87186 :   input_mem_regions[ *input_mem_regions_cnt ].haddr                  = (ulong)buffer;
     134       87186 :   input_mem_regions[ *input_mem_regions_cnt ].region_sz              = (uint)region_sz;
     135       87186 :   input_mem_regions[ *input_mem_regions_cnt ].address_space_reserved = address_space_reserved;
     136       87186 :   input_mem_regions[ *input_mem_regions_cnt ].vaddr_offset           = vaddr_offset;
     137       87186 :   input_mem_regions[ *input_mem_regions_cnt ].acc_region_meta_idx    = acc_region_meta_idx;
     138       87186 :   (*input_mem_regions_cnt)++;
     139       87186 : }
     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. However, when direct mapping is
     146             :    enabled, the account data and resizing buffers are represented by two
     147             :    different memory regions. 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      163966 :                int                       direct_mapping ) {
     161             : 
     162      163966 :   uchar const * data = account ? fd_borrowed_account_get_data( account )     : NULL;
     163      163966 :   ulong         dlen = account ? fd_borrowed_account_get_data_len( account ) : 0UL;
     164             : 
     165      163966 :   acc_region_metas[instr_acc_idx].original_data_len = dlen;
     166      163966 :   acc_region_metas[instr_acc_idx].acc               = account->acc;
     167      163966 :   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      163966 :   if( !virtual_address_space_adjustments ) {
     172             :     /* Copy the account data into input region buffer */
     173      126820 :     fd_memcpy( *serialized_params, data, dlen );
     174      126820 :     *serialized_params += dlen;
     175             : 
     176      126820 :     if( FD_LIKELY( !is_loader_v1 ) ) {
     177             :       /* Zero out padding bytes and max permitted data increase */
     178       81523 :       ulong align_offset = fd_ulong_align_up( dlen, FD_BPF_ALIGN_OF_U128 ) - dlen;
     179       81523 :       fd_memset( *serialized_params, 0, MAX_PERMITTED_DATA_INCREASE + align_offset );
     180       81523 :       *serialized_params += MAX_PERMITTED_DATA_INCREASE + align_offset;
     181       81523 :     }
     182      126820 :     acc_region_metas[instr_acc_idx].region_idx = UINT_MAX;
     183      126820 :   } else { /* virtual_address_space_adjustments == true */
     184             : 
     185             :     /* Set up account region metadata */
     186       37146 :     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       37146 :     ulong region_sz = (ulong)(*serialized_params) - (ulong)(*serialized_params_start);
     195       37146 :     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       37146 :     if( !direct_mapping ) {
     200       18631 :       fd_memcpy( *serialized_params, data, dlen );
     201       18631 :       *serialized_params += dlen;
     202       18631 :       if( FD_LIKELY( !is_loader_v1 ) ) {
     203       12426 :         fd_memset( *serialized_params, 0, MAX_PERMITTED_DATA_INCREASE );
     204       12426 :         *serialized_params += MAX_PERMITTED_DATA_INCREASE;
     205       12426 :       }
     206       18631 :     }
     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       37146 :     ulong address_space_reserved = !is_loader_v1 ?
     211       24009 :       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       37201 :     if( address_space_reserved > 0 ) {
     215       37201 :       int err = 0;
     216       37201 :       uchar is_writable = !!(fd_borrowed_account_can_data_be_changed( account, &err ) && !err);
     217             : 
     218       37201 :       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       18608 :         uchar * data_start = *serialized_params - address_space_reserved;
     222       18608 :         new_input_mem_region( input_mem_regions, input_mem_regions_cnt, data_start, dlen, address_space_reserved, is_writable, instr_acc_idx );
     223       18608 :       } else {
     224             :         /* Direct mapping: create region pointing directly to account data */
     225       18593 :         new_input_mem_region( input_mem_regions, input_mem_regions_cnt, data, dlen, address_space_reserved, is_writable, instr_acc_idx );
     226       18593 :       }
     227       37201 :     }
     228             : 
     229       37146 :     *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       37146 :     if( FD_LIKELY( !is_loader_v1 ) ) {
     233       24009 :       ulong align_offset = fd_ulong_align_up( dlen, FD_BPF_ALIGN_OF_U128 ) - dlen;
     234       24009 :       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       12426 :         fd_memset( *serialized_params, 0, align_offset );
     242       12426 :         *serialized_params += align_offset;
     243       12426 :       } else {
     244             :         /* If direct mapping is enabled, we align the start of each region
     245             :            metadata to FD_BPF_ALIGN_OF_U128. */
     246       11583 :         fd_memset( *serialized_params, 0, FD_BPF_ALIGN_OF_U128 );
     247       11583 :         *serialized_params       += FD_BPF_ALIGN_OF_U128;
     248       11583 :         *serialized_params_start += fd_ulong_sat_sub( FD_BPF_ALIGN_OF_U128, align_offset );
     249       11583 :       }
     250       24009 :     }
     251             : 
     252       37146 :     return region_sz + address_space_reserved;
     253       37146 :   }
     254             : 
     255      126820 :   return 0UL;
     256      163966 : }
     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       10398 :                                          ulong *                   serialized_bytes_written ) {
     270             :   /* Transaction sanitisation limits the number of instruction accounts to
     271             :      FD_TXN_ACCT_ADDR_MAX. */
     272       10398 :   uchar  acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ] = {0};
     273       10398 :   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       10398 :   uchar * serialized_params            = ctx->runtime->bpf_loader_serialization.serialization_mem[ ctx->runtime->instr.stack_sz-1UL ];
     278       10398 :   uchar * serialized_params_start      = serialized_params;
     279       10398 :   uchar * curr_serialized_params_start = serialized_params;
     280       10398 :   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       10398 :   FD_STORE( ulong, serialized_params, ctx->instr->acct_cnt );
     284       10398 :   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      180927 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     289      170529 :     uchar         acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     290      170529 :     fd_pubkey_t * acc     = &ctx->txn_out->accounts.keys[acc_idx];
     291             : 
     292      170529 :     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       65142 :       FD_STORE( ulong, serialized_params, 0UL );
     298       65142 :       FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
     299       65142 :       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       65142 :       acc_region_metas[i] = acc_region_metas[dup_acc_idx[acc_idx]];
     304      105387 :     } else {
     305      105387 :       acc_idx_seen[acc_idx] = 1;
     306      105387 :       dup_acc_idx[acc_idx]  = i;
     307             : 
     308      105387 :       acc_region_metas[i].vm_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     309      105387 :         (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      105387 :       FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
     313      105387 :       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      105387 :       fd_guarded_borrowed_account_t view_acc = {0};
     318      105387 :       int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, &view_acc );
     319      105387 :       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      105387 :       uchar is_signer = (uchar)fd_instr_acc_is_signer_idx( ctx->instr, (uchar)i, NULL );
     325      105387 :       FD_STORE( uchar, serialized_params, is_signer );
     326      105387 :       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      105387 :       uchar is_writable = (uchar)fd_instr_acc_is_writable_idx( ctx->instr, (uchar)i );
     330      105387 :       FD_STORE( uchar, serialized_params, is_writable );
     331      105387 :       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      105387 :       uchar is_executable = (uchar)view_acc.acc->executable;
     335      105387 :       FD_STORE( uchar, serialized_params, is_executable );
     336      105387 :       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      105387 :       uint padding_0 = 0U;
     341      105387 :       FD_STORE( uint, serialized_params, padding_0 );
     342      105387 :       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      105387 :       fd_pubkey_t key = *acc;
     346      105387 :       acc_region_metas[i].vm_key_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     347      105387 :         (ulong)(serialized_params - curr_serialized_params_start);
     348      105387 :       FD_STORE( fd_pubkey_t, serialized_params, key );
     349      105387 :       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      105387 :       fd_pubkey_t owner = *(fd_pubkey_t *)&view_acc.acc->owner;
     353      105387 :       acc_region_metas[i].vm_owner_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     354      105387 :         (ulong)(serialized_params - curr_serialized_params_start);
     355      105387 :       FD_STORE( fd_pubkey_t, serialized_params, owner );
     356      105387 :       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      105387 :       ulong lamports = view_acc.acc->lamports;
     360      105387 :       acc_region_metas[i].vm_lamports_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     361      105387 :         (ulong)(serialized_params - curr_serialized_params_start);
     362      105387 :       FD_STORE( ulong, serialized_params, lamports );
     363      105387 :       serialized_params += sizeof(ulong);
     364             : 
     365      105387 :       ulong acc_data_len = view_acc.acc->data_len;
     366      105387 :       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      105387 :       ulong data_len = acc_data_len;
     370      105387 :       FD_STORE( ulong, serialized_params, data_len );
     371      105387 :       serialized_params += sizeof(ulong);
     372             : 
     373             :       /* vm_data_addr: data is written immediately after the data_len field */
     374      105387 :       acc_region_metas[i].vm_data_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     375      105387 :         (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      105387 :       write_account(
     379      105387 :         &view_acc,
     380      105387 :         (uchar)i,
     381      105387 :         &serialized_params,
     382      105387 :         &curr_serialized_params_start,
     383      105387 :         input_mem_regions,
     384      105387 :         input_mem_regions_cnt,
     385      105387 :         acc_region_metas,
     386      105387 :         0,
     387      105387 :         virtual_address_space_adjustments,
     388      105387 :         direct_mapping );
     389             : 
     390             :       /* write_account may have pushed a new region(s) */
     391      105387 :       curr_region_vaddr = *input_mem_regions_cnt == 0U ? 0UL :
     392      105387 :         input_mem_regions[*input_mem_regions_cnt-1U].vaddr_offset +
     393       23971 :         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      105387 :       FD_STORE( ulong, serialized_params, ULONG_MAX );
     397      105387 :       serialized_params += sizeof(ulong);
     398      105387 :     }
     399             : 
     400      170529 :   }
     401             : 
     402             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L571 */
     403       10398 :   ulong instr_data_len = ctx->instr->data_sz;
     404       10398 :   FD_STORE( ulong, serialized_params, instr_data_len );
     405       10398 :   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       10398 :   *instr_data_offset = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     409       10398 :     (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       10398 :   fd_memcpy( serialized_params, ctx->instr->data, instr_data_len );
     413       10398 :   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       10398 :   FD_STORE( fd_pubkey_t, serialized_params, ctx->txn_out->accounts.keys[ctx->instr->program_id] );
     417       10398 :   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       10398 :   if( direct_account_pointers_in_program_input ) {
     421         445 :     ulong cur_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     422         445 :       (ulong)(serialized_params - curr_serialized_params_start);
     423         445 :     ulong padding = FD_ULONG_ALIGN_UP( cur_vaddr, FD_BPF_ALIGN_OF_U128 ) - cur_vaddr;
     424         445 :     fd_memset( serialized_params, 0, padding );
     425         445 :     serialized_params += padding;
     426       28845 :     for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     427       28400 :       FD_STORE( ulong, serialized_params, acc_region_metas[i].vm_addr );
     428       28400 :       serialized_params += sizeof(ulong);
     429       28400 :     }
     430         445 :   }
     431             : 
     432             :   /* Write out the final region. */
     433       10398 :   ulong region_sz = (ulong)(serialized_params - curr_serialized_params_start);
     434       10398 :   new_input_mem_region( input_mem_regions, input_mem_regions_cnt, curr_serialized_params_start,
     435       10398 :                         region_sz, region_sz, 1U, ULONG_MAX );
     436             : 
     437       10398 :   *serialized_bytes_written = (ulong)(serialized_params - serialized_params_start);
     438       10398 :   return FD_EXECUTOR_INSTR_SUCCESS;
     439       10398 : }
     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        1034 :                                            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        1034 :   ulong start = 0UL;
     452             : 
     453        1034 :   uchar acc_idx_seen[256] = {0};
     454             : 
     455        1034 :   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       38835 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     458       37809 :     uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     459             : 
     460       37809 :     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       37809 :     fd_guarded_borrowed_account_t view_acc = {0};
     465       37809 :     FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, i, &view_acc );
     466             : 
     467       37809 :     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       22822 :     } else {
     471             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L614-L618 */
     472       22822 :       acc_idx_seen[acc_idx] = 1;
     473       22822 :       start += sizeof(uchar)        // is_signer
     474       22822 :              + sizeof(uchar)        // is_writable
     475       22822 :              + sizeof(uchar)        // executable
     476       22822 :              + sizeof(uint)         // original_data_len
     477       22822 :              + 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       22822 :       fd_pubkey_t * owner = (fd_pubkey_t *)(buffer+start);
     482       22822 :       start += sizeof(fd_pubkey_t); // owner
     483             : 
     484       22822 :       ulong lamports = FD_LOAD( ulong, buffer+start );
     485       22822 :       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       22818 :       start += sizeof(ulong); // lamports
     492             : 
     493       22818 :       ulong post_len = FD_LOAD( ulong, buffer+start );
     494       22818 :       start += sizeof(ulong); // data length
     495             : 
     496       22818 :       ulong pre_len = pre_lens[i];
     497       22818 :       ulong alignment_offset = fd_ulong_align_up( pre_len, FD_BPF_ALIGN_OF_U128 ) - pre_len;
     498             : 
     499       22818 :       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       22818 :       if( FD_UNLIKELY( fd_ulong_sat_sub( post_len, pre_len )>MAX_PERMITTED_DATA_INCREASE ||
     503       22818 :                        post_len>MAX_PERMITTED_DATA_LENGTH ) ) {
     504           4 :         return FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     505           4 :       }
     506             : 
     507       22814 :       int can_data_be_changed_err = 0;
     508       22814 :       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           0 :         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           0 :         int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, post_len );
     538           0 :         if( FD_UNLIKELY( set_data_err ) ) {
     539           0 :           return set_data_err;
     540           0 :         }
     541        6021 :       } 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       22814 :       if( !( virtual_address_space_adjustments && direct_mapping ) ) {
     551       19729 :         start += fd_ulong_sat_add( MAX_PERMITTED_DATA_INCREASE, fd_ulong_sat_add( pre_len, alignment_offset ) );
     552       19729 :       } else {
     553        3085 :         start += FD_BPF_ALIGN_OF_U128;
     554        3085 :       }
     555             : 
     556             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L673 */
     557       22814 :       start += sizeof(ulong); // rent epoch
     558       22814 :       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       22814 :     }
     565       37809 :   }
     566             : 
     567        1026 :   return FD_EXECUTOR_INSTR_SUCCESS;
     568        1034 : }
     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        2382 :                                          ulong *                   serialized_bytes_written ) {
     580             :   /* Transaction sanitisation limits the number of instruction accounts to
     581             :      FD_TXN_ACCT_ADDR_MAX. */
     582        2382 :   uchar  acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ] = {0};
     583        2382 :   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        2382 :   uchar * serialized_params            = ctx->runtime->bpf_loader_serialization.serialization_mem[ ctx->runtime->instr.stack_sz-1UL ];
     588        2382 :   uchar * serialized_params_start      = serialized_params;
     589        2382 :   uchar * curr_serialized_params_start = serialized_params;
     590        2382 :   ulong   curr_region_vaddr            = 0UL;
     591             : 
     592        2382 :   FD_STORE( ulong, serialized_params, ctx->instr->acct_cnt );
     593        2382 :   serialized_params += sizeof(ulong);
     594             : 
     595       99259 :   for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
     596       96877 :     uchar               acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
     597       96877 :     fd_pubkey_t const * acc     = &ctx->txn_out->accounts.keys[acc_idx];
     598             : 
     599       96877 :     if( FD_UNLIKELY( acc_idx_seen[acc_idx] && dup_acc_idx[acc_idx] != i ) ) {
     600             :       // Duplicate
     601       38297 :       FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
     602       38297 :       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       38297 :       acc_region_metas[i] = acc_region_metas[dup_acc_idx[acc_idx]];
     607       58580 :     } else {
     608       58580 :       acc_idx_seen[acc_idx] = 1;
     609       58580 :       dup_acc_idx[acc_idx]  = i;
     610             : 
     611       58580 :       acc_region_metas[i].vm_addr = 0UL; /* abiv0 has no account pointer table */
     612             : 
     613       58580 :       FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
     614       58580 :       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       58580 :       fd_guarded_borrowed_account_t view_acc = {0};
     619       58580 :       int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, &view_acc );
     620       58580 :       if( FD_UNLIKELY( err ) ) {
     621           0 :         return err;
     622           0 :       }
     623             : 
     624       58580 :       pre_lens[ i ] = view_acc.acc->data_len;
     625             : 
     626       58580 :       uchar is_signer = (uchar)fd_instr_acc_is_signer_idx( ctx->instr, (uchar)i, NULL );
     627       58580 :       FD_STORE( uchar, serialized_params, is_signer );
     628       58580 :       serialized_params += sizeof(uchar);
     629             : 
     630       58580 :       uchar is_writable = (uchar)fd_instr_acc_is_writable_idx( ctx->instr, (uchar)i );
     631       58580 :       FD_STORE( uchar, serialized_params, is_writable );
     632       58580 :       serialized_params += sizeof(uchar);
     633             : 
     634       58580 :       fd_pubkey_t key = *acc;
     635       58580 :       acc_region_metas[i].vm_key_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     636       58580 :         (ulong)(serialized_params - curr_serialized_params_start);
     637       58580 :       FD_STORE( fd_pubkey_t, serialized_params, key );
     638       58580 :       serialized_params += sizeof(fd_pubkey_t);
     639             : 
     640       58580 :       ulong lamports = view_acc.acc->lamports;
     641       58580 :       acc_region_metas[i].vm_lamports_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     642       58580 :         (ulong)(serialized_params - curr_serialized_params_start);
     643       58580 :       FD_STORE( ulong, serialized_params, lamports );
     644       58580 :       serialized_params += sizeof(ulong);
     645             : 
     646       58580 :       ulong acc_data_len = view_acc.acc->data_len;
     647       58580 :       FD_STORE( ulong, serialized_params, acc_data_len );
     648       58580 :       serialized_params += sizeof(ulong);
     649             : 
     650             :       /* vm_data_addr: data is written immediately after the data_len field */
     651       58580 :       acc_region_metas[i].vm_data_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     652       58580 :         (ulong)(serialized_params - curr_serialized_params_start);
     653             : 
     654       58580 :       write_account( &view_acc, (uchar)i,
     655       58580 :         &serialized_params, &curr_serialized_params_start,
     656       58580 :         input_mem_regions, input_mem_regions_cnt, acc_region_metas, 1,
     657       58580 :         virtual_address_space_adjustments, direct_mapping );
     658             : 
     659             :       /* write_account may have pushed a new region(s) */
     660       58580 :       curr_region_vaddr = *input_mem_regions_cnt == 0U ? 0UL :
     661       58580 :         input_mem_regions[*input_mem_regions_cnt-1U].vaddr_offset +
     662       13213 :         input_mem_regions[*input_mem_regions_cnt-1U].address_space_reserved;
     663             : 
     664       58580 :       fd_pubkey_t owner = *(fd_pubkey_t *)&view_acc.acc->owner;
     665       58580 :       acc_region_metas[i].vm_owner_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     666       58580 :         (ulong)(serialized_params - curr_serialized_params_start);
     667       58580 :       FD_STORE( fd_pubkey_t, serialized_params, owner );
     668       58580 :       serialized_params += sizeof(fd_pubkey_t);
     669             : 
     670       58580 :       uchar is_executable = (uchar)view_acc.acc->executable;
     671       58580 :       FD_STORE( uchar, serialized_params, is_executable );
     672       58580 :       serialized_params += sizeof(uchar);
     673             : 
     674       58580 :       FD_STORE( ulong, serialized_params, ULONG_MAX );
     675       58580 :       serialized_params += sizeof(ulong);
     676       58580 :     }
     677       96877 :   }
     678             : 
     679        2382 :   ulong instr_data_len = ctx->instr->data_sz;
     680        2382 :   FD_STORE( ulong, serialized_params, instr_data_len );
     681        2382 :   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        2382 :   *instr_data_offset = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
     685        2382 :     (ulong)(serialized_params - curr_serialized_params_start);
     686             : 
     687        2382 :   fd_memcpy( serialized_params, ctx->instr->data, instr_data_len );
     688        2382 :   serialized_params += instr_data_len;
     689             : 
     690        2382 :   FD_STORE( fd_pubkey_t, serialized_params, ctx->txn_out->accounts.keys[ctx->instr->program_id] );
     691        2382 :   serialized_params += sizeof(fd_pubkey_t);
     692             : 
     693        2382 :   *serialized_bytes_written = (ulong)(serialized_params - serialized_params_start);
     694             : 
     695        2382 :   ulong region_sz = (ulong)(serialized_params - curr_serialized_params_start);
     696        2382 :   new_input_mem_region( input_mem_regions, input_mem_regions_cnt, curr_serialized_params_start,
     697        2382 :     region_sz, region_sz, 1U, ULONG_MAX );
     698             : 
     699        2382 :   return FD_EXECUTOR_INSTR_SUCCESS;
     700        2382 : }
     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       12779 :                                           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       12779 :   ulong num_ix_accounts = instr_ctx->instr->acct_cnt;
     805       12779 :   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       12779 :   if( FD_UNLIKELY( is_deprecated ) ) {
     811        2382 :     return fd_bpf_loader_input_serialize_for_abiv0( instr_ctx, pre_lens,
     812        2382 :                                                     input_mem_regions, input_mem_regions_cnt,
     813        2382 :                                                     acc_region_metas, virtual_address_space_adjustments,
     814        2382 :                                                     direct_mapping, instr_data_offset, serialized_bytes_written );
     815       10397 :   } else {
     816       10397 :     return fd_bpf_loader_input_serialize_for_abiv1( instr_ctx, pre_lens,
     817       10397 :                                                     input_mem_regions, input_mem_regions_cnt,
     818       10397 :                                                     acc_region_metas, virtual_address_space_adjustments,
     819       10397 :                                                     direct_mapping, direct_account_pointers_in_program_input,
     820       10397 :                                                     instr_data_offset, serialized_bytes_written );
     821       10397 :   }
     822       12779 : }
     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        1584 :                                             uchar                 is_deprecated ) {
     833        1584 :   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        1034 :   } else {
     837        1034 :     return fd_bpf_loader_input_deserialize_for_abiv1(
     838        1034 :       ctx, pre_lens, input, input_sz, virtual_address_space_adjustments, direct_mapping );
     839        1034 :   }
     840        1584 : }

Generated by: LCOV version 1.14