LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_system_program.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 157 315 49.8 %
Date: 2026-05-15 07:18:56 Functions: 9 40 22.5 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_program_fd_system_program_h
       2             : #define HEADER_fd_src_flamenco_runtime_program_fd_system_program_h
       3             : 
       4             : /* fd_system_program.h provides hand-written types and zero-copy
       5             :    parsers for Solana's SystemInstruction enum, plus entrypoints for
       6             :    the system program.
       7             : 
       8             :    The decoder produces pointers into the caller-owned instruction
       9             :    buffer for variable-length fields (seeds).  Callers must keep the
      10             :    instruction buffer alive for the lifetime of the decoded struct.
      11             : 
      12             :    https://github.com/anza-xyz/solana-sdk/blob/system-interface%40v3.0.0/system-interface/src/instruction.rs#L92-L299 */
      13             : 
      14             : #include "../../fd_flamenco_base.h"
      15             : #include "../../../ballet/utf8/fd_utf8.h"
      16             : 
      17             : /* Custom error types */
      18             : 
      19          12 : #define FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE              (0)  /* SystemError::AccountAlreadyInUse */
      20           3 : #define FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS    (1)  /* SystemError::ResultWithNegativeLamports */
      21             : #define FD_SYSTEM_PROGRAM_ERR_INVALID_PROGRAM_ID               (2)  /* SystemError::InvalidProgramId */
      22           3 : #define FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN            (3)  /* SystemError::InvalidAccountDataLength */
      23             : #define FD_SYSTEM_PROGRAM_ERR_MAX_SEED_LEN_EXCEEDED            (4)  /* SystemError::MaxSeedLengthExceeded */
      24           0 : #define FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH          (5)  /* SystemError::AddressWithSeedMismatch */
      25           0 : #define FD_SYSTEM_PROGRAM_ERR_NONCE_NO_RECENT_BLOCKHASHES      (6)  /* SystemError::NonceNoRecentBlockhashes */
      26           0 : #define FD_SYSTEM_PROGRAM_ERR_NONCE_BLOCKHASH_NOT_EXPIRED      (7)  /* SystemError::NonceBlockhashNotExpired */
      27             : #define FD_SYSTEM_PROGRAM_ERR_NONCE_UNEXPECTED_BLOCKHASH_VALUE (8)  /* SystemError::NonceUnexpectedBlockhashValue */
      28             : 
      29          12 : #define FD_SYSTEM_PROGRAM_NONCE_DLEN (80UL)
      30             : 
      31             : /* Nonce account state bincode wire format (must match Agave byte-for-byte).
      32             : 
      33             :    https://github.com/anza-xyz/solana-sdk/blob/nonce%40v3.0.0/nonce/src/versions.rs
      34             :    https://github.com/anza-xyz/solana-sdk/blob/nonce%40v3.0.0/nonce/src/state.rs
      35             : 
      36             :    Outer enum `Versions` (4-byte u32 LE discriminant):
      37             :      0 = Legacy(Box<State>)
      38             :      1 = Current(Box<State>)
      39             :    Inner enum `State` (4-byte u32 LE discriminant):
      40             :      0 = Uninitialized       (no payload; total wire size = 8)
      41             :      1 = Initialized(Data)   (payload = 72 bytes; total wire size = 80)
      42             :    Data struct (72 bytes fixed):
      43             :      pubkey authority[32] | hash durable_nonce[32] | u64 lamports_per_signature
      44             : 
      45             :    Agave uses bincode 1.3.3 `DefaultOptions::with_fixint_encoding().
      46             :    allow_trailing_bytes()` via the top-level `bincode::deserialize` helper
      47             :    (TransactionContext::get_state).  Decoders must therefore accept trailing
      48             :    bytes beyond the parsed region. */
      49             : 
      50             : #define FD_NONCE_VERSION_LEGACY         (0U)
      51          30 : #define FD_NONCE_VERSION_CURRENT        (1U)
      52             : 
      53           9 : #define FD_NONCE_STATE_UNINITIALIZED    (0U)
      54         102 : #define FD_NONCE_STATE_INITIALIZED      (1U)
      55             : 
      56           0 : #define FD_NONCE_STATE_UNINITIALIZED_SZ (8UL)
      57          21 : #define FD_NONCE_STATE_INITIALIZED_SZ   (80UL)
      58             : 
      59             : /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L49-L53 */
      60           0 : #define FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN (-1)
      61         183 : #define FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_SYSTEM  (0)
      62         183 : #define FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_NONCE   (1)
      63             : 
      64             : /* SystemInstruction discriminants (wire-format u32 values). */
      65             : 
      66         198 : #define FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT               (0U)
      67           0 : #define FD_SYSTEM_PROGRAM_INSTR_ASSIGN                       (1U)
      68          57 : #define FD_SYSTEM_PROGRAM_INSTR_TRANSFER                     (2U)
      69           0 : #define FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_WITH_SEED     (3U)
      70          18 : #define FD_SYSTEM_PROGRAM_INSTR_ADVANCE_NONCE_ACCOUNT        (4U)
      71           0 : #define FD_SYSTEM_PROGRAM_INSTR_WITHDRAW_NONCE_ACCOUNT       (5U)
      72           9 : #define FD_SYSTEM_PROGRAM_INSTR_INITIALIZE_NONCE_ACCOUNT     (6U)
      73           0 : #define FD_SYSTEM_PROGRAM_INSTR_AUTHORIZE_NONCE_ACCOUNT      (7U)
      74         156 : #define FD_SYSTEM_PROGRAM_INSTR_ALLOCATE                     (8U)
      75           0 : #define FD_SYSTEM_PROGRAM_INSTR_ALLOCATE_WITH_SEED           (9U)
      76           0 : #define FD_SYSTEM_PROGRAM_INSTR_ASSIGN_WITH_SEED             (10U)
      77           0 : #define FD_SYSTEM_PROGRAM_INSTR_TRANSFER_WITH_SEED           (11U)
      78           0 : #define FD_SYSTEM_PROGRAM_INSTR_UPGRADE_NONCE_ACCOUNT        (12U)
      79         246 : #define FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_ALLOW_PREFUND (13U)
      80             : 
      81             : /* Per-variant structs. */
      82             : 
      83             : struct create_account {
      84             :   ulong       lamports;
      85             :   ulong       space;
      86             :   fd_pubkey_t owner;
      87             : };
      88             : typedef struct create_account create_account_t;
      89             : 
      90             : struct create_account_with_seed {
      91             :   fd_pubkey_t   base;
      92             :   uchar const * seed; /* points into caller-owned instr_data */
      93             :   ulong         seed_len;
      94             :   ulong         lamports;
      95             :   ulong         space;
      96             :   fd_pubkey_t   owner;
      97             : };
      98             : typedef struct create_account_with_seed create_account_with_seed_t;
      99             : 
     100             : struct allocate_with_seed {
     101             :   fd_pubkey_t   base;
     102             :   uchar const * seed;
     103             :   ulong         seed_len;
     104             :   ulong         space;
     105             :   fd_pubkey_t   owner;
     106             : };
     107             : typedef struct allocate_with_seed allocate_with_seed_t;
     108             : 
     109             : struct assign_with_seed {
     110             :   fd_pubkey_t   base;
     111             :   uchar const * seed;
     112             :   ulong         seed_len;
     113             :   fd_pubkey_t   owner;
     114             : };
     115             : typedef struct assign_with_seed assign_with_seed_t;
     116             : 
     117             : struct transfer_with_seed {
     118             :   ulong         lamports;
     119             :   uchar const * from_seed;
     120             :   ulong         from_seed_len;
     121             :   fd_pubkey_t   from_owner;
     122             : };
     123             : typedef struct transfer_with_seed transfer_with_seed_t;
     124             : 
     125             : /* Discriminated union. */
     126             : 
     127             : union fd_system_program_instruction_inner {
     128             :   create_account_t           create_account;
     129             :   fd_pubkey_t                assign;
     130             :   ulong                      transfer;
     131             :   create_account_with_seed_t create_account_with_seed;
     132             :   ulong                      withdraw_nonce_account;
     133             :   fd_pubkey_t                initialize_nonce_account;
     134             :   fd_pubkey_t                authorize_nonce_account;
     135             :   ulong                      allocate;
     136             :   allocate_with_seed_t       allocate_with_seed;
     137             :   assign_with_seed_t         assign_with_seed;
     138             :   transfer_with_seed_t       transfer_with_seed;
     139             :   create_account_t           create_account_allow_prefund;
     140             : };
     141             : typedef union fd_system_program_instruction_inner fd_system_program_instruction_inner_t;
     142             : 
     143             : struct fd_system_program_instruction {
     144             :   uint                                  discriminant;
     145             :   fd_system_program_instruction_inner_t inner;
     146             : };
     147             : typedef struct fd_system_program_instruction fd_system_program_instruction_t;
     148             : 
     149             : /* fd_system_program_instruction_decode reads a bincode-encoded
     150             :    SystemInstruction from [data, data+data_sz).  Variable-length seed
     151             :    fields in the output point directly into `data`, so the caller must
     152             :    keep that buffer alive.  Returns 0 on success, -1 on decode error. */
     153             : 
     154             : static inline int
     155             : fd_system_program_instruction_decode( fd_system_program_instruction_t * out,
     156             :                                       uchar const *                     data,
     157         240 :                                       ulong                             data_sz ) {
     158         240 :   uchar const * _payload    = data;
     159         240 :   ulong const   _payload_sz = data_sz;
     160         240 :   ulong         _i          = 0UL;
     161             : 
     162         465 : # define CHECK( cond )   { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
     163         465 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
     164         708 : # define INC( n )        (_i += (ulong)(n))
     165         240 : # define CURSOR          (_payload+_i)
     166             : 
     167         240 :   CHECK_LEFT( 4UL );
     168         237 :   uint disc = FD_LOAD( uint, CURSOR ); INC( 4UL );
     169         237 :   out->discriminant = disc;
     170             : 
     171         237 :   switch( disc ) {
     172             : 
     173          15 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT:
     174         123 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_ALLOW_PREFUND: {
     175         123 :     create_account_t * ca =
     176         123 :         (disc==FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT)
     177         123 :           ? &out->inner.create_account
     178         123 :           : &out->inner.create_account_allow_prefund;
     179         123 :     CHECK_LEFT( 48UL );
     180         123 :     ca->lamports = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     181         123 :     ca->space    = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     182         123 :     fd_memcpy( ca->owner.key, CURSOR, 32UL ); INC( 32UL );
     183         123 :     return 0;
     184         123 :   }
     185             : 
     186           0 :   case FD_SYSTEM_PROGRAM_INSTR_ASSIGN: {
     187           0 :     CHECK_LEFT( 32UL );
     188           0 :     fd_memcpy( out->inner.assign.key, CURSOR, 32UL ); INC( 32UL );
     189           0 :     return 0;
     190           0 :   }
     191             : 
     192          27 :   case FD_SYSTEM_PROGRAM_INSTR_TRANSFER: {
     193          27 :     CHECK_LEFT( 8UL );
     194          27 :     out->inner.transfer = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     195          27 :     return 0;
     196          27 :   }
     197             : 
     198           0 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_WITH_SEED: {
     199           0 :     create_account_with_seed_t * cs = &out->inner.create_account_with_seed;
     200           0 :     CHECK_LEFT( 32UL ); fd_memcpy( cs->base.key, CURSOR, 32UL ); INC( 32UL );
     201           0 :     CHECK_LEFT( 8UL );  cs->seed_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     202           0 :     CHECK_LEFT( cs->seed_len );
     203           0 :     if( cs->seed_len ) {
     204           0 :       CHECK( fd_utf8_verify( (char const *)CURSOR, cs->seed_len ) );
     205           0 :     }
     206           0 :     cs->seed = CURSOR; INC( cs->seed_len );
     207           0 :     CHECK_LEFT( 48UL );
     208           0 :     cs->lamports = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     209           0 :     cs->space    = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     210           0 :     fd_memcpy( cs->owner.key, CURSOR, 32UL ); INC( 32UL );
     211           0 :     return 0;
     212           0 :   }
     213             : 
     214          12 :   case FD_SYSTEM_PROGRAM_INSTR_ADVANCE_NONCE_ACCOUNT: {
     215          12 :     return 0;
     216           0 :   }
     217             : 
     218           0 :   case FD_SYSTEM_PROGRAM_INSTR_WITHDRAW_NONCE_ACCOUNT: {
     219           0 :     CHECK_LEFT( 8UL );
     220           0 :     out->inner.withdraw_nonce_account = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     221           0 :     return 0;
     222           0 :   }
     223             : 
     224           6 :   case FD_SYSTEM_PROGRAM_INSTR_INITIALIZE_NONCE_ACCOUNT: {
     225           6 :     CHECK_LEFT( 32UL );
     226           6 :     fd_memcpy( out->inner.initialize_nonce_account.key, CURSOR, 32UL ); INC( 32UL );
     227           6 :     return 0;
     228           6 :   }
     229             : 
     230           0 :   case FD_SYSTEM_PROGRAM_INSTR_AUTHORIZE_NONCE_ACCOUNT: {
     231           0 :     CHECK_LEFT( 32UL );
     232           0 :     fd_memcpy( out->inner.authorize_nonce_account.key, CURSOR, 32UL ); INC( 32UL );
     233           0 :     return 0;
     234           0 :   }
     235             : 
     236          69 :   case FD_SYSTEM_PROGRAM_INSTR_ALLOCATE: {
     237          69 :     CHECK_LEFT( 8UL );
     238          69 :     out->inner.allocate = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     239          69 :     return 0;
     240          69 :   }
     241             : 
     242           0 :   case FD_SYSTEM_PROGRAM_INSTR_ALLOCATE_WITH_SEED: {
     243           0 :     allocate_with_seed_t * as_ = &out->inner.allocate_with_seed;
     244           0 :     CHECK_LEFT( 32UL ); fd_memcpy( as_->base.key, CURSOR, 32UL ); INC( 32UL );
     245           0 :     CHECK_LEFT( 8UL );  as_->seed_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     246           0 :     CHECK_LEFT( as_->seed_len );
     247           0 :     if( as_->seed_len ) {
     248           0 :       CHECK( fd_utf8_verify( (char const *)CURSOR, as_->seed_len ) );
     249           0 :     }
     250           0 :     as_->seed = CURSOR; INC( as_->seed_len );
     251           0 :     CHECK_LEFT( 40UL );
     252           0 :     as_->space = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     253           0 :     fd_memcpy( as_->owner.key, CURSOR, 32UL ); INC( 32UL );
     254           0 :     return 0;
     255           0 :   }
     256             : 
     257           0 :   case FD_SYSTEM_PROGRAM_INSTR_ASSIGN_WITH_SEED: {
     258           0 :     assign_with_seed_t * aw = &out->inner.assign_with_seed;
     259           0 :     CHECK_LEFT( 32UL ); fd_memcpy( aw->base.key, CURSOR, 32UL ); INC( 32UL );
     260           0 :     CHECK_LEFT( 8UL );  aw->seed_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     261           0 :     CHECK_LEFT( aw->seed_len );
     262           0 :     if( aw->seed_len ) {
     263           0 :       CHECK( fd_utf8_verify( (char const *)CURSOR, aw->seed_len ) );
     264           0 :     }
     265           0 :     aw->seed = CURSOR; INC( aw->seed_len );
     266           0 :     CHECK_LEFT( 32UL );
     267           0 :     fd_memcpy( aw->owner.key, CURSOR, 32UL ); INC( 32UL );
     268           0 :     return 0;
     269           0 :   }
     270             : 
     271           0 :   case FD_SYSTEM_PROGRAM_INSTR_TRANSFER_WITH_SEED: {
     272           0 :     transfer_with_seed_t * tw = &out->inner.transfer_with_seed;
     273           0 :     CHECK_LEFT( 8UL );  tw->lamports      = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     274           0 :     CHECK_LEFT( 8UL );  tw->from_seed_len = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     275           0 :     CHECK_LEFT( tw->from_seed_len );
     276           0 :     if( tw->from_seed_len ) {
     277           0 :       CHECK( fd_utf8_verify( (char const *)CURSOR, tw->from_seed_len ) );
     278           0 :     }
     279           0 :     tw->from_seed = CURSOR; INC( tw->from_seed_len );
     280           0 :     CHECK_LEFT( 32UL );
     281           0 :     fd_memcpy( tw->from_owner.key, CURSOR, 32UL ); INC( 32UL );
     282           0 :     return 0;
     283           0 :   }
     284             : 
     285           0 :   case FD_SYSTEM_PROGRAM_INSTR_UPGRADE_NONCE_ACCOUNT: {
     286           0 :     return 0;
     287           0 :   }
     288             : 
     289           0 :   default: return -1;
     290         237 :   }
     291             : 
     292         237 : # undef CHECK
     293         237 : # undef CHECK_LEFT
     294         237 : # undef INC
     295         237 : # undef CURSOR
     296         237 : }
     297             : 
     298             : /* fd_system_program_instruction_encode writes a bincode-encoded
     299             :    SystemInstruction into [buf, buf+bufsz).  On success stores the
     300             :    number of bytes written to *out_sz and returns 0.  Returns -1 on
     301             :    short buffer. */
     302             : 
     303             : static inline int
     304             : fd_system_program_instruction_encode( fd_system_program_instruction_t const * in,
     305             :                                       uchar *                                 buf,
     306             :                                       ulong                                   bufsz,
     307          27 :                                       ulong *                                 out_sz ) {
     308          27 :   uchar * const _payload    = buf;
     309          27 :   ulong const   _payload_sz = bufsz;
     310          27 :   ulong         _i          = 0UL;
     311             : 
     312          54 : # define CHECK_LEFT( n ) { if( FD_UNLIKELY( (n)>(_payload_sz-_i) ) ) { return -1; } }
     313          84 : # define INC( n )        (_i += (ulong)(n))
     314          27 : # define CURSOR          (_payload+_i)
     315             : 
     316          27 :   CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, in->discriminant ); INC( 4UL );
     317             : 
     318          27 :   switch( in->discriminant ) {
     319             : 
     320          15 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT:
     321          15 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_ALLOW_PREFUND: {
     322          15 :     create_account_t const * ca =
     323          15 :         (in->discriminant==FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT)
     324          15 :           ? &in->inner.create_account
     325          15 :           : &in->inner.create_account_allow_prefund;
     326          15 :     CHECK_LEFT( 48UL );
     327          15 :     FD_STORE( ulong, CURSOR, ca->lamports ); INC( 8UL );
     328          15 :     FD_STORE( ulong, CURSOR, ca->space ); INC( 8UL );
     329          15 :     fd_memcpy( CURSOR, ca->owner.key, 32UL ); INC( 32UL );
     330          15 :     break;
     331          15 :   }
     332             : 
     333           0 :   case FD_SYSTEM_PROGRAM_INSTR_ASSIGN: {
     334           0 :     CHECK_LEFT( 32UL );
     335           0 :     fd_memcpy( CURSOR, in->inner.assign.key, 32UL ); INC( 32UL );
     336           0 :     break;
     337           0 :   }
     338             : 
     339           3 :   case FD_SYSTEM_PROGRAM_INSTR_TRANSFER: {
     340           3 :     CHECK_LEFT( 8UL );
     341           3 :     FD_STORE( ulong, CURSOR, in->inner.transfer ); INC( 8UL );
     342           3 :     break;
     343           3 :   }
     344             : 
     345           0 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_WITH_SEED: {
     346           0 :     create_account_with_seed_t const * cs = &in->inner.create_account_with_seed;
     347           0 :     CHECK_LEFT( 32UL ); fd_memcpy( CURSOR, cs->base.key, 32UL ); INC( 32UL );
     348           0 :     CHECK_LEFT( 8UL );  FD_STORE( ulong, CURSOR, cs->seed_len ); INC( 8UL );
     349           0 :     if( cs->seed_len ) {
     350           0 :       CHECK_LEFT( cs->seed_len ); fd_memcpy( CURSOR, cs->seed, cs->seed_len ); INC( cs->seed_len );
     351           0 :     }
     352           0 :     CHECK_LEFT( 48UL );
     353           0 :     FD_STORE( ulong, CURSOR, cs->lamports ); INC( 8UL );
     354           0 :     FD_STORE( ulong, CURSOR, cs->space ); INC( 8UL );
     355           0 :     fd_memcpy( CURSOR, cs->owner.key, 32UL ); INC( 32UL );
     356           0 :     break;
     357           0 :   }
     358             : 
     359           0 :   case FD_SYSTEM_PROGRAM_INSTR_ADVANCE_NONCE_ACCOUNT: break;
     360             : 
     361           0 :   case FD_SYSTEM_PROGRAM_INSTR_WITHDRAW_NONCE_ACCOUNT: {
     362           0 :     CHECK_LEFT( 8UL );
     363           0 :     FD_STORE( ulong, CURSOR, in->inner.withdraw_nonce_account ); INC( 8UL );
     364           0 :     break;
     365           0 :   }
     366             : 
     367           0 :   case FD_SYSTEM_PROGRAM_INSTR_INITIALIZE_NONCE_ACCOUNT: {
     368           0 :     CHECK_LEFT( 32UL );
     369           0 :     fd_memcpy( CURSOR, in->inner.initialize_nonce_account.key, 32UL ); INC( 32UL );
     370           0 :     break;
     371           0 :   }
     372             : 
     373           0 :   case FD_SYSTEM_PROGRAM_INSTR_AUTHORIZE_NONCE_ACCOUNT: {
     374           0 :     CHECK_LEFT( 32UL );
     375           0 :     fd_memcpy( CURSOR, in->inner.authorize_nonce_account.key, 32UL ); INC( 32UL );
     376           0 :     break;
     377           0 :   }
     378             : 
     379           9 :   case FD_SYSTEM_PROGRAM_INSTR_ALLOCATE: {
     380           9 :     CHECK_LEFT( 8UL );
     381           9 :     FD_STORE( ulong, CURSOR, in->inner.allocate ); INC( 8UL );
     382           9 :     break;
     383           9 :   }
     384             : 
     385           0 :   case FD_SYSTEM_PROGRAM_INSTR_ALLOCATE_WITH_SEED: {
     386           0 :     allocate_with_seed_t const * as_ = &in->inner.allocate_with_seed;
     387           0 :     CHECK_LEFT( 32UL ); fd_memcpy( CURSOR, as_->base.key, 32UL ); INC( 32UL );
     388           0 :     CHECK_LEFT( 8UL );  FD_STORE( ulong, CURSOR, as_->seed_len ); INC( 8UL );
     389           0 :     if( as_->seed_len ) {
     390           0 :       CHECK_LEFT( as_->seed_len ); fd_memcpy( CURSOR, as_->seed, as_->seed_len ); INC( as_->seed_len );
     391           0 :     }
     392           0 :     CHECK_LEFT( 40UL );
     393           0 :     FD_STORE( ulong, CURSOR, as_->space ); INC( 8UL );
     394           0 :     fd_memcpy( CURSOR, as_->owner.key, 32UL ); INC( 32UL );
     395           0 :     break;
     396           0 :   }
     397             : 
     398           0 :   case FD_SYSTEM_PROGRAM_INSTR_ASSIGN_WITH_SEED: {
     399           0 :     assign_with_seed_t const * aw = &in->inner.assign_with_seed;
     400           0 :     CHECK_LEFT( 32UL ); fd_memcpy( CURSOR, aw->base.key, 32UL ); INC( 32UL );
     401           0 :     CHECK_LEFT( 8UL );  FD_STORE( ulong, CURSOR, aw->seed_len ); INC( 8UL );
     402           0 :     if( aw->seed_len ) {
     403           0 :       CHECK_LEFT( aw->seed_len ); fd_memcpy( CURSOR, aw->seed, aw->seed_len ); INC( aw->seed_len );
     404           0 :     }
     405           0 :     CHECK_LEFT( 32UL );
     406           0 :     fd_memcpy( CURSOR, aw->owner.key, 32UL ); INC( 32UL );
     407           0 :     break;
     408           0 :   }
     409             : 
     410           0 :   case FD_SYSTEM_PROGRAM_INSTR_TRANSFER_WITH_SEED: {
     411           0 :     transfer_with_seed_t const * tw = &in->inner.transfer_with_seed;
     412           0 :     CHECK_LEFT( 8UL );  FD_STORE( ulong, CURSOR, tw->lamports ); INC( 8UL );
     413           0 :     CHECK_LEFT( 8UL );  FD_STORE( ulong, CURSOR, tw->from_seed_len ); INC( 8UL );
     414           0 :     if( tw->from_seed_len ) {
     415           0 :       CHECK_LEFT( tw->from_seed_len ); fd_memcpy( CURSOR, tw->from_seed, tw->from_seed_len ); INC( tw->from_seed_len );
     416           0 :     }
     417           0 :     CHECK_LEFT( 32UL );
     418           0 :     fd_memcpy( CURSOR, tw->from_owner.key, 32UL ); INC( 32UL );
     419           0 :     break;
     420           0 :   }
     421             : 
     422           0 :   case FD_SYSTEM_PROGRAM_INSTR_UPGRADE_NONCE_ACCOUNT: break;
     423             : 
     424           0 :   default: return -1;
     425          27 :   }
     426             : 
     427          27 :   *out_sz = _i;
     428             : 
     429          27 : # undef CHECK_LEFT
     430          27 : # undef INC
     431          27 : # undef CURSOR
     432             : 
     433          27 :   return 0;
     434          27 : }
     435             : 
     436             : /* fd_nonce_state_versions_t is the in-memory representation of a decoded
     437             :    nonce account state.  Mirrors Agave's `Versions(Box<State>)` wrapper
     438             :    flattened into a single struct with an explicit `version`/`kind`
     439             :    discriminant pair.  When `kind == FD_NONCE_STATE_UNINITIALIZED` the
     440             :    `authority`, `durable_nonce`, and `lamports_per_signature` fields are
     441             :    ignored on both encode and decode. */
     442             : 
     443             : struct fd_nonce_state_versions {
     444             :   uint        version;
     445             :   uint        kind;
     446             :   fd_pubkey_t authority;
     447             :   fd_hash_t   durable_nonce;
     448             :   ulong       lamports_per_signature;
     449             : };
     450             : typedef struct fd_nonce_state_versions fd_nonce_state_versions_t;
     451             : 
     452             : /* fd_nonce_state_versions_size returns the bincode-exact wire size of the
     453             :    given nonce state.  Matches Agave's `bincode::serialized_size` for
     454             :    `nonce::versions::Versions`. */
     455             : 
     456             : static inline ulong
     457          21 : fd_nonce_state_versions_size( fd_nonce_state_versions_t const * in ) {
     458          21 :   return ( in->kind==FD_NONCE_STATE_INITIALIZED )
     459          21 :     ? FD_NONCE_STATE_INITIALIZED_SZ
     460          21 :     : FD_NONCE_STATE_UNINITIALIZED_SZ;
     461          21 : }
     462             : 
     463             : /* fd_nonce_state_versions_decode reads a bincode-encoded
     464             :    `nonce::versions::Versions` from [data, data+data_sz).  Trailing bytes
     465             :    beyond the parsed region are accepted (matches Agave's top-level
     466             :    `bincode::deserialize` which uses `allow_trailing_bytes()`).  Returns 0
     467             :    on success, -1 on any decode failure (short buffer, unknown
     468             :    discriminant).  Callers should map -1 to
     469             :    `FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA`. */
     470             : 
     471             : static inline int
     472             : fd_nonce_state_versions_decode( fd_nonce_state_versions_t * out,
     473             :                                 uchar const *               data,
     474          21 :                                 ulong                       data_sz ) {
     475          21 :   uchar const * _payload    = data;
     476          21 :   ulong const   _payload_sz = data_sz;
     477          21 :   ulong         _i          = 0UL;
     478             : 
     479         102 : # define CHECK( cond )   { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
     480          60 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
     481          96 : # define INC( n )        (_i += (ulong)(n))
     482          36 : # define CURSOR          (_payload+_i)
     483             : 
     484          21 :   CHECK_LEFT( 4UL ); uint version = FD_LOAD( uint, CURSOR ); INC( 4UL );
     485          21 :   CHECK( version<=FD_NONCE_VERSION_CURRENT );
     486          21 :   out->version = version;
     487             : 
     488          21 :   CHECK_LEFT( 4UL ); uint kind = FD_LOAD( uint, CURSOR ); INC( 4UL );
     489          21 :   CHECK( kind<=FD_NONCE_STATE_INITIALIZED );
     490          21 :   out->kind = kind;
     491             : 
     492          21 :   if( kind==FD_NONCE_STATE_INITIALIZED ) {
     493          18 :     CHECK_LEFT( 72UL );
     494          18 :     fd_memcpy( out->authority.key,     CURSOR, 32UL ); INC( 32UL );
     495          18 :     fd_memcpy( out->durable_nonce.hash, CURSOR, 32UL ); INC( 32UL );
     496          18 :     out->lamports_per_signature = FD_LOAD( ulong, CURSOR ); INC( 8UL );
     497          18 :   }
     498             : 
     499          21 : # undef CHECK
     500          21 : # undef CHECK_LEFT
     501          21 : # undef INC
     502          21 : # undef CURSOR
     503             : 
     504          21 :   return 0;
     505          21 : }
     506             : 
     507             : /* fd_nonce_state_versions_encode writes a bincode-encoded
     508             :    `nonce::versions::Versions` into [buf, buf+bufsz).  On success stores
     509             :    the number of bytes written to *out_sz and returns 0.  Returns -1 on
     510             :    short buffer or invalid discriminant. */
     511             : 
     512             : static inline int
     513             : fd_nonce_state_versions_encode( fd_nonce_state_versions_t const * in,
     514             :                                 uchar *                           buf,
     515             :                                 ulong                             bufsz,
     516          30 :                                 ulong *                           out_sz ) {
     517          30 :   uchar * const _payload    = buf;
     518          30 :   ulong const   _payload_sz = bufsz;
     519          30 :   ulong         _i          = 0UL;
     520             : 
     521         147 : # define CHECK( cond )   { if( FD_UNLIKELY( !(cond) ) ) { return -1; } }
     522          87 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
     523         141 : # define INC( n )        (_i += (ulong)(n))
     524          54 : # define CURSOR          (_payload+_i)
     525             : 
     526          30 :   CHECK( in->version<=FD_NONCE_VERSION_CURRENT );
     527          30 :   CHECK( in->kind   <=FD_NONCE_STATE_INITIALIZED );
     528             : 
     529          30 :   CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, in->version ); INC( 4UL );
     530          30 :   CHECK_LEFT( 4UL ); FD_STORE( uint, CURSOR, in->kind    ); INC( 4UL );
     531             : 
     532          30 :   if( in->kind==FD_NONCE_STATE_INITIALIZED ) {
     533          27 :     CHECK_LEFT( 72UL );
     534          27 :     fd_memcpy( CURSOR, in->authority.key,      32UL ); INC( 32UL );
     535          27 :     fd_memcpy( CURSOR, in->durable_nonce.hash, 32UL ); INC( 32UL );
     536          27 :     FD_STORE( ulong, CURSOR, in->lamports_per_signature ); INC( 8UL );
     537          27 :   }
     538             : 
     539          30 :   *out_sz = _i;
     540             : 
     541          30 : # undef CHECK
     542          30 : # undef CHECK_LEFT
     543          30 : # undef INC
     544          30 : # undef CURSOR
     545             : 
     546          30 :   return 0;
     547          30 : }
     548             : 
     549             : FD_PROTOTYPES_BEGIN
     550             : 
     551             : /* fd_system_program_execute is the entrypoint for the system program */
     552             : 
     553             : int fd_system_program_execute( fd_exec_instr_ctx_t * ctx );
     554             : 
     555             : /* System program instruction handlers */
     556             : 
     557             : int fd_system_program_exec_create_account              ( fd_exec_instr_ctx_t * ctx, create_account_t const *           data     );
     558             : int fd_system_program_exec_assign                      ( fd_exec_instr_ctx_t * ctx, fd_pubkey_t const *                owner    );
     559             : int fd_system_program_exec_transfer                    ( fd_exec_instr_ctx_t * ctx, ulong                              lamports );
     560             : int fd_system_program_exec_create_account_with_seed    ( fd_exec_instr_ctx_t * ctx, create_account_with_seed_t const * data     );
     561             : int fd_system_program_exec_advance_nonce_account       ( fd_exec_instr_ctx_t * ctx                                              );
     562             : int fd_system_program_exec_withdraw_nonce_account      ( fd_exec_instr_ctx_t * ctx, ulong                              lamports );
     563             : int fd_system_program_exec_initialize_nonce_account    ( fd_exec_instr_ctx_t * ctx, fd_pubkey_t const *                pubkey   );
     564             : int fd_system_program_exec_authorize_nonce_account     ( fd_exec_instr_ctx_t * ctx, fd_pubkey_t const *                pubkey   );
     565             : int fd_system_program_exec_allocate                    ( fd_exec_instr_ctx_t * ctx, ulong                              space    );
     566             : int fd_system_program_exec_allocate_with_seed          ( fd_exec_instr_ctx_t * ctx, allocate_with_seed_t const *       data     );
     567             : int fd_system_program_exec_assign_with_seed            ( fd_exec_instr_ctx_t * ctx, assign_with_seed_t const *         data     );
     568             : int fd_system_program_exec_transfer_with_seed          ( fd_exec_instr_ctx_t * ctx, transfer_with_seed_t const *       data     );
     569             : int fd_system_program_exec_upgrade_nonce_account       ( fd_exec_instr_ctx_t * ctx                                              );
     570             : int fd_system_program_exec_create_account_allow_prefund( fd_exec_instr_ctx_t * ctx, create_account_t const *           data     );
     571             : 
     572             : /* User APIs */
     573             : 
     574             : /* fd_check_transaction_age returns 0 if the transactions age is valid,
     575             :    returns non-zero otherwise. This is determined by the age of the
     576             :    blockhash provided in the transaction message or by the validity of
     577             :    the nonce provided in the transaction. */
     578             : 
     579             : int
     580             : fd_check_transaction_age( fd_bank_t *         bank,
     581             :                           fd_txn_in_t const * txn_in,
     582             :                           fd_txn_out_t *      txn_out );
     583             : 
     584             : /* `fd_get_system_account_kind()` determines whether an account is
     585             :    a normal system program account or a nonce account. Returns:
     586             :    - FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_SYSTEM if the account is a
     587             :      normal system program account
     588             :    - FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_NONCE if the account is a
     589             :      nonce account
     590             :    - FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN otherwise
     591             :    https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L55-L71 */
     592             : 
     593             : int
     594             : fd_get_system_account_kind( fd_account_meta_t const * meta );
     595             : 
     596             : FD_PROTOTYPES_END
     597             : 
     598             : #endif /* HEADER_fd_src_flamenco_runtime_program_fd_system_program_h */

Generated by: LCOV version 1.14