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-07-01 06:01:22 Functions: 11 385 2.9 %

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

Generated by: LCOV version 1.14