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 7254 : 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 7254 : ulong vaddr_offset = *input_mem_regions_cnt==0UL ? 0UL : input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
131 4278 : input_mem_regions[ *input_mem_regions_cnt-1U ].address_space_reserved;
132 7254 : input_mem_regions[ *input_mem_regions_cnt ].is_writable = is_writable;
133 7254 : input_mem_regions[ *input_mem_regions_cnt ].haddr = (ulong)buffer;
134 7254 : input_mem_regions[ *input_mem_regions_cnt ].region_sz = (uint)region_sz;
135 7254 : input_mem_regions[ *input_mem_regions_cnt ].address_space_reserved = address_space_reserved;
136 7254 : input_mem_regions[ *input_mem_regions_cnt ].vaddr_offset = vaddr_offset;
137 7254 : input_mem_regions[ *input_mem_regions_cnt ].acc_region_meta_idx = acc_region_meta_idx;
138 7254 : (*input_mem_regions_cnt)++;
139 7254 : }
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 4218 : int direct_mapping ) {
161 :
162 4218 : uchar const * data = account ? fd_borrowed_account_get_data( account ) : NULL;
163 4218 : ulong dlen = account ? fd_borrowed_account_get_data_len( account ) : 0UL;
164 :
165 4218 : acc_region_metas[instr_acc_idx].original_data_len = dlen;
166 4218 : acc_region_metas[instr_acc_idx].acc = account->acc;
167 :
168 : /* Legacy behavior: no virtual_address_space_adjustments (also implies no direct mapping)
169 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L132-L142 */
170 4218 : if( !virtual_address_space_adjustments ) {
171 : /* Copy the account data into input region buffer */
172 2067 : fd_memcpy( *serialized_params, data, dlen );
173 2067 : *serialized_params += dlen;
174 :
175 2067 : if( FD_LIKELY( !is_loader_v1 ) ) {
176 : /* Zero out padding bytes and max permitted data increase */
177 2007 : ulong align_offset = fd_ulong_align_up( dlen, FD_BPF_ALIGN_OF_U128 ) - dlen;
178 2007 : fd_memset( *serialized_params, 0, MAX_PERMITTED_DATA_INCREASE + align_offset );
179 2007 : *serialized_params += MAX_PERMITTED_DATA_INCREASE + align_offset;
180 2007 : }
181 2067 : acc_region_metas[instr_acc_idx].region_idx = UINT_MAX;
182 2151 : } else { /* virtual_address_space_adjustments == true */
183 :
184 : /* Set up account region metadata */
185 2151 : acc_region_metas[instr_acc_idx].region_idx = *input_mem_regions_cnt;
186 :
187 : /* First, push on the region for the metadata that has just been serialized.
188 : This function will push the metadata in the serialized_params from
189 : serialized_params_start to serialized_params as a region to the input
190 : memory regions array.
191 :
192 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L143 */
193 2151 : ulong region_sz = (ulong)(*serialized_params) - (ulong)(*serialized_params_start);
194 2151 : new_input_mem_region( input_mem_regions, input_mem_regions_cnt, *serialized_params_start, region_sz, region_sz, 1U, ULONG_MAX );
195 :
196 : /* If direct mapping isn't enabled, then copy the account data in directly
197 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L145-L151 */
198 2151 : if( !direct_mapping ) {
199 1044 : fd_memcpy( *serialized_params, data, dlen );
200 1044 : *serialized_params += dlen;
201 1044 : if( FD_LIKELY( !is_loader_v1 ) ) {
202 984 : fd_memset( *serialized_params, 0, MAX_PERMITTED_DATA_INCREASE );
203 984 : *serialized_params += MAX_PERMITTED_DATA_INCREASE;
204 984 : }
205 1044 : }
206 :
207 : /* Calculate address space reserved for account (data + realloc space)
208 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L152-L159 */
209 2151 : ulong address_space_reserved = !is_loader_v1 ?
210 2031 : fd_ulong_sat_add( dlen, MAX_PERMITTED_DATA_INCREASE ) : dlen;
211 :
212 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L160-L170 */
213 2151 : if( address_space_reserved > 0 ) {
214 2127 : int err = 0;
215 2127 : uchar is_writable = !!(fd_borrowed_account_can_data_be_changed( account, &err ) && !err);
216 :
217 2127 : if( !direct_mapping ) {
218 : /* Create region pointing to the copied data in buffer
219 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L161-L165 */
220 1032 : uchar * data_start = *serialized_params - address_space_reserved;
221 1032 : new_input_mem_region( input_mem_regions, input_mem_regions_cnt, data_start, dlen, address_space_reserved, is_writable, instr_acc_idx );
222 1095 : } else {
223 : /* Direct mapping: create region pointing directly to account data */
224 1095 : new_input_mem_region( input_mem_regions, input_mem_regions_cnt, data, dlen, address_space_reserved, is_writable, instr_acc_idx );
225 1095 : }
226 2127 : }
227 :
228 2151 : *serialized_params_start = *serialized_params;
229 :
230 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L171-L187 */
231 2151 : if( FD_LIKELY( !is_loader_v1 ) ) {
232 2031 : ulong align_offset = fd_ulong_align_up( dlen, FD_BPF_ALIGN_OF_U128 ) - dlen;
233 2031 : if( !direct_mapping ) {
234 : /* If direct mapping is not enabled, we do not align the start of each
235 : region metadata to FD_BPF_ALIGN_OF_U128, but we do align the start
236 : of the actual contents of the metadata region.
237 :
238 : This follows Agave's logic
239 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L174-L177 */
240 984 : fd_memset( *serialized_params, 0, align_offset );
241 984 : *serialized_params += align_offset;
242 1047 : } else {
243 : /* If direct mapping is enabled, we align the start of each region
244 : metadata to FD_BPF_ALIGN_OF_U128. */
245 1047 : fd_memset( *serialized_params, 0, FD_BPF_ALIGN_OF_U128 );
246 1047 : *serialized_params += FD_BPF_ALIGN_OF_U128;
247 1047 : *serialized_params_start += fd_ulong_sat_sub( FD_BPF_ALIGN_OF_U128, align_offset );
248 1047 : }
249 2031 : }
250 :
251 2151 : return region_sz + address_space_reserved;
252 2151 : }
253 :
254 2067 : return 0UL;
255 4218 : }
256 :
257 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L473 */
258 : static int
259 : fd_bpf_loader_input_serialize_for_abiv1( fd_exec_instr_ctx_t * ctx,
260 : ulong * pre_lens,
261 : fd_vm_input_region_t * input_mem_regions,
262 : uint * input_mem_regions_cnt,
263 : fd_vm_acc_region_meta_t * acc_region_metas,
264 : int virtual_address_space_adjustments,
265 : int direct_mapping,
266 : int direct_account_pointers_in_program_input,
267 : ulong * instr_data_offset,
268 2868 : ulong * serialized_bytes_written ) {
269 : /* Transaction sanitisation limits the number of instruction accounts to
270 : FD_TXN_ACCT_ADDR_MAX. */
271 2868 : uchar acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ] = {0};
272 2868 : ushort dup_acc_idx[ FD_TXN_ACCT_ADDR_MAX ] = {0};
273 :
274 : /* 16-byte aligned buffer from runtime:
275 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L61 */
276 2868 : uchar * serialized_params = ctx->runtime->bpf_loader_serialization.serialization_mem[ ctx->runtime->instr.stack_sz-1UL ];
277 2868 : uchar * serialized_params_start = serialized_params;
278 2868 : uchar * curr_serialized_params_start = serialized_params;
279 2868 : ulong curr_region_vaddr = 0UL;
280 :
281 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L539 */
282 2868 : FD_STORE( ulong, serialized_params, ctx->instr->acct_cnt );
283 2868 : serialized_params += sizeof(ulong);
284 :
285 : /* Iterate over accounts in the instruction to populate input region.
286 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L540-L570 */
287 8847 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
288 5979 : uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
289 5979 : fd_pubkey_t * acc = &ctx->txn_out->accounts.keys[acc_idx];
290 :
291 5979 : if( FD_UNLIKELY( acc_idx_seen[acc_idx] && dup_acc_idx[acc_idx] != i ) ) {
292 : /* Duplicate. Store 8 byte buffer to maintain alignment but store the
293 : account index in the first byte.
294 :
295 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L564-L568 */
296 1941 : FD_STORE( ulong, serialized_params, 0UL );
297 1941 : FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
298 1941 : serialized_params += sizeof(ulong);
299 :
300 : /* Clone the account metadata from the original account
301 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L372 */
302 1941 : acc_region_metas[i] = acc_region_metas[dup_acc_idx[acc_idx]];
303 4038 : } else {
304 4038 : acc_idx_seen[acc_idx] = 1;
305 4038 : dup_acc_idx[acc_idx] = i;
306 :
307 4038 : acc_region_metas[i].vm_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
308 4038 : (ulong)(serialized_params - curr_serialized_params_start);
309 :
310 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L376 */
311 4038 : FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
312 4038 : serialized_params += sizeof(uchar);
313 :
314 : /* Borrow the account
315 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L245-L258 */
316 4038 : fd_guarded_borrowed_account_t view_acc = {0};
317 4038 : int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, &view_acc );
318 4038 : if( FD_UNLIKELY( err ) ) {
319 0 : return err;
320 0 : }
321 :
322 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L544 */
323 4038 : uchar is_signer = (uchar)fd_instr_acc_is_signer_idx( ctx->instr, (uchar)i, NULL );
324 4038 : FD_STORE( uchar, serialized_params, is_signer );
325 4038 : serialized_params += sizeof(uchar);
326 :
327 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L545 */
328 4038 : uchar is_writable = (uchar)fd_instr_acc_is_writable_idx( ctx->instr, (uchar)i );
329 4038 : FD_STORE( uchar, serialized_params, is_writable );
330 4038 : serialized_params += sizeof(uchar);
331 :
332 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L546-L547 */
333 4038 : uchar is_executable = (uchar)view_acc.acc->executable;
334 4038 : FD_STORE( uchar, serialized_params, is_executable );
335 4038 : serialized_params += sizeof(uchar);
336 :
337 : /* The original data len field is intentionally NOT populated. */
338 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L548 */
339 4038 : uint padding_0 = 0U;
340 4038 : FD_STORE( uint, serialized_params, padding_0 );
341 4038 : serialized_params += sizeof(uint);
342 :
343 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L549 */
344 4038 : fd_pubkey_t key = *acc;
345 4038 : acc_region_metas[i].vm_key_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
346 4038 : (ulong)(serialized_params - curr_serialized_params_start);
347 4038 : FD_STORE( fd_pubkey_t, serialized_params, key );
348 4038 : serialized_params += sizeof(fd_pubkey_t);
349 :
350 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L550 */
351 4038 : fd_pubkey_t owner = *(fd_pubkey_t *)&view_acc.acc->owner;
352 4038 : acc_region_metas[i].vm_owner_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
353 4038 : (ulong)(serialized_params - curr_serialized_params_start);
354 4038 : FD_STORE( fd_pubkey_t, serialized_params, owner );
355 4038 : serialized_params += sizeof(fd_pubkey_t);
356 :
357 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L551 */
358 4038 : ulong lamports = view_acc.acc->lamports;
359 4038 : acc_region_metas[i].vm_lamports_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
360 4038 : (ulong)(serialized_params - curr_serialized_params_start);
361 4038 : FD_STORE( ulong, serialized_params, lamports );
362 4038 : serialized_params += sizeof(ulong);
363 :
364 4038 : ulong acc_data_len = view_acc.acc->data_len;
365 4038 : pre_lens[i] = acc_data_len;
366 :
367 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L552 */
368 4038 : ulong data_len = acc_data_len;
369 4038 : FD_STORE( ulong, serialized_params, data_len );
370 4038 : serialized_params += sizeof(ulong);
371 :
372 : /* vm_data_addr: data is written immediately after the data_len field */
373 4038 : acc_region_metas[i].vm_data_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
374 4038 : (ulong)(serialized_params - curr_serialized_params_start);
375 :
376 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L553 */
377 4038 : write_account(
378 4038 : &view_acc,
379 4038 : (uchar)i,
380 4038 : &serialized_params,
381 4038 : &curr_serialized_params_start,
382 4038 : input_mem_regions,
383 4038 : input_mem_regions_cnt,
384 4038 : acc_region_metas,
385 4038 : 0,
386 4038 : virtual_address_space_adjustments,
387 4038 : direct_mapping );
388 :
389 : /* write_account may have pushed a new region(s) */
390 4038 : curr_region_vaddr = *input_mem_regions_cnt == 0U ? 0UL :
391 4038 : input_mem_regions[*input_mem_regions_cnt-1U].vaddr_offset +
392 2031 : input_mem_regions[*input_mem_regions_cnt-1U].address_space_reserved;
393 :
394 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L554-L555 */
395 4038 : FD_STORE( ulong, serialized_params, ULONG_MAX );
396 4038 : serialized_params += sizeof(ulong);
397 4038 : }
398 :
399 5979 : }
400 :
401 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L571 */
402 2868 : ulong instr_data_len = ctx->instr->data_sz;
403 2868 : FD_STORE( ulong, serialized_params, instr_data_len );
404 2868 : serialized_params += sizeof(ulong);
405 :
406 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L572 */
407 2868 : *instr_data_offset = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
408 2868 : (ulong)(serialized_params - curr_serialized_params_start);
409 :
410 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L571 */
411 2868 : fd_memcpy( serialized_params, ctx->instr->data, instr_data_len );
412 2868 : serialized_params += instr_data_len;
413 :
414 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L400 */
415 2868 : FD_STORE( fd_pubkey_t, serialized_params, ctx->txn_out->accounts.keys[ctx->instr->program_id] );
416 2868 : serialized_params += sizeof(fd_pubkey_t);
417 :
418 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-rc.0/program-runtime/src/serialization.rs#L522-L529 */
419 2868 : if( direct_account_pointers_in_program_input ) {
420 237 : ulong cur_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
421 237 : (ulong)(serialized_params - curr_serialized_params_start);
422 237 : ulong padding = FD_ULONG_ALIGN_UP( cur_vaddr, FD_BPF_ALIGN_OF_U128 ) - cur_vaddr;
423 237 : fd_memset( serialized_params, 0, padding );
424 237 : serialized_params += padding;
425 2322 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
426 2085 : FD_STORE( ulong, serialized_params, acc_region_metas[i].vm_addr );
427 2085 : serialized_params += sizeof(ulong);
428 2085 : }
429 237 : }
430 :
431 : /* Write out the final region. */
432 2868 : ulong region_sz = (ulong)(serialized_params - curr_serialized_params_start);
433 2868 : new_input_mem_region( input_mem_regions, input_mem_regions_cnt, curr_serialized_params_start,
434 2868 : region_sz, region_sz, 1U, ULONG_MAX );
435 :
436 2868 : *serialized_bytes_written = (ulong)(serialized_params - serialized_params_start);
437 2868 : return FD_EXECUTOR_INSTR_SUCCESS;
438 2868 : }
439 :
440 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L594-L681 */
441 : static int
442 : fd_bpf_loader_input_deserialize_for_abiv1( fd_exec_instr_ctx_t * ctx,
443 : ulong const * pre_lens,
444 : uchar * buffer,
445 : ulong FD_FN_UNUSED buffer_sz,
446 : int virtual_address_space_adjustments,
447 2388 : int direct_mapping ) {
448 : /* TODO: An optimization would be to skip ahead through non-writable accounts */
449 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L601 */
450 2388 : ulong start = 0UL;
451 :
452 2388 : uchar acc_idx_seen[256] = {0};
453 :
454 2388 : start += sizeof(ulong); // number of accounts
455 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L602-L679 */
456 5802 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
457 3534 : uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
458 :
459 3534 : start++; // position
460 :
461 : /* get the borrowed account
462 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L612-L613 */
463 3534 : fd_guarded_borrowed_account_t view_acc = {0};
464 3534 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, i, &view_acc );
465 :
466 3534 : if( FD_UNLIKELY( acc_idx_seen[acc_idx] ) ) {
467 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L610 */
468 144 : start += 7UL;
469 3390 : } else {
470 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L614-L618 */
471 3390 : acc_idx_seen[acc_idx] = 1;
472 3390 : start += sizeof(uchar) // is_signer
473 3390 : + sizeof(uchar) // is_writable
474 3390 : + sizeof(uchar) // executable
475 3390 : + sizeof(uint) // original_data_len
476 3390 : + sizeof(fd_pubkey_t); // key
477 :
478 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L619-L621 */
479 :
480 3390 : fd_pubkey_t * owner = (fd_pubkey_t *)(buffer+start);
481 3390 : start += sizeof(fd_pubkey_t); // owner
482 :
483 3390 : ulong lamports = FD_LOAD( ulong, buffer+start );
484 3390 : if( lamports!=fd_borrowed_account_get_lamports( &view_acc ) ) {
485 0 : int err = fd_borrowed_account_set_lamports( &view_acc, lamports );
486 0 : if( FD_UNLIKELY( err ) ) {
487 0 : return err;
488 0 : }
489 0 : }
490 3390 : start += sizeof(ulong); // lamports
491 :
492 3390 : ulong post_len = FD_LOAD( ulong, buffer+start );
493 3390 : start += sizeof(ulong); // data length
494 :
495 3390 : ulong pre_len = pre_lens[i];
496 3390 : ulong alignment_offset = fd_ulong_align_up( pre_len, FD_BPF_ALIGN_OF_U128 ) - pre_len;
497 :
498 3390 : uchar * post_data = buffer+start;
499 :
500 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L640-L644 */
501 3390 : if( FD_UNLIKELY( fd_ulong_sat_sub( post_len, pre_len )>MAX_PERMITTED_DATA_INCREASE ||
502 3390 : post_len>MAX_PERMITTED_DATA_LENGTH ) ) {
503 96 : return FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
504 96 : }
505 :
506 3294 : int can_data_be_changed_err = 0;
507 3294 : if( !virtual_address_space_adjustments ) {
508 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L645-L655 */
509 :
510 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L646-L648 */
511 1719 : if( FD_UNLIKELY( start + post_len > buffer_sz ) ) {
512 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
513 0 : }
514 :
515 : /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/program-runtime/src/serialization.rs#L648-L652 */
516 1719 : int can_data_be_resized_err = 0;
517 1719 : if( fd_borrowed_account_can_data_be_resized( &view_acc, post_len, &can_data_be_resized_err ) ) {
518 1365 : int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, post_len );
519 1365 : if( FD_UNLIKELY( set_data_err ) ) {
520 0 : return set_data_err;
521 0 : }
522 1365 : } else {
523 354 : if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &view_acc )!=post_len ||
524 354 : memcmp( fd_borrowed_account_get_data( &view_acc ), post_data, post_len ) ) ) {
525 24 : return can_data_be_resized_err;
526 24 : }
527 354 : }
528 :
529 1719 : } else if( !direct_mapping && fd_borrowed_account_can_data_be_changed( &view_acc, &can_data_be_changed_err ) ) {
530 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L657-L659 */
531 624 : if( FD_UNLIKELY( start + post_len > buffer_sz ) ) {
532 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
533 0 : }
534 :
535 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L655-L661 */
536 624 : int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, post_len );
537 624 : if( FD_UNLIKELY( set_data_err ) ) {
538 0 : return set_data_err;
539 0 : }
540 951 : } else if( fd_borrowed_account_get_data_len( &view_acc ) != post_len ) {
541 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L661-L663 */
542 156 : int set_data_length_err = fd_borrowed_account_set_data_length( &view_acc, post_len );
543 156 : if( FD_UNLIKELY( set_data_length_err ) ) {
544 0 : return set_data_length_err;
545 0 : }
546 156 : }
547 :
548 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L664-L672 */
549 3270 : if( !( virtual_address_space_adjustments && direct_mapping ) ) {
550 2475 : start += fd_ulong_sat_add( MAX_PERMITTED_DATA_INCREASE, fd_ulong_sat_add( pre_len, alignment_offset ) );
551 2475 : } else {
552 795 : start += FD_BPF_ALIGN_OF_U128;
553 795 : }
554 :
555 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L673 */
556 3270 : start += sizeof(ulong); // rent epoch
557 3270 : if( memcmp( fd_borrowed_account_get_owner( &view_acc ), owner, sizeof(fd_pubkey_t) ) ) {
558 0 : int err = fd_borrowed_account_set_owner( &view_acc, owner );
559 0 : if( FD_UNLIKELY( err ) ) {
560 0 : return err;
561 0 : }
562 0 : }
563 3270 : }
564 3534 : }
565 :
566 2268 : return FD_EXECUTOR_INSTR_SUCCESS;
567 2388 : }
568 :
569 : static int
570 : fd_bpf_loader_input_serialize_for_abiv0( fd_exec_instr_ctx_t * ctx,
571 : ulong * pre_lens,
572 : fd_vm_input_region_t * input_mem_regions,
573 : uint * input_mem_regions_cnt,
574 : fd_vm_acc_region_meta_t * acc_region_metas,
575 : int virtual_address_space_adjustments,
576 : int direct_mapping,
577 : ulong * instr_data_offset,
578 108 : ulong * serialized_bytes_written ) {
579 : /* Transaction sanitisation limits the number of instruction accounts to
580 : FD_TXN_ACCT_ADDR_MAX. */
581 108 : uchar acc_idx_seen[ FD_TXN_ACCT_ADDR_MAX ] = {0};
582 108 : ushort dup_acc_idx[ FD_TXN_ACCT_ADDR_MAX ] = {0};
583 :
584 : /* 16-byte aligned buffer:
585 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L61 */
586 108 : uchar * serialized_params = ctx->runtime->bpf_loader_serialization.serialization_mem[ ctx->runtime->instr.stack_sz-1UL ];
587 108 : uchar * serialized_params_start = serialized_params;
588 108 : uchar * curr_serialized_params_start = serialized_params;
589 108 : ulong curr_region_vaddr = 0UL;
590 :
591 108 : FD_STORE( ulong, serialized_params, ctx->instr->acct_cnt );
592 108 : serialized_params += sizeof(ulong);
593 :
594 342 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
595 234 : uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
596 234 : fd_pubkey_t const * acc = &ctx->txn_out->accounts.keys[acc_idx];
597 :
598 234 : if( FD_UNLIKELY( acc_idx_seen[acc_idx] && dup_acc_idx[acc_idx] != i ) ) {
599 : // Duplicate
600 54 : FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
601 54 : serialized_params += sizeof(uchar);
602 :
603 : /* Clone the account metadata from the original account
604 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L382 */
605 54 : acc_region_metas[i] = acc_region_metas[dup_acc_idx[acc_idx]];
606 180 : } else {
607 180 : acc_idx_seen[acc_idx] = 1;
608 180 : dup_acc_idx[acc_idx] = i;
609 :
610 180 : FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
611 180 : serialized_params += sizeof(uchar);
612 :
613 : /* Borrow the account
614 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L253 */
615 180 : fd_guarded_borrowed_account_t view_acc = {0};
616 180 : int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, i, &view_acc );
617 180 : if( FD_UNLIKELY( err ) ) {
618 0 : return err;
619 0 : }
620 :
621 180 : pre_lens[ i ] = view_acc.acc->data_len;
622 :
623 180 : uchar is_signer = (uchar)fd_instr_acc_is_signer_idx( ctx->instr, (uchar)i, NULL );
624 180 : FD_STORE( uchar, serialized_params, is_signer );
625 180 : serialized_params += sizeof(uchar);
626 :
627 180 : uchar is_writable = (uchar)fd_instr_acc_is_writable_idx( ctx->instr, (uchar)i );
628 180 : FD_STORE( uchar, serialized_params, is_writable );
629 180 : serialized_params += sizeof(uchar);
630 :
631 180 : fd_pubkey_t key = *acc;
632 180 : acc_region_metas[i].vm_key_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
633 180 : (ulong)(serialized_params - curr_serialized_params_start);
634 180 : FD_STORE( fd_pubkey_t, serialized_params, key );
635 180 : serialized_params += sizeof(fd_pubkey_t);
636 :
637 180 : ulong lamports = view_acc.acc->lamports;
638 180 : acc_region_metas[i].vm_lamports_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
639 180 : (ulong)(serialized_params - curr_serialized_params_start);
640 180 : FD_STORE( ulong, serialized_params, lamports );
641 180 : serialized_params += sizeof(ulong);
642 :
643 180 : ulong acc_data_len = view_acc.acc->data_len;
644 180 : FD_STORE( ulong, serialized_params, acc_data_len );
645 180 : serialized_params += sizeof(ulong);
646 :
647 : /* vm_data_addr: data is written immediately after the data_len field */
648 180 : acc_region_metas[i].vm_data_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
649 180 : (ulong)(serialized_params - curr_serialized_params_start);
650 :
651 180 : write_account( &view_acc, (uchar)i,
652 180 : &serialized_params, &curr_serialized_params_start,
653 180 : input_mem_regions, input_mem_regions_cnt, acc_region_metas, 1,
654 180 : virtual_address_space_adjustments, direct_mapping );
655 :
656 : /* write_account may have pushed a new region(s) */
657 180 : curr_region_vaddr = *input_mem_regions_cnt == 0U ? 0UL :
658 180 : input_mem_regions[*input_mem_regions_cnt-1U].vaddr_offset +
659 120 : input_mem_regions[*input_mem_regions_cnt-1U].address_space_reserved;
660 :
661 180 : fd_pubkey_t owner = *(fd_pubkey_t *)&view_acc.acc->owner;
662 180 : acc_region_metas[i].vm_owner_addr = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
663 180 : (ulong)(serialized_params - curr_serialized_params_start);
664 180 : FD_STORE( fd_pubkey_t, serialized_params, owner );
665 180 : serialized_params += sizeof(fd_pubkey_t);
666 :
667 180 : uchar is_executable = (uchar)view_acc.acc->executable;
668 180 : FD_STORE( uchar, serialized_params, is_executable );
669 180 : serialized_params += sizeof(uchar);
670 :
671 180 : FD_STORE( ulong, serialized_params, ULONG_MAX );
672 180 : serialized_params += sizeof(ulong);
673 180 : }
674 234 : }
675 :
676 108 : ulong instr_data_len = ctx->instr->data_sz;
677 108 : FD_STORE( ulong, serialized_params, instr_data_len );
678 108 : serialized_params += sizeof(ulong);
679 :
680 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L399 */
681 108 : *instr_data_offset = FD_VM_MEM_MAP_INPUT_REGION_START + curr_region_vaddr +
682 108 : (ulong)(serialized_params - curr_serialized_params_start);
683 :
684 108 : fd_memcpy( serialized_params, ctx->instr->data, instr_data_len );
685 108 : serialized_params += instr_data_len;
686 :
687 108 : FD_STORE( fd_pubkey_t, serialized_params, ctx->txn_out->accounts.keys[ctx->instr->program_id] );
688 108 : serialized_params += sizeof(fd_pubkey_t);
689 :
690 108 : *serialized_bytes_written = (ulong)(serialized_params - serialized_params_start);
691 :
692 108 : ulong region_sz = (ulong)(serialized_params - curr_serialized_params_start);
693 108 : new_input_mem_region( input_mem_regions, input_mem_regions_cnt, curr_serialized_params_start,
694 108 : region_sz, region_sz, 1U, ULONG_MAX );
695 :
696 108 : return FD_EXECUTOR_INSTR_SUCCESS;
697 108 : }
698 :
699 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L411 */
700 : static int
701 : fd_bpf_loader_input_deserialize_for_abiv0( fd_exec_instr_ctx_t * ctx,
702 : ulong const * pre_lens,
703 : uchar * input,
704 : ulong input_sz,
705 : int virtual_address_space_adjustments,
706 0 : int direct_mapping ) {
707 0 : uchar * input_cursor = input;
708 0 : uchar acc_idx_seen[256] = {0};
709 :
710 0 : input_cursor += sizeof(ulong);
711 :
712 0 : for( ushort i=0; i<ctx->instr->acct_cnt; i++ ) {
713 0 : uchar acc_idx = (uchar)ctx->instr->accounts[i].index_in_transaction;
714 :
715 0 : input_cursor++; /* is_dup */
716 0 : if( FD_UNLIKELY( acc_idx_seen[acc_idx] ) ) {
717 : /* no-op */
718 0 : } else {
719 0 : acc_idx_seen[acc_idx] = 1;
720 0 : input_cursor += sizeof(uchar) + /* is_signer */
721 0 : sizeof(uchar) + /* is_writable */
722 0 : sizeof(fd_pubkey_t); /* key */
723 :
724 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L427-L428 */
725 0 : fd_guarded_borrowed_account_t view_acc = {0};
726 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, i, &view_acc );
727 :
728 0 : ulong lamports = FD_LOAD( ulong, input_cursor );
729 0 : if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &view_acc )!=lamports ) ) {
730 0 : int err = fd_borrowed_account_set_lamports( &view_acc, lamports );
731 0 : if( FD_UNLIKELY( err ) ) {
732 0 : return err;
733 0 : }
734 0 : }
735 :
736 0 : input_cursor += sizeof(ulong); /* lamports */
737 0 : input_cursor += sizeof(ulong); /* data length */
738 :
739 0 : ulong pre_len = pre_lens[i];
740 0 : uchar * post_data = input_cursor;
741 :
742 : /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/program-runtime/src/serialization.rs#L446-L450 */
743 0 : int can_data_be_changed_err = 0;
744 0 : if( !virtual_address_space_adjustments ) {
745 0 : int can_data_be_resized_err = 0;
746 0 : if( fd_borrowed_account_can_data_be_resized( &view_acc, pre_len, &can_data_be_resized_err ) ) {
747 0 : int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, pre_len );
748 0 : if( FD_UNLIKELY( set_data_err ) ) {
749 0 : return set_data_err;
750 0 : }
751 0 : } else if( fd_borrowed_account_get_data_len( &view_acc ) != pre_len ||
752 0 : memcmp( post_data, fd_borrowed_account_get_data( &view_acc ), pre_len ) ) {
753 0 : return can_data_be_resized_err;
754 0 : }
755 0 : } else if( !direct_mapping && fd_borrowed_account_can_data_be_changed( &view_acc, &can_data_be_changed_err ) ) {
756 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L453-L459 */
757 0 : int set_data_err = fd_borrowed_account_set_data_from_slice( &view_acc, post_data, pre_len );
758 0 : if( FD_UNLIKELY( set_data_err ) ) {
759 0 : return set_data_err;
760 0 : }
761 0 : } else if( fd_borrowed_account_get_data_len( &view_acc ) != pre_len ) {
762 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L459-L461 */
763 0 : int set_data_length_err = fd_borrowed_account_set_data_length( &view_acc, pre_len );
764 0 : if( FD_UNLIKELY( set_data_length_err ) ) {
765 0 : return set_data_length_err;
766 0 : }
767 0 : }
768 :
769 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L462-L464 */
770 0 : if( !( virtual_address_space_adjustments && direct_mapping ) ) {
771 0 : input_cursor += pre_len;
772 0 : }
773 0 : input_cursor += sizeof(fd_pubkey_t) + /* owner */
774 0 : sizeof(uchar) + /* executable */
775 0 : sizeof(ulong); /* rent_epoch*/
776 0 : }
777 0 : }
778 :
779 0 : if( FD_UNLIKELY( input_cursor>input+input_sz ) ) {
780 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
781 0 : }
782 :
783 0 : return 0;
784 0 : }
785 :
786 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L222 */
787 : int
788 : fd_bpf_loader_input_serialize_parameters( fd_exec_instr_ctx_t * instr_ctx,
789 : ulong * pre_lens,
790 : fd_vm_input_region_t * input_mem_regions,
791 : uint * input_mem_regions_cnt,
792 : fd_vm_acc_region_meta_t * acc_region_metas,
793 : int virtual_address_space_adjustments,
794 : int direct_mapping,
795 : int direct_account_pointers_in_program_input,
796 : uchar is_deprecated,
797 : ulong * instr_data_offset,
798 2976 : ulong * serialized_bytes_written ) {
799 :
800 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L236-L239 */
801 2976 : ulong num_ix_accounts = instr_ctx->instr->acct_cnt;
802 2976 : if( FD_UNLIKELY( num_ix_accounts>FD_TXN_INSTR_ACCT_MAX ) ) {
803 0 : return FD_EXECUTOR_INSTR_ERR_MAX_ACCS_EXCEEDED;
804 0 : }
805 :
806 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L265-L285 */
807 2976 : if( FD_UNLIKELY( is_deprecated ) ) {
808 108 : return fd_bpf_loader_input_serialize_for_abiv0( instr_ctx, pre_lens,
809 108 : input_mem_regions, input_mem_regions_cnt,
810 108 : acc_region_metas, virtual_address_space_adjustments,
811 108 : direct_mapping, instr_data_offset, serialized_bytes_written );
812 2868 : } else {
813 2868 : return fd_bpf_loader_input_serialize_for_abiv1( instr_ctx, pre_lens,
814 2868 : input_mem_regions, input_mem_regions_cnt,
815 2868 : acc_region_metas, virtual_address_space_adjustments,
816 2868 : direct_mapping, direct_account_pointers_in_program_input,
817 2868 : instr_data_offset, serialized_bytes_written );
818 2868 : }
819 2976 : }
820 :
821 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.3/program-runtime/src/serialization.rs#L288-L317 */
822 : int
823 : fd_bpf_loader_input_deserialize_parameters( fd_exec_instr_ctx_t * ctx,
824 : ulong const * pre_lens,
825 : uchar * input,
826 : ulong input_sz,
827 : int virtual_address_space_adjustments,
828 : int direct_mapping,
829 2388 : uchar is_deprecated ) {
830 2388 : if( FD_UNLIKELY( is_deprecated ) ) {
831 0 : return fd_bpf_loader_input_deserialize_for_abiv0(
832 0 : ctx, pre_lens, input, input_sz, virtual_address_space_adjustments, direct_mapping );
833 2388 : } else {
834 2388 : return fd_bpf_loader_input_deserialize_for_abiv1(
835 2388 : ctx, pre_lens, input, input_sz, virtual_address_space_adjustments, direct_mapping );
836 2388 : }
837 2388 : }
|