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: 181 259 69.9 %
Date: 2026-10-22 18:10:43 Functions: 5 495 1.0 %

          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        2610 : #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         622 : #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        1307 : #define FD_BPF_INSTR_UPGRADE                  (3U)
      65        1415 : #define FD_BPF_INSTR_SET_AUTHORITY            (4U)
      66        1779 : #define FD_BPF_INSTR_CLOSE                    (5U)
      67         762 : #define FD_BPF_INSTR_EXTEND_PROGRAM           (6U)
      68        2031 : #define FD_BPF_INSTR_SET_AUTHORITY_CHECKED    (7U)
      69        2962 : #define FD_BPF_INSTR_MIGRATE                  (8U)
      70         597 : #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        8044 : #define FD_BPF_STATE_UNINITIALIZED (0U)
     124        9182 : #define FD_BPF_STATE_BUFFER        (1U)
     125       58464 : #define FD_BPF_STATE_PROGRAM       (2U)
     126       14288 : #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        3707 :                            ulong                  data_sz ) {
     178        3707 :   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        3707 :   ulong const   _payload_sz = fd_ulong_min( data_sz, FD_TXN_MTU_V0 );
     182        3707 :   ulong         _i          = 0UL;
     183             : 
     184        5727 : # define CHECK( cond )   { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
     185        5727 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
     186        5676 : # define INC( n )        (_i += (ulong)(n))
     187        3707 : # define CURSOR          (_payload+_i)
     188             : 
     189        3707 :   CHECK_LEFT( 4UL );
     190        3705 :   uint disc = FD_LOAD( uint, CURSOR ); INC( 4UL );
     191        3705 :   out->discriminant = disc;
     192             : 
     193        3705 :   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         298 :   case FD_BPF_INSTR_EXTEND_PROGRAM_CHECKED: {
     220         298 :     fd_bpf_instruction_extend_program_checked_t * e = &out->inner.extend_program_checked;
     221         298 :     CHECK_LEFT( 4UL );
     222         298 :     e->additional_bytes = FD_LOAD( uint, CURSOR ); INC( 4UL );
     223         298 :     return 0;
     224         298 :   }
     225             : 
     226         311 :   case FD_BPF_INSTR_INITIALIZE_BUFFER:
     227         808 :   case FD_BPF_INSTR_UPGRADE:
     228        1111 :   case FD_BPF_INSTR_SET_AUTHORITY:
     229        1445 :   case FD_BPF_INSTR_CLOSE:
     230        1738 :   case FD_BPF_INSTR_SET_AUTHORITY_CHECKED:
     231        2350 :   case FD_BPF_INSTR_MIGRATE:
     232        2350 :     return 0;
     233             : 
     234           0 :   default: return -1;
     235        3705 :   }
     236             : 
     237        3705 : # undef CHECK
     238        3705 : # undef CHECK_LEFT
     239        3705 : # undef INC
     240        3705 : # undef CURSOR
     241        3705 : }
     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       53758 :                      ulong            data_sz ) {
     330       53758 :   uchar const * _payload    = data;
     331       53758 :   ulong const   _payload_sz = data_sz;
     332       53758 :   ulong         _i          = 0UL;
     333             : 
     334      142468 : # define CHECK( cond )   { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
     335      123850 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
     336      122292 : # define INC( n )        (_i += (ulong)(n))
     337       56345 : # define CURSOR          (_payload+_i)
     338             : 
     339       53758 :   CHECK_LEFT( 4UL );
     340       53494 :   uint disc = FD_LOAD( uint, CURSOR ); INC( 4UL );
     341       53494 :   out->discriminant = disc;
     342             : 
     343       53494 :   switch( disc ) {
     344             : 
     345        7289 :   case FD_BPF_STATE_UNINITIALIZED:
     346        7289 :     return 0;
     347             : 
     348        6406 :   case FD_BPF_STATE_BUFFER: {
     349        6406 :     fd_bpf_state_buffer_t * b = &out->inner.buffer;
     350        6406 :     CHECK_LEFT( 1UL ); uchar tag = *CURSOR; INC( 1UL );
     351        6328 :     CHECK( tag<=1 );
     352        5002 :     b->has_authority_address = tag;
     353        5002 :     if( tag ) {
     354        4541 :       CHECK_LEFT( 32UL );
     355        4402 :       fd_memcpy( b->authority_address.key, CURSOR, 32UL ); INC( 32UL );
     356        4402 :     } else {
     357         461 :       fd_memset( b->authority_address.key, 0, 32UL );
     358         461 :     }
     359        4863 :     return 0;
     360        5002 :   }
     361             : 
     362       25596 :   case FD_BPF_STATE_PROGRAM: {
     363       25596 :     fd_bpf_state_program_t * p = &out->inner.program;
     364       25596 :     CHECK_LEFT( 32UL );
     365       24883 :     fd_memcpy( p->programdata_address.key, CURSOR, 32UL ); INC( 32UL );
     366       24883 :     return 0;
     367       25596 :   }
     368             : 
     369       12543 :   case FD_BPF_STATE_PROGRAM_DATA: {
     370       12543 :     fd_bpf_state_program_data_t * pd = &out->inner.program_data;
     371       12543 :     CHECK_LEFT( 8UL ); pd->slot = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     372       12453 :     CHECK_LEFT( 1UL ); uchar tag = *CURSOR; INC( 1UL );
     373       12290 :     CHECK( tag<=1 );
     374       12188 :     pd->has_upgrade_authority_address = tag;
     375       12188 :     if( tag ) {
     376        8553 :       CHECK_LEFT( 32UL );
     377        8442 :       fd_memcpy( pd->upgrade_authority_address.key, CURSOR, 32UL ); INC( 32UL );
     378        8442 :     } else {
     379        3635 :       fd_memset( pd->upgrade_authority_address.key, 0, 32UL );
     380        3635 :     }
     381       12077 :     return 0;
     382       12188 :   }
     383             : 
     384        1682 :   default: return -1;
     385       53494 :   }
     386             : 
     387       53494 : # undef CHECK
     388       53494 : # undef CHECK_LEFT
     389       53494 : # undef INC
     390       53494 : # undef CURSOR
     391       53494 : }
     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        1054 :                      ulong *                out_sz ) {
     403        1054 :   uchar * const _payload    = buf;
     404        1054 :   ulong const   _payload_sz = bufsz;
     405        1054 :   ulong         _i          = 0UL;
     406             : 
     407        3158 : # define CHECK_LEFT( n ) { if( FD_UNLIKELY( (n)>(_payload_sz-_i) ) ) { return -1; } }
     408        3158 : # define INC( n )        (_i += (ulong)(n))
     409        1640 : # define CURSOR          (_payload+_i)
     410             : 
     411        1054 :   CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, in->discriminant ); INC( 4UL );
     412             : 
     413        1054 :   switch( in->discriminant ) {
     414             : 
     415         141 :   case FD_BPF_STATE_UNINITIALIZED:
     416         141 :     break;
     417             : 
     418         275 :   case FD_BPF_STATE_BUFFER: {
     419         275 :     fd_bpf_state_buffer_t const * b = &in->inner.buffer;
     420         275 :     CHECK_LEFT( 1UL ); *CURSOR = (uchar)( !!b->has_authority_address ); INC( 1UL );
     421         275 :     if( b->has_authority_address ) {
     422         275 :       CHECK_LEFT( 32UL );
     423         275 :       fd_memcpy( CURSOR, b->authority_address.key, 32UL ); INC( 32UL );
     424         275 :     }
     425         275 :     break;
     426         275 :   }
     427             : 
     428         275 :   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         464 :   case FD_BPF_STATE_PROGRAM_DATA: {
     436         464 :     fd_bpf_state_program_data_t const * pd = &in->inner.program_data;
     437         464 :     CHECK_LEFT( 8UL ); FD_STORE( ulong, CURSOR, pd->slot ); INC( 8UL );
     438         464 :     CHECK_LEFT( 1UL ); *CURSOR = (uchar)( !!pd->has_upgrade_authority_address ); INC( 1UL );
     439         464 :     if( pd->has_upgrade_authority_address ) {
     440         452 :       CHECK_LEFT( 32UL );
     441         452 :       fd_memcpy( CURSOR, pd->upgrade_authority_address.key, 32UL ); INC( 32UL );
     442         452 :     }
     443         464 :     break;
     444         464 :   }
     445             : 
     446         464 :   default: return -1;
     447        1054 :   }
     448             : 
     449        1054 :   *out_sz = _i;
     450             : 
     451        1054 : # undef CHECK_LEFT
     452        1054 : # undef INC
     453        1054 : # undef CURSOR
     454             : 
     455        1054 :   return 0;
     456        1054 : }
     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        1352 : fd_bpf_state_size( fd_bpf_state_t const * in ) {
     463        1352 :   switch( in->discriminant ) {
     464         141 :     case FD_BPF_STATE_UNINITIALIZED: return 4UL;
     465         574 :     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         464 :     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        1352 :   }
     470        1352 : }
     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 */

Generated by: LCOV version 1.14