Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_program_fd_bpf_loader_program_h
2 : #define HEADER_fd_src_flamenco_runtime_program_fd_bpf_loader_program_h
3 :
4 : /* fd_bpf_loader_v3_program.h is the third version of the BPF loader
5 : program.
6 :
7 : Address: BPFLoaderUpgradeab1e11111111111111111111111 */
8 :
9 : #include "../../fd_flamenco_base.h"
10 : #include "../../accdb/fd_accdb.h"
11 : #include "../../progcache/fd_progcache_base.h"
12 :
13 : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/programs/bpf_loader/src/lib.rs#L67-L69 */
14 : #define DEFAULT_LOADER_COMPUTE_UNITS (570UL )
15 : #define DEPRECATED_LOADER_COMPUTE_UNITS (1140UL)
16 : #define UPGRADEABLE_LOADER_COMPUTE_UNITS (2370UL)
17 :
18 : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/sdk/program/src/bpf_loader_upgradeable.rs#L29-L120 */
19 3 : #define SIZE_OF_PROGRAM (36UL ) /* UpgradeableLoaderState::size_of_program() */
20 9 : #define BUFFER_METADATA_SIZE (37UL ) /* UpgradeableLoaderState::size_of_buffer_metadata() */
21 147 : #define PROGRAMDATA_METADATA_SIZE (45UL ) /* UpgradeableLoaderState::size_of_programdata_metadata() */
22 9 : #define SIZE_OF_UNINITIALIZED (4UL ) /* UpgradeableLoaderState::size_of_uninitialized() */
23 :
24 : /* InstructionError conversions
25 : https://github.com/anza-xyz/agave/blob/ced98f1ebe73f7e9691308afa757323003ff744f/sdk/program/src/program_error.rs#L127-L160 */
26 51 : #define BUILTIN_BIT_SHIFT (32UL)
27 :
28 0 : #define CUSTOM_ZERO ((1UL) << BUILTIN_BIT_SHIFT)
29 0 : #define INVALID_ARGUMENT ((2UL) << BUILTIN_BIT_SHIFT)
30 0 : #define INVALID_INSTRUCTION_DATA ((3UL) << BUILTIN_BIT_SHIFT)
31 0 : #define INVALID_ACCOUNT_DATA ((4UL) << BUILTIN_BIT_SHIFT)
32 0 : #define ACCOUNT_DATA_TOO_SMALL ((5UL) << BUILTIN_BIT_SHIFT)
33 0 : #define INSUFFICIENT_FUNDS ((6UL) << BUILTIN_BIT_SHIFT)
34 0 : #define INCORRECT_PROGRAM_ID ((7UL) << BUILTIN_BIT_SHIFT)
35 0 : #define MISSING_REQUIRED_SIGNATURES ((8UL) << BUILTIN_BIT_SHIFT)
36 0 : #define ACCOUNT_ALREADY_INITIALIZED ((9UL) << BUILTIN_BIT_SHIFT)
37 0 : #define UNINITIALIZED_ACCOUNT ((10UL) << BUILTIN_BIT_SHIFT)
38 0 : #define NOT_ENOUGH_ACCOUNT_KEYS ((11UL) << BUILTIN_BIT_SHIFT)
39 0 : #define ACCOUNT_BORROW_FAILED ((12UL) << BUILTIN_BIT_SHIFT)
40 0 : #define MAX_SEED_LENGTH_EXCEEDED ((13UL) << BUILTIN_BIT_SHIFT)
41 0 : #define INVALID_SEEDS ((14UL) << BUILTIN_BIT_SHIFT)
42 0 : #define BORSH_IO_ERROR ((15UL) << BUILTIN_BIT_SHIFT)
43 0 : #define ACCOUNT_NOT_RENT_EXEMPT ((16UL) << BUILTIN_BIT_SHIFT)
44 0 : #define UNSUPPORTED_SYSVAR ((17UL) << BUILTIN_BIT_SHIFT)
45 0 : #define ILLEGAL_OWNER ((18UL) << BUILTIN_BIT_SHIFT)
46 0 : #define MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED ((19UL) << BUILTIN_BIT_SHIFT)
47 0 : #define INVALID_ACCOUNT_DATA_REALLOC ((20UL) << BUILTIN_BIT_SHIFT)
48 0 : #define MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED ((21UL) << BUILTIN_BIT_SHIFT)
49 0 : #define BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS ((22UL) << BUILTIN_BIT_SHIFT)
50 0 : #define INVALID_ACCOUNT_OWNER ((23UL) << BUILTIN_BIT_SHIFT)
51 0 : #define ARITHMETIC_OVERFLOW ((24UL) << BUILTIN_BIT_SHIFT)
52 0 : #define IMMUTABLE ((25UL) << BUILTIN_BIT_SHIFT)
53 0 : #define INCORRECT_AUTHORITY ((26UL) << BUILTIN_BIT_SHIFT)
54 :
55 : /* UpgradeableLoaderInstruction wire format (u32 discriminant).
56 :
57 : https://github.com/anza-xyz/agave/blob/v2.2.6/sdk/program/src/bpf_loader_upgradeable.rs */
58 :
59 0 : #define FD_BPF_INSTR_INITIALIZE_BUFFER (0U)
60 0 : #define FD_BPF_INSTR_WRITE (1U)
61 0 : #define FD_BPF_INSTR_DEPLOY_WITH_MAX_DATA_LEN (2U)
62 0 : #define FD_BPF_INSTR_UPGRADE (3U)
63 0 : #define FD_BPF_INSTR_SET_AUTHORITY (4U)
64 24 : #define FD_BPF_INSTR_CLOSE (5U)
65 0 : #define FD_BPF_INSTR_EXTEND_PROGRAM (6U)
66 12 : #define FD_BPF_INSTR_SET_AUTHORITY_CHECKED (7U)
67 12 : #define FD_BPF_INSTR_MIGRATE (8U)
68 0 : #define FD_BPF_INSTR_EXTEND_PROGRAM_CHECKED (9U)
69 :
70 : /* SIMD-0431: must extend by at least 10kb
71 : https://github.com/anza-xyz/solana-sdk/blob/loader-v3-interface%40v7.0.0/loader-v3-interface/src/instruction.rs#L18 */
72 0 : #define MINIMUM_EXTEND_PROGRAM_BYTES (10240UL)
73 :
74 : /* Per-variant payload structs.
75 :
76 : The `write` variant uses zero-copy for its `bytes` field: after a
77 : successful decode `bytes` points directly into the caller-owned
78 : instruction buffer, and the caller must keep that buffer alive for
79 : the lifetime of the decoded struct. */
80 :
81 : struct fd_bpf_instruction_write {
82 : uint offset;
83 : uchar const * bytes;
84 : ulong bytes_len;
85 : };
86 : typedef struct fd_bpf_instruction_write fd_bpf_instruction_write_t;
87 :
88 : struct fd_bpf_instruction_deploy_with_max_data_len {
89 : ulong max_data_len;
90 : };
91 : typedef struct fd_bpf_instruction_deploy_with_max_data_len fd_bpf_instruction_deploy_with_max_data_len_t;
92 :
93 : struct fd_bpf_instruction_extend_program {
94 : uint additional_bytes;
95 : };
96 : typedef struct fd_bpf_instruction_extend_program fd_bpf_instruction_extend_program_t;
97 :
98 : struct fd_bpf_instruction_extend_program_checked {
99 : uint additional_bytes;
100 : };
101 : typedef struct fd_bpf_instruction_extend_program_checked fd_bpf_instruction_extend_program_checked_t;
102 :
103 : union fd_bpf_instruction_inner {
104 : fd_bpf_instruction_write_t write;
105 : fd_bpf_instruction_deploy_with_max_data_len_t deploy_with_max_data_len;
106 : fd_bpf_instruction_extend_program_t extend_program;
107 : fd_bpf_instruction_extend_program_checked_t extend_program_checked;
108 : };
109 : typedef union fd_bpf_instruction_inner fd_bpf_instruction_inner_t;
110 :
111 : struct fd_bpf_instruction {
112 : uint discriminant;
113 : fd_bpf_instruction_inner_t inner;
114 : };
115 : typedef struct fd_bpf_instruction fd_bpf_instruction_t;
116 :
117 : /* UpgradeableLoaderState wire format (u32 discriminant).
118 :
119 : https://github.com/anza-xyz/agave/blob/v2.2.6/sdk/program/src/bpf_loader_upgradeable.rs */
120 :
121 24 : #define FD_BPF_STATE_UNINITIALIZED (0U)
122 21 : #define FD_BPF_STATE_BUFFER (1U)
123 42 : #define FD_BPF_STATE_PROGRAM (2U)
124 66 : #define FD_BPF_STATE_PROGRAM_DATA (3U)
125 :
126 : /* State struct field layout MUST be preserved: callers initialize and
127 : read these fields by name (e.g. `state.inner.buffer.has_authority_address`,
128 : `state.inner.program.programdata_address`, etc). */
129 :
130 : struct fd_bpf_state_buffer {
131 : fd_pubkey_t authority_address;
132 : uchar has_authority_address;
133 : };
134 : typedef struct fd_bpf_state_buffer fd_bpf_state_buffer_t;
135 :
136 : struct fd_bpf_state_program {
137 : fd_pubkey_t programdata_address;
138 : };
139 : typedef struct fd_bpf_state_program fd_bpf_state_program_t;
140 :
141 : struct fd_bpf_state_program_data {
142 : ulong slot;
143 : fd_pubkey_t upgrade_authority_address;
144 : uchar has_upgrade_authority_address;
145 : };
146 : typedef struct fd_bpf_state_program_data fd_bpf_state_program_data_t;
147 :
148 : union fd_bpf_state_inner {
149 : fd_bpf_state_buffer_t buffer;
150 : fd_bpf_state_program_t program;
151 : fd_bpf_state_program_data_t program_data;
152 : };
153 : typedef union fd_bpf_state_inner fd_bpf_state_inner_t;
154 :
155 : struct fd_bpf_state {
156 : uint discriminant;
157 : fd_bpf_state_inner_t inner;
158 : };
159 : typedef struct fd_bpf_state fd_bpf_state_t;
160 :
161 : /* fd_bpf_instruction_decode parses a bincode-encoded
162 : UpgradeableLoaderInstruction from [data, data+data_sz).
163 : Variable-length fields (`write.bytes`) point directly into `data`, so
164 : callers must keep that buffer alive. Trailing bytes beyond the parsed
165 : region are accepted (matches Agave's default `allow_trailing_bytes()`).
166 : Returns 0 on success, -1 on malformed input. */
167 :
168 : static inline int
169 : fd_bpf_instruction_decode( fd_bpf_instruction_t * out,
170 : uchar const * data,
171 6 : ulong data_sz ) {
172 6 : uchar const * _payload = data;
173 6 : ulong const _payload_sz = data_sz;
174 6 : ulong _i = 0UL;
175 :
176 6 : # define CHECK( cond ) { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
177 6 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
178 6 : # define INC( n ) (_i += (ulong)(n))
179 6 : # define CURSOR (_payload+_i)
180 :
181 6 : CHECK_LEFT( 4UL );
182 6 : uint disc = FD_LOAD( uint, CURSOR ); INC( 4UL );
183 6 : out->discriminant = disc;
184 :
185 6 : switch( disc ) {
186 :
187 0 : case FD_BPF_INSTR_WRITE: {
188 0 : fd_bpf_instruction_write_t * w = &out->inner.write;
189 0 : CHECK_LEFT( 4UL ); w->offset = FD_LOAD( uint, CURSOR ); INC( 4UL );
190 0 : CHECK_LEFT( 8UL ); w->bytes_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
191 0 : CHECK_LEFT( w->bytes_len );
192 0 : w->bytes = w->bytes_len ? CURSOR : NULL;
193 0 : INC( w->bytes_len );
194 0 : return 0;
195 0 : }
196 :
197 0 : case FD_BPF_INSTR_DEPLOY_WITH_MAX_DATA_LEN: {
198 0 : fd_bpf_instruction_deploy_with_max_data_len_t * d = &out->inner.deploy_with_max_data_len;
199 0 : CHECK_LEFT( 8UL );
200 0 : d->max_data_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
201 0 : return 0;
202 0 : }
203 :
204 0 : case FD_BPF_INSTR_EXTEND_PROGRAM: {
205 0 : fd_bpf_instruction_extend_program_t * e = &out->inner.extend_program;
206 0 : CHECK_LEFT( 4UL );
207 0 : e->additional_bytes = FD_LOAD( uint, CURSOR ); INC( 4UL );
208 0 : return 0;
209 0 : }
210 :
211 0 : case FD_BPF_INSTR_EXTEND_PROGRAM_CHECKED: {
212 0 : fd_bpf_instruction_extend_program_checked_t * e = &out->inner.extend_program_checked;
213 0 : CHECK_LEFT( 4UL );
214 0 : e->additional_bytes = FD_LOAD( uint, CURSOR ); INC( 4UL );
215 0 : return 0;
216 0 : }
217 :
218 0 : case FD_BPF_INSTR_INITIALIZE_BUFFER:
219 0 : case FD_BPF_INSTR_UPGRADE:
220 0 : case FD_BPF_INSTR_SET_AUTHORITY:
221 6 : case FD_BPF_INSTR_CLOSE:
222 6 : case FD_BPF_INSTR_SET_AUTHORITY_CHECKED:
223 6 : case FD_BPF_INSTR_MIGRATE:
224 6 : return 0;
225 :
226 0 : default: return -1;
227 6 : }
228 :
229 6 : # undef CHECK
230 6 : # undef CHECK_LEFT
231 6 : # undef INC
232 6 : # undef CURSOR
233 6 : }
234 :
235 : /* fd_bpf_upgradeable_loader_program_instruction_encode serializes an
236 : UpgradeableLoaderInstruction into [buf, buf+bufsz). On success stores
237 : the number of bytes written to *out_sz and returns 0. Returns -1 on
238 : short buffer or unknown discriminant. */
239 :
240 : static inline int
241 : fd_bpf_instruction_encode( fd_bpf_instruction_t const * in,
242 : uchar * buf,
243 : ulong bufsz,
244 6 : ulong * out_sz ) {
245 6 : uchar * const _payload = buf;
246 6 : ulong const _payload_sz = bufsz;
247 6 : ulong _i = 0UL;
248 :
249 6 : # define CHECK_LEFT( n ) { if( FD_UNLIKELY( (n)>(_payload_sz-_i) ) ) { return -1; } }
250 6 : # define INC( n ) (_i += (ulong)(n))
251 6 : # define CURSOR (_payload+_i)
252 :
253 6 : CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, in->discriminant ); INC( 4UL );
254 :
255 6 : switch( in->discriminant ) {
256 :
257 0 : case FD_BPF_INSTR_WRITE: {
258 0 : fd_bpf_instruction_write_t const * w = &in->inner.write;
259 0 : CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, w->offset ); INC( 4UL );
260 0 : CHECK_LEFT( 8UL ); FD_STORE( ulong, CURSOR, w->bytes_len ); INC( 8UL );
261 0 : if( w->bytes_len ) {
262 0 : CHECK_LEFT( w->bytes_len );
263 0 : fd_memcpy( CURSOR, w->bytes, w->bytes_len );
264 0 : INC( w->bytes_len );
265 0 : }
266 0 : break;
267 0 : }
268 :
269 0 : case FD_BPF_INSTR_DEPLOY_WITH_MAX_DATA_LEN: {
270 0 : fd_bpf_instruction_deploy_with_max_data_len_t const * d = &in->inner.deploy_with_max_data_len;
271 0 : CHECK_LEFT( 8UL );
272 0 : FD_STORE( ulong, CURSOR, d->max_data_len ); INC( 8UL );
273 0 : break;
274 0 : }
275 :
276 0 : case FD_BPF_INSTR_EXTEND_PROGRAM: {
277 0 : fd_bpf_instruction_extend_program_t const * e = &in->inner.extend_program;
278 0 : CHECK_LEFT( 4UL );
279 0 : FD_STORE( uint, CURSOR, e->additional_bytes ); INC( 4UL );
280 0 : break;
281 0 : }
282 :
283 0 : case FD_BPF_INSTR_EXTEND_PROGRAM_CHECKED: {
284 0 : fd_bpf_instruction_extend_program_checked_t const * e = &in->inner.extend_program_checked;
285 0 : CHECK_LEFT( 4UL );
286 0 : FD_STORE( uint, CURSOR, e->additional_bytes ); INC( 4UL );
287 0 : break;
288 0 : }
289 :
290 0 : case FD_BPF_INSTR_INITIALIZE_BUFFER:
291 0 : case FD_BPF_INSTR_UPGRADE:
292 0 : case FD_BPF_INSTR_SET_AUTHORITY:
293 6 : case FD_BPF_INSTR_CLOSE:
294 6 : case FD_BPF_INSTR_SET_AUTHORITY_CHECKED:
295 6 : case FD_BPF_INSTR_MIGRATE:
296 6 : break;
297 :
298 0 : default: return -1;
299 6 : }
300 :
301 6 : *out_sz = _i;
302 :
303 6 : # undef CHECK_LEFT
304 6 : # undef INC
305 6 : # undef CURSOR
306 :
307 6 : return 0;
308 6 : }
309 :
310 : /* fd_bpf_state_decode parses a bincode-encoded
311 : UpgradeableLoaderState from [data, data+data_sz). The output struct
312 : has no variable-length fields, so the decoder performs a fixed-size
313 : copy and does not retain any pointer into `data`. Trailing bytes
314 : beyond the parsed region are accepted (matches Agave's top-level
315 : `bincode::deserialize` which uses `allow_trailing_bytes()`). Returns
316 : 0 on success, -1 on malformed input. */
317 :
318 : static inline int
319 : fd_bpf_state_decode( fd_bpf_state_t * out,
320 : uchar const * data,
321 75 : ulong data_sz ) {
322 75 : uchar const * _payload = data;
323 75 : ulong const _payload_sz = data_sz;
324 75 : ulong _i = 0UL;
325 :
326 216 : # define CHECK( cond ) { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
327 177 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
328 177 : # define INC( n ) (_i += (ulong)(n))
329 75 : # define CURSOR (_payload+_i)
330 :
331 75 : CHECK_LEFT( 4UL );
332 75 : uint disc = FD_LOAD( uint, CURSOR ); INC( 4UL );
333 75 : out->discriminant = disc;
334 :
335 75 : switch( disc ) {
336 :
337 18 : case FD_BPF_STATE_UNINITIALIZED:
338 18 : return 0;
339 :
340 3 : case FD_BPF_STATE_BUFFER: {
341 3 : fd_bpf_state_buffer_t * b = &out->inner.buffer;
342 3 : CHECK_LEFT( 1UL ); uchar tag = *CURSOR; INC( 1UL );
343 3 : CHECK( tag<=1 );
344 3 : b->has_authority_address = tag;
345 3 : if( tag ) {
346 0 : CHECK_LEFT( 32UL );
347 0 : fd_memcpy( b->authority_address.key, CURSOR, 32UL ); INC( 32UL );
348 3 : } else {
349 3 : fd_memset( b->authority_address.key, 0, 32UL );
350 3 : }
351 3 : return 0;
352 3 : }
353 :
354 15 : case FD_BPF_STATE_PROGRAM: {
355 15 : fd_bpf_state_program_t * p = &out->inner.program;
356 15 : CHECK_LEFT( 32UL );
357 15 : fd_memcpy( p->programdata_address.key, CURSOR, 32UL ); INC( 32UL );
358 15 : return 0;
359 15 : }
360 :
361 36 : case FD_BPF_STATE_PROGRAM_DATA: {
362 36 : fd_bpf_state_program_data_t * pd = &out->inner.program_data;
363 36 : CHECK_LEFT( 8UL ); pd->slot = FD_LOAD( ulong, CURSOR ); INC( 8UL );
364 36 : CHECK_LEFT( 1UL ); uchar tag = *CURSOR; INC( 1UL );
365 36 : CHECK( tag<=1 );
366 36 : pd->has_upgrade_authority_address = tag;
367 36 : if( tag ) {
368 12 : CHECK_LEFT( 32UL );
369 12 : fd_memcpy( pd->upgrade_authority_address.key, CURSOR, 32UL ); INC( 32UL );
370 24 : } else {
371 24 : fd_memset( pd->upgrade_authority_address.key, 0, 32UL );
372 24 : }
373 36 : return 0;
374 36 : }
375 :
376 3 : default: return -1;
377 75 : }
378 :
379 75 : # undef CHECK
380 75 : # undef CHECK_LEFT
381 75 : # undef INC
382 75 : # undef CURSOR
383 75 : }
384 :
385 : /* fd_bpf_state_encode serializes an UpgradeableLoaderState into
386 : [buf, buf+bufsz). On success stores the number of bytes written to
387 : *out_sz and returns 0. Returns -1 on short buffer or unknown
388 : discriminant. */
389 :
390 : static inline int
391 : fd_bpf_state_encode( fd_bpf_state_t const * in,
392 : uchar * buf,
393 : ulong bufsz,
394 18 : ulong * out_sz ) {
395 18 : uchar * const _payload = buf;
396 18 : ulong const _payload_sz = bufsz;
397 18 : ulong _i = 0UL;
398 :
399 54 : # define CHECK_LEFT( n ) { if( FD_UNLIKELY( (n)>(_payload_sz-_i) ) ) { return -1; } }
400 54 : # define INC( n ) (_i += (ulong)(n))
401 30 : # define CURSOR (_payload+_i)
402 :
403 18 : CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, in->discriminant ); INC( 4UL );
404 :
405 18 : switch( in->discriminant ) {
406 :
407 0 : case FD_BPF_STATE_UNINITIALIZED:
408 0 : break;
409 :
410 9 : case FD_BPF_STATE_BUFFER: {
411 9 : fd_bpf_state_buffer_t const * b = &in->inner.buffer;
412 9 : CHECK_LEFT( 1UL ); *CURSOR = (uchar)( !!b->has_authority_address ); INC( 1UL );
413 9 : if( b->has_authority_address ) {
414 6 : CHECK_LEFT( 32UL );
415 6 : fd_memcpy( CURSOR, b->authority_address.key, 32UL ); INC( 32UL );
416 6 : }
417 9 : break;
418 9 : }
419 :
420 9 : case FD_BPF_STATE_PROGRAM: {
421 3 : fd_bpf_state_program_t const * p = &in->inner.program;
422 3 : CHECK_LEFT( 32UL );
423 3 : fd_memcpy( CURSOR, p->programdata_address.key, 32UL ); INC( 32UL );
424 3 : break;
425 3 : }
426 :
427 6 : case FD_BPF_STATE_PROGRAM_DATA: {
428 6 : fd_bpf_state_program_data_t const * pd = &in->inner.program_data;
429 6 : CHECK_LEFT( 8UL ); FD_STORE( ulong, CURSOR, pd->slot ); INC( 8UL );
430 6 : CHECK_LEFT( 1UL ); *CURSOR = (uchar)( !!pd->has_upgrade_authority_address ); INC( 1UL );
431 6 : if( pd->has_upgrade_authority_address ) {
432 6 : CHECK_LEFT( 32UL );
433 6 : fd_memcpy( CURSOR, pd->upgrade_authority_address.key, 32UL ); INC( 32UL );
434 6 : }
435 6 : break;
436 6 : }
437 :
438 6 : default: return -1;
439 18 : }
440 :
441 18 : *out_sz = _i;
442 :
443 18 : # undef CHECK_LEFT
444 18 : # undef INC
445 18 : # undef CURSOR
446 :
447 18 : return 0;
448 18 : }
449 :
450 : /* fd_bpf_state_size returns the bincode-exact wire size for
451 : encoding. Returns 0 for unknown discriminants. */
452 :
453 : static inline ulong
454 0 : fd_bpf_state_size( fd_bpf_state_t const * in ) {
455 0 : switch( in->discriminant ) {
456 0 : case FD_BPF_STATE_UNINITIALIZED: return 4UL;
457 0 : case FD_BPF_STATE_BUFFER: return 4UL + 1UL + (in->inner.buffer.has_authority_address ? 32UL : 0UL);
458 0 : case FD_BPF_STATE_PROGRAM: return 4UL + 32UL;
459 0 : case FD_BPF_STATE_PROGRAM_DATA: return 4UL + 8UL + 1UL + (in->inner.program_data.has_upgrade_authority_address ? 32UL : 0UL);
460 0 : default: return 0UL;
461 0 : }
462 0 : }
463 :
464 : FD_PROTOTYPES_BEGIN
465 :
466 : /* Mirrors solana_sdk::transaction_context::BorrowedAccount::get_state()
467 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L965-L969 */
468 :
469 : int
470 : fd_bpf_loader_program_get_state( fd_acc_t const * acc,
471 : fd_bpf_state_t * state );
472 :
473 : int
474 : fd_bpf_loader_program_get_state2( uchar const * data,
475 : ulong data_len,
476 : fd_bpf_state_t * state );
477 :
478 : int
479 : fd_deploy_program( fd_exec_instr_ctx_t * instr_ctx,
480 : uchar const * programdata,
481 : ulong programdata_size,
482 : int disable_sbpf_v0_v1_v2_deployment );
483 :
484 : /* SIMD-0500 finalize gate. Returns
485 : FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA when `feature_active` is
486 : non-zero and the ELF embedded in `programdata` parses as
487 : SBPFv0/v1/v2; FD_EXECUTOR_INSTR_SUCCESS otherwise. */
488 : int
489 : fd_bpf_loader_finalize_v3_check( int feature_active,
490 : uchar const * programdata,
491 : ulong programdata_len );
492 :
493 : int
494 : fd_bpf_execute( fd_exec_instr_ctx_t * instr_ctx,
495 : fd_progcache_rec_t const * program,
496 : uchar is_deprecated );
497 :
498 : int
499 : fd_bpf_loader_program_execute( fd_exec_instr_ctx_t * instr_ctx );
500 :
501 : FD_PROTOTYPES_END
502 :
503 : #endif /* HEADER_fd_src_flamenco_runtime_program_fd_bpf_loader_program_h */
|