LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_bpf_loader_program.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 148 259 57.1 %
Date: 2026-07-01 06:01:22 Functions: 7 425 1.6 %

          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 */

Generated by: LCOV version 1.14