Line data Source code
1 : #include "fd_bpf_program_util.h"
2 : #include "fd_bpf_loader_program.h"
3 : #include "fd_loader_v4_program.h"
4 : #include "../fd_acc_mgr.h"
5 : #include "../context/fd_exec_slot_ctx.h"
6 : #include "../../vm/syscall/fd_vm_syscall.h"
7 :
8 : #include <assert.h>
9 :
10 : fd_sbpf_validated_program_t *
11 2373 : fd_sbpf_validated_program_new( void * mem, fd_sbpf_elf_info_t const * elf_info ) {
12 2373 : fd_sbpf_validated_program_t * validated_prog = (fd_sbpf_validated_program_t *)mem;
13 :
14 2373 : ulong l = FD_LAYOUT_INIT;
15 :
16 : /* calldests backing memory */
17 2373 : l = FD_LAYOUT_APPEND( l, alignof(fd_sbpf_validated_program_t), sizeof(fd_sbpf_validated_program_t) );
18 2373 : validated_prog->calldests_shmem = (uchar *)mem + l;
19 :
20 : /* rodata backing memory */
21 2373 : l = FD_LAYOUT_APPEND( l, fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint(elf_info->rodata_sz/8UL) );
22 2373 : validated_prog->rodata = (uchar *)mem + l;
23 :
24 : /* SBPF version */
25 2373 : validated_prog->sbpf_version = elf_info->sbpf_version;
26 :
27 2373 : return (fd_sbpf_validated_program_t *)mem;
28 2373 : }
29 :
30 : ulong
31 0 : fd_sbpf_validated_program_align( void ) {
32 0 : return alignof(fd_sbpf_validated_program_t);
33 0 : }
34 :
35 : ulong
36 2373 : fd_sbpf_validated_program_footprint( fd_sbpf_elf_info_t const * elf_info ) {
37 2373 : ulong l = FD_LAYOUT_INIT;
38 2373 : l = FD_LAYOUT_APPEND( l, alignof(fd_sbpf_validated_program_t), sizeof(fd_sbpf_validated_program_t) );
39 2373 : l = FD_LAYOUT_APPEND( l, fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint(elf_info->rodata_sz/8UL) );
40 2373 : l = FD_LAYOUT_APPEND( l, 8UL, elf_info->rodata_footprint );
41 2373 : l = FD_LAYOUT_FINI( l, 128UL );
42 2373 : return l;
43 2373 : }
44 :
45 : static inline fd_funk_rec_key_t
46 122490 : fd_acc_mgr_cache_key( fd_pubkey_t const * pubkey ) {
47 122490 : fd_funk_rec_key_t id;
48 122490 : memcpy( id.uc, pubkey, sizeof(fd_pubkey_t) );
49 122490 : memset( id.uc + sizeof(fd_pubkey_t), 0, sizeof(fd_funk_rec_key_t) - sizeof(fd_pubkey_t) );
50 :
51 122490 : id.c[ FD_FUNK_REC_KEY_FOOTPRINT - 1 ] = FD_FUNK_KEY_TYPE_ELF_CACHE;
52 :
53 122490 : return id;
54 122490 : }
55 :
56 : /* Similar to the below function, but gets the executable program content for the v4 loader.
57 : Unlike the v3 loader, the programdata is stored in a single program account. The program must
58 : NOT be retracted to be added to the cache. */
59 : static int
60 : fd_bpf_get_executable_program_content_for_v4_loader( fd_borrowed_account_t * program_acc,
61 : uchar const ** program_data,
62 2943 : ulong * program_data_len ) {
63 2943 : int err;
64 2943 : fd_loader_v4_state_t state = {0};
65 :
66 : /* Get the current loader v4 state. This implicitly also checks the dlen. */
67 2943 : err = fd_loader_v4_get_state( program_acc, &state );
68 2943 : if( FD_UNLIKELY( err ) ) {
69 2079 : return -1;
70 2079 : }
71 :
72 : /* The program must be deployed or finalized. */
73 864 : if( FD_UNLIKELY( fd_loader_v4_status_is_retracted( &state ) ) ) {
74 240 : return -1;
75 240 : }
76 :
77 624 : *program_data = program_acc->const_data + LOADER_V4_PROGRAM_DATA_OFFSET;
78 624 : *program_data_len = program_acc->const_meta->dlen - LOADER_V4_PROGRAM_DATA_OFFSET;
79 624 : return 0;
80 864 : }
81 :
82 : static int
83 : fd_bpf_get_executable_program_content_for_upgradeable_loader( fd_exec_slot_ctx_t * slot_ctx,
84 : fd_borrowed_account_t * program_acc,
85 : uchar const ** program_data,
86 56079 : ulong * program_data_len ) {
87 56079 : FD_BORROWED_ACCOUNT_DECL( programdata_acc );
88 :
89 56079 : fd_bincode_decode_ctx_t ctx = {
90 56079 : .data = program_acc->const_data,
91 56079 : .dataend = program_acc->const_data + program_acc->const_meta->dlen,
92 56079 : .valloc = fd_scratch_virtual(),
93 56079 : };
94 :
95 56079 : fd_bpf_upgradeable_loader_state_t program_account_state = {0};
96 56079 : if( FD_UNLIKELY( fd_bpf_upgradeable_loader_state_decode( &program_account_state, &ctx ) ) ) {
97 34095 : return -1;
98 34095 : }
99 :
100 21984 : if( !fd_bpf_upgradeable_loader_state_is_program( &program_account_state ) ) {
101 8859 : return -1;
102 8859 : }
103 :
104 13125 : fd_pubkey_t * programdata_address = &program_account_state.inner.program.programdata_address;
105 :
106 13125 : if( fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, programdata_address, programdata_acc ) != FD_ACC_MGR_SUCCESS ) {
107 1392 : return -1;
108 1392 : }
109 :
110 11733 : fd_bincode_decode_ctx_t ctx_programdata = {
111 11733 : .data = programdata_acc->const_data,
112 11733 : .dataend = programdata_acc->const_data + programdata_acc->const_meta->dlen,
113 11733 : .valloc = fd_scratch_virtual(),
114 11733 : };
115 :
116 11733 : fd_bpf_upgradeable_loader_state_t program_data_account_state = {0};
117 11733 : if( FD_UNLIKELY( fd_bpf_upgradeable_loader_state_decode( &program_data_account_state, &ctx_programdata ) ) ) {
118 7119 : return -1;
119 7119 : }
120 :
121 4614 : *program_data = programdata_acc->const_data + PROGRAMDATA_METADATA_SIZE;
122 4614 : *program_data_len = programdata_acc->const_meta->dlen - PROGRAMDATA_METADATA_SIZE;
123 4614 : return 0;
124 11733 : }
125 :
126 : static int
127 : fd_bpf_get_executable_program_content_for_v1_v2_loaders( fd_borrowed_account_t * program_acc,
128 : uchar const ** program_data,
129 61464 : ulong * program_data_len ) {
130 61464 : *program_data = program_acc->const_data;
131 61464 : *program_data_len = program_acc->const_meta->dlen;
132 61464 : return 0;
133 61464 : }
134 :
135 : void
136 : fd_bpf_get_sbpf_versions( uint * sbpf_min_version,
137 : uint * sbpf_max_version,
138 67626 : fd_exec_slot_ctx_t const * slot_ctx ) {
139 67626 : int disable_v0 = FD_FEATURE_ACTIVE( slot_ctx, disable_sbpf_v0_execution );
140 67626 : int reenable_v0 = FD_FEATURE_ACTIVE( slot_ctx, reenable_sbpf_v0_execution );
141 67626 : int enable_v0 = !disable_v0 || reenable_v0;
142 67626 : int enable_v1 = FD_FEATURE_ACTIVE( slot_ctx, enable_sbpf_v1_deployment_and_execution );
143 67626 : int enable_v2 = FD_FEATURE_ACTIVE( slot_ctx, enable_sbpf_v2_deployment_and_execution );
144 67626 : int enable_v3 = FD_FEATURE_ACTIVE( slot_ctx, enable_sbpf_v3_deployment_and_execution );
145 :
146 67626 : *sbpf_min_version = enable_v0 ? FD_SBPF_V0 : FD_SBPF_V3;
147 67626 : if( enable_v3 ) {
148 0 : *sbpf_max_version = FD_SBPF_V3;
149 67626 : } else if( enable_v2 ) {
150 0 : *sbpf_max_version = FD_SBPF_V2;
151 67626 : } else if( enable_v1 ) {
152 0 : *sbpf_max_version = FD_SBPF_V1;
153 67626 : } else {
154 67626 : *sbpf_max_version = FD_SBPF_V0;
155 67626 : }
156 67626 : }
157 :
158 : int
159 : fd_bpf_create_bpf_program_cache_entry( fd_exec_slot_ctx_t * slot_ctx,
160 120486 : fd_borrowed_account_t * program_acc ) {
161 120486 : FD_SCRATCH_SCOPE_BEGIN {
162 :
163 120486 : fd_pubkey_t * program_pubkey = program_acc->pubkey;
164 :
165 120486 : fd_funk_t * funk = slot_ctx->acc_mgr->funk;
166 120486 : fd_funk_txn_t * funk_txn = slot_ctx->funk_txn;
167 120486 : fd_funk_rec_key_t id = fd_acc_mgr_cache_key( program_pubkey );
168 :
169 120486 : uchar const * program_data = NULL;
170 120486 : ulong program_data_len = 0UL;
171 :
172 : /* For v3 loaders, deserialize the program account and lookup the
173 : programdata account. Deserialize the programdata account. */
174 :
175 120486 : int res;
176 120486 : if( !memcmp( program_acc->const_meta->info.owner, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) ) {
177 56079 : res = fd_bpf_get_executable_program_content_for_upgradeable_loader( slot_ctx, program_acc, &program_data, &program_data_len );
178 64407 : } else if( !memcmp( program_acc->const_meta->info.owner, fd_solana_bpf_loader_v4_program_id.key, sizeof(fd_pubkey_t) ) ) {
179 2943 : res = fd_bpf_get_executable_program_content_for_v4_loader( program_acc, &program_data, &program_data_len );
180 61464 : } else {
181 61464 : res = fd_bpf_get_executable_program_content_for_v1_v2_loaders( program_acc, &program_data, &program_data_len );
182 61464 : }
183 :
184 120486 : if( res ) {
185 53784 : return -1;
186 53784 : }
187 :
188 66702 : fd_sbpf_elf_info_t elf_info = {0};
189 66702 : uint min_sbpf_version, max_sbpf_version;
190 66702 : fd_bpf_get_sbpf_versions( &min_sbpf_version, &max_sbpf_version, slot_ctx );
191 66702 : if( fd_sbpf_elf_peek( &elf_info, program_data, program_data_len, /* deploy checks */ 0, min_sbpf_version, max_sbpf_version ) == NULL ) {
192 64329 : FD_LOG_DEBUG(( "fd_sbpf_elf_peek() failed: %s", fd_sbpf_strerror() ));
193 64329 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
194 64329 : }
195 :
196 2373 : int funk_err = FD_FUNK_SUCCESS;
197 2373 : fd_funk_rec_t const * existing_rec = fd_funk_rec_query_global( funk, funk_txn, &id, NULL );
198 2373 : fd_funk_rec_t * rec = fd_funk_rec_write_prepare( funk, funk_txn, &id, fd_sbpf_validated_program_footprint( &elf_info ), 1, existing_rec, &funk_err );
199 2373 : if( rec == NULL || funk_err != FD_FUNK_SUCCESS ) {
200 0 : return -1;
201 0 : }
202 :
203 2373 : void * val = fd_funk_val( rec, fd_funk_wksp( funk ) );
204 2373 : fd_sbpf_validated_program_t * validated_prog = fd_sbpf_validated_program_new( val, &elf_info );
205 :
206 2373 : ulong prog_align = fd_sbpf_program_align();
207 2373 : ulong prog_footprint = fd_sbpf_program_footprint( &elf_info );
208 2373 : fd_sbpf_program_t * prog = fd_sbpf_program_new( fd_scratch_alloc( prog_align, prog_footprint ), &elf_info, validated_prog->rodata );
209 2373 : if( FD_UNLIKELY( !prog ) ) {
210 0 : return -1;
211 0 : }
212 :
213 : /* Allocate syscalls */
214 :
215 2373 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_scratch_alloc( fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() ) );
216 2373 : if( FD_UNLIKELY( !syscalls ) ) {
217 0 : FD_LOG_ERR(( "Call to fd_sbpf_syscalls_new() failed" ));
218 0 : }
219 :
220 2373 : fd_vm_syscall_register_slot( syscalls, slot_ctx, 0 );
221 :
222 : /* Load program. */
223 :
224 2373 : if( FD_UNLIKELY( 0!=fd_sbpf_program_load( prog, program_data, program_data_len, syscalls, false ) ) ) {
225 : /* Remove pending funk record */
226 339 : FD_LOG_DEBUG(( "fd_sbpf_program_load() failed: %s", fd_sbpf_strerror() ));
227 339 : fd_funk_rec_remove( funk, rec, funk_txn->xid.ul[0] );
228 339 : return -1;
229 339 : }
230 :
231 : /* Validate the program. */
232 :
233 2034 : fd_vm_t _vm[ 1UL ];
234 2034 : fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
235 2034 : if( FD_UNLIKELY( !vm ) ) {
236 0 : FD_LOG_ERR(( "fd_vm_new() or fd_vm_join() failed" ));
237 0 : }
238 2034 : fd_exec_instr_ctx_t dummy_instr_ctx = {0};
239 2034 : dummy_instr_ctx.slot_ctx = slot_ctx;
240 2034 : vm = fd_vm_init( vm,
241 2034 : &dummy_instr_ctx,
242 2034 : 0UL,
243 2034 : 0UL,
244 2034 : prog->rodata,
245 2034 : prog->rodata_sz,
246 2034 : prog->text,
247 2034 : prog->text_cnt,
248 2034 : prog->text_off,
249 2034 : prog->text_sz,
250 2034 : prog->entry_pc,
251 2034 : prog->calldests,
252 2034 : elf_info.sbpf_version,
253 2034 : NULL,
254 2034 : NULL,
255 2034 : NULL,
256 2034 : NULL,
257 2034 : 0U,
258 2034 : NULL,
259 2034 : 0,
260 2034 : FD_FEATURE_ACTIVE( slot_ctx, bpf_account_data_direct_mapping ) );
261 :
262 2034 : if( FD_UNLIKELY( !vm ) ) {
263 0 : FD_LOG_ERR(( "fd_vm_init() failed" ));
264 0 : }
265 :
266 2034 : res = fd_vm_validate( vm );
267 2034 : if( FD_UNLIKELY( res ) ) {
268 : /* Remove pending funk record */
269 228 : FD_LOG_DEBUG(( "fd_vm_validate() failed" ));
270 228 : fd_funk_rec_remove( funk, rec, 0UL );
271 228 : return -1;
272 228 : }
273 :
274 1806 : fd_memcpy( validated_prog->calldests_shmem, prog->calldests_shmem, fd_sbpf_calldests_footprint(prog->rodata_sz/8UL) );
275 1806 : validated_prog->calldests = fd_sbpf_calldests_join( validated_prog->calldests_shmem );
276 :
277 1806 : validated_prog->entry_pc = prog->entry_pc;
278 1806 : validated_prog->last_updated_slot = slot_ctx->slot_bank.slot;
279 1806 : validated_prog->text_off = prog->text_off;
280 1806 : validated_prog->text_cnt = prog->text_cnt;
281 1806 : validated_prog->text_sz = prog->text_sz;
282 1806 : validated_prog->rodata_sz = prog->rodata_sz;
283 :
284 1806 : return 0;
285 120486 : } FD_SCRATCH_SCOPE_END;
286 120486 : }
287 :
288 : static void FD_FN_UNUSED
289 : fd_bpf_scan_task( void * tpool,
290 : ulong t0 FD_PARAM_UNUSED, ulong t1 FD_PARAM_UNUSED,
291 : void * args FD_PARAM_UNUSED,
292 : void * reduce FD_PARAM_UNUSED, ulong stride FD_PARAM_UNUSED,
293 : ulong l0 FD_PARAM_UNUSED, ulong l1 FD_PARAM_UNUSED,
294 : ulong m0, ulong m1 FD_PARAM_UNUSED,
295 0 : ulong n0 FD_PARAM_UNUSED, ulong n1 FD_PARAM_UNUSED ) {
296 0 : fd_funk_rec_t const * recs = ((fd_funk_rec_t const **)tpool)[m0];
297 0 : fd_exec_slot_ctx_t * slot_ctx = (fd_exec_slot_ctx_t *)args;
298 0 : uchar * is_bpf_program = (uchar *)reduce + m0;
299 :
300 0 : if( !fd_funk_key_is_acc( recs->pair.key ) ) {
301 0 : *is_bpf_program = 0;
302 0 : return;
303 0 : }
304 :
305 0 : fd_pubkey_t const * pubkey = fd_type_pun_const( recs->pair.key[0].uc );
306 :
307 0 : FD_BORROWED_ACCOUNT_DECL( exec_rec );
308 0 : if( fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, pubkey, exec_rec ) != FD_ACC_MGR_SUCCESS ) {
309 0 : return;
310 0 : }
311 :
312 0 : if( memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_deprecated_program_id.key, sizeof(fd_pubkey_t) ) &&
313 0 : memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_program_id.key, sizeof(fd_pubkey_t) ) &&
314 0 : memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) &&
315 0 : memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_v4_program_id.key, sizeof(fd_pubkey_t) ) ) {
316 0 : *is_bpf_program = 0;
317 0 : } else {
318 0 : *is_bpf_program = 1;
319 0 : }
320 0 : }
321 :
322 : int
323 : fd_bpf_scan_and_create_bpf_program_cache_entry_tpool( fd_exec_slot_ctx_t * slot_ctx,
324 : fd_funk_txn_t * funk_txn,
325 0 : fd_tpool_t * tpool ) {
326 0 : long elapsed_ns = -fd_log_wallclock();
327 0 : fd_funk_t * funk = slot_ctx->acc_mgr->funk;
328 0 : ulong cached_cnt = 0;
329 :
330 : /* Use random-ish xid to avoid concurrency issues */
331 0 : fd_funk_txn_xid_t cache_xid = fd_funk_generate_xid();
332 :
333 0 : fd_funk_txn_t * cache_txn = fd_funk_txn_prepare( funk, slot_ctx->funk_txn, &cache_xid, 1 );
334 0 : if( !cache_txn ) {
335 0 : FD_LOG_ERR(( "fd_funk_txn_prepare() failed" ));
336 0 : return -1;
337 0 : }
338 :
339 0 : fd_funk_txn_t * parent_txn = slot_ctx->funk_txn;
340 0 : slot_ctx->funk_txn = cache_txn;
341 :
342 0 : fd_funk_rec_t const * rec = fd_funk_txn_first_rec( funk, funk_txn );
343 0 : while( rec!=NULL ) {
344 0 : FD_SCRATCH_SCOPE_BEGIN {
345 0 : fd_funk_rec_t const * * recs = fd_scratch_alloc( alignof(fd_funk_rec_t const *), 65536UL * sizeof(fd_funk_rec_t const *) );
346 0 : uchar * is_bpf_program = fd_scratch_alloc( 8UL, 65536UL * sizeof(uchar) );
347 :
348 : /* Make a list of rec ptrs to process */
349 0 : ulong rec_cnt = 0;
350 0 : for( ; NULL != rec; rec = fd_funk_txn_next_rec( funk, rec ) ) {
351 0 : if( rec->flags & FD_FUNK_REC_FLAG_ERASE ) continue;
352 0 : recs[ rec_cnt ] = rec;
353 :
354 0 : if( rec_cnt==65536UL ) {
355 0 : break;
356 0 : }
357 :
358 0 : rec_cnt++;
359 0 : }
360 :
361 0 : fd_tpool_exec_all_block( tpool, 0, fd_tpool_worker_cnt( tpool ), fd_bpf_scan_task, recs, slot_ctx, is_bpf_program, 1, 0, rec_cnt );
362 :
363 0 : for( ulong i = 0; i<rec_cnt; i++ ) {
364 0 : if( !is_bpf_program[ i ] ) {
365 0 : continue;
366 0 : }
367 :
368 0 : fd_pubkey_t const * pubkey = fd_type_pun_const( recs[i]->pair.key[0].uc );
369 0 : int res = fd_bpf_check_and_create_bpf_program_cache_entry( slot_ctx, funk_txn, pubkey );
370 0 : if( res==0 ) {
371 0 : cached_cnt++;
372 0 : }
373 0 : }
374 :
375 0 : } FD_SCRATCH_SCOPE_END;
376 0 : }
377 :
378 0 : if( fd_funk_txn_publish_into_parent( funk, cache_txn, 1 ) != FD_FUNK_SUCCESS ) {
379 0 : FD_LOG_ERR(( "fd_funk_txn_publish_into_parent() failed" ));
380 0 : return -1;
381 0 : }
382 :
383 0 : slot_ctx->funk_txn = parent_txn;
384 :
385 0 : elapsed_ns += fd_log_wallclock();
386 :
387 0 : FD_LOG_NOTICE(( "loaded program cache - entries: %lu, elapsed_seconds: %ld", cached_cnt, elapsed_ns/(long)1e9 ));
388 :
389 0 : return 0;
390 0 : }
391 :
392 : int
393 : fd_bpf_scan_and_create_bpf_program_cache_entry( fd_exec_slot_ctx_t * slot_ctx,
394 407859 : fd_funk_txn_t * funk_txn ) {
395 407859 : fd_funk_t * funk = slot_ctx->acc_mgr->funk;
396 407859 : ulong cnt = 0;
397 :
398 : /* Use random-ish xid to avoid concurrency issues */
399 407859 : fd_funk_txn_xid_t cache_xid = fd_funk_generate_xid();
400 :
401 407859 : fd_funk_txn_t * cache_txn = fd_funk_txn_prepare( funk, slot_ctx->funk_txn, &cache_xid, 1 );
402 407859 : if( !cache_txn ) {
403 0 : FD_LOG_ERR(( "fd_funk_txn_prepare() failed" ));
404 0 : return -1;
405 0 : }
406 :
407 407859 : fd_funk_txn_t * parent_txn = slot_ctx->funk_txn;
408 407859 : slot_ctx->funk_txn = cache_txn;
409 :
410 407859 : for (fd_funk_rec_t const *rec = fd_funk_txn_first_rec( funk, funk_txn );
411 1137561 : NULL != rec;
412 729702 : rec = fd_funk_txn_next_rec( funk, rec )) {
413 729702 : if( !fd_funk_key_is_acc( rec->pair.key ) || ( rec->flags & FD_FUNK_REC_FLAG_ERASE ) ) {
414 0 : continue;
415 0 : }
416 :
417 729702 : fd_pubkey_t const * program_pubkey = fd_type_pun_const( rec->pair.key[0].uc );
418 :
419 729702 : int res = fd_bpf_check_and_create_bpf_program_cache_entry( slot_ctx,
420 729702 : funk_txn,
421 729702 : program_pubkey );
422 :
423 729702 : if( res==0 ) {
424 1806 : cnt++;
425 1806 : }
426 729702 : }
427 :
428 407859 : FD_LOG_DEBUG(( "loaded program cache: %lu", cnt));
429 :
430 407859 : if( fd_funk_txn_publish_into_parent( funk, cache_txn, 1 ) != FD_FUNK_SUCCESS ) {
431 0 : FD_LOG_ERR(( "fd_funk_txn_publish_into_parent() failed" ));
432 0 : return -1;
433 0 : }
434 :
435 407859 : slot_ctx->funk_txn = parent_txn;
436 407859 : return 0;
437 407859 : }
438 :
439 : int
440 : fd_bpf_check_and_create_bpf_program_cache_entry( fd_exec_slot_ctx_t * slot_ctx,
441 : fd_funk_txn_t * funk_txn,
442 729702 : fd_pubkey_t const * pubkey ) {
443 729702 : FD_BORROWED_ACCOUNT_DECL( exec_rec );
444 729702 : if( fd_acc_mgr_view( slot_ctx->acc_mgr, funk_txn, pubkey, exec_rec ) != FD_ACC_MGR_SUCCESS ) {
445 13641 : return -1;
446 13641 : }
447 :
448 716061 : if( memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_deprecated_program_id.key, sizeof(fd_pubkey_t) ) &&
449 716061 : memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_program_id.key, sizeof(fd_pubkey_t) ) &&
450 716061 : memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) &&
451 716061 : memcmp( exec_rec->const_meta->info.owner, fd_solana_bpf_loader_v4_program_id.key, sizeof(fd_pubkey_t) ) ) {
452 595575 : return -1;
453 595575 : }
454 :
455 120486 : if( fd_bpf_create_bpf_program_cache_entry( slot_ctx, exec_rec ) != 0 ) {
456 118680 : return -1;
457 118680 : }
458 :
459 1806 : return 0;
460 120486 : }
461 :
462 : int
463 : fd_bpf_load_cache_entry( fd_exec_slot_ctx_t const * slot_ctx,
464 : fd_pubkey_t const * program_pubkey,
465 2004 : fd_sbpf_validated_program_t ** valid_prog ) {
466 2004 : fd_funk_t * funk = slot_ctx->acc_mgr->funk;
467 2004 : fd_funk_txn_t * funk_txn = slot_ctx->funk_txn;
468 2004 : fd_funk_rec_key_t id = fd_acc_mgr_cache_key( program_pubkey );
469 :
470 2004 : fd_funk_rec_t const * rec = fd_funk_rec_query_global(funk, funk_txn, &id, NULL);
471 :
472 2004 : if( FD_UNLIKELY( !rec || !!( rec->flags & FD_FUNK_REC_FLAG_ERASE ) ) ) {
473 975 : return -1;
474 975 : }
475 :
476 1029 : void const * data = fd_funk_val_const( rec, fd_funk_wksp(funk) );
477 :
478 : /* TODO: magic check */
479 :
480 1029 : *valid_prog = (fd_sbpf_validated_program_t *)data;
481 :
482 1029 : return 0;
483 2004 : }
|