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