LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_system_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 396 0.0 %
Date: 2025-10-13 04:42:14 Functions: 0 18 0.0 %

          Line data    Source code
       1             : #include "fd_system_program.h"
       2             : #include "../fd_executor.h"
       3             : #include "../fd_borrowed_account.h"
       4             : #include "../fd_system_ids.h"
       5             : #include "../fd_pubkey_utils.h"
       6             : 
       7             : 
       8             : /* The `Address` type in the Agave system program is logged in the format:
       9             :    "Address { address: <pubkey>>, base: <pubkey | None> }"
      10             :    When this function is called, there are two cases:
      11             :    1. _base==NULL. This means the address was not derived, so we should log the base pubkey as `None`.
      12             :    2. _base!=NULL. The address was derived, so we should log the base pubkey as `Some(pubkey)`.
      13             : 
      14             :    Max buffer length: 29 (string literal) + 90 (2 encoded pubkeys) + 6 (Some()) = 125
      15             :    */
      16             : static inline char *
      17           0 : fd_log_address_type( fd_spad_t * spad, fd_pubkey_t const * pubkey, fd_pubkey_t const * base ) {
      18           0 :   char * out = fd_spad_alloc( spad, alignof(char), 125UL );
      19           0 :   char base_addr[52];
      20           0 :   if( FD_UNLIKELY( base ) ) {
      21           0 :     snprintf( base_addr, 52UL, "Some(%s)", FD_BASE58_ENC_32_ALLOCA( base ) );
      22           0 :   } else {
      23           0 :     snprintf( base_addr, 52UL, "None" );
      24           0 :   }
      25             : 
      26           0 :   snprintf( out, 125UL, "Address { address: %s, base: %s }", FD_BASE58_ENC_32_ALLOCA( pubkey ), base_addr );
      27           0 :   return out;
      28           0 : }
      29             : 
      30             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L42-L68
      31             : 
      32             :    Partial port of system_processor::Address::create, only covering the
      33             :    case of the "seed" input actually existing.  Note that this doesn't
      34             :    "create" an address, but rather re-derives from PDA inputs and checks
      35             :    that the result matches some expected value. */
      36             : 
      37             : static int
      38             : verify_seed_address( fd_exec_instr_ctx_t * ctx,
      39             :                      fd_pubkey_t const *   expected,
      40             :                      fd_pubkey_t const *   base,
      41             :                      char const *          seed,
      42             :                      ulong                 seed_sz,
      43           0 :                      fd_pubkey_t const *   owner ) {
      44             : 
      45           0 :   fd_pubkey_t actual[1];
      46           0 :   do {
      47           0 :     int err = fd_pubkey_create_with_seed(
      48           0 :         ctx,
      49           0 :         base->uc,
      50           0 :         seed,
      51           0 :         seed_sz,
      52           0 :         owner->uc,
      53           0 :         actual->uc );
      54           0 :     if( FD_UNLIKELY( err ) ) return err;
      55           0 :   } while(0);
      56             : 
      57           0 :   if( FD_UNLIKELY( 0!=memcmp( actual->uc, expected->uc, sizeof(fd_pubkey_t) ) ) ) {
      58             :     /* Log msg_sz can be more or less than 127 bytes */
      59           0 :     fd_log_collector_printf_inefficient_max_512( ctx,
      60           0 :       "Create: address %s does not match derived address %s",
      61           0 :       FD_BASE58_ENC_32_ALLOCA( expected ),
      62           0 :       FD_BASE58_ENC_32_ALLOCA( actual ) );
      63           0 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
      64           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      65           0 :   }
      66             : 
      67           0 :   return 0;
      68           0 : }
      69             : 
      70             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L183
      71             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L182
      72             : 
      73             :    Matches Solana Labs system_processor::transfer_verified */
      74             : 
      75             : static int
      76             : fd_system_program_transfer_verified( fd_exec_instr_ctx_t * ctx,
      77             :                                      ulong                 transfer_amount,
      78             :                                      ushort                from_acct_idx,
      79           0 :                                      ushort                to_acct_idx ) {
      80           0 :   int err;
      81             : 
      82             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L191-L192 */
      83             : 
      84           0 :   fd_guarded_borrowed_account_t from = {0};
      85           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, from_acct_idx, &from );
      86             : 
      87             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L193-L196 */
      88             : 
      89           0 :   if( fd_borrowed_account_get_data_len( &from ) != 0UL ) {
      90           0 :     fd_log_collector_msg_literal( ctx, "Transfer: `from` must not carry data" );
      91           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
      92           0 :   }
      93             : 
      94             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L197-L205 */
      95             : 
      96           0 :   if( transfer_amount > fd_borrowed_account_get_lamports( &from ) ) {
      97             :     /* Max msg_sz: 45 - 6 + 20 + 20 = 79 < 127 => we can use printf */
      98           0 :     fd_log_collector_printf_dangerous_max_127( ctx, "Transfer: insufficient lamports %lu, need %lu", fd_borrowed_account_get_lamports( &from ), transfer_amount );
      99           0 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS;
     100           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     101           0 :   }
     102             : 
     103             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L207 */
     104             : 
     105           0 :   err = fd_borrowed_account_checked_sub_lamports( &from, transfer_amount );
     106             :   /* Note: this err can never happen because of the check above */
     107           0 :   if( FD_UNLIKELY( err ) ) return err;
     108             : 
     109             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L208 */
     110             : 
     111           0 :   fd_borrowed_account_drop( &from );
     112             : 
     113             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L209-L210 */
     114             : 
     115           0 :   fd_guarded_borrowed_account_t to = {0};
     116           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, to_acct_idx, &to );
     117             : 
     118             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L211 */
     119             : 
     120           0 :   err = fd_borrowed_account_checked_add_lamports( &to, transfer_amount );
     121           0 :   if( FD_UNLIKELY( err ) ) return err;
     122             : 
     123           0 :   return 0;
     124           0 : }
     125             : 
     126             : /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L214
     127             : 
     128             :    Matches system_processor::transfer */
     129             : 
     130             : static int
     131             : fd_system_program_transfer( fd_exec_instr_ctx_t * ctx,
     132             :                             ulong                 transfer_amount,
     133             :                             ushort                from_acct_idx,
     134           0 :                             ushort                to_acct_idx ) {
     135             : 
     136             :   /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L222-L232 */
     137             : 
     138           0 :   int instr_err_code = 0;
     139           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, from_acct_idx, &instr_err_code ) ) ) {
     140             :     /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
     141           0 :     if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
     142             :     /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
     143           0 :     ushort idx_in_txn = ctx->instr->accounts[ from_acct_idx ].index_in_transaction;
     144           0 :     fd_log_collector_printf_dangerous_max_127( ctx,
     145           0 :       "Transfer: `from` account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->txn_ctx->account_keys[ idx_in_txn ] ) );
     146           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     147           0 :   }
     148             : 
     149             :   /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L234-L241 */
     150             : 
     151           0 :   return fd_system_program_transfer_verified( ctx, transfer_amount, from_acct_idx, to_acct_idx );
     152           0 : }
     153             : 
     154             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L71-L111
     155             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L70
     156             : 
     157             :    Based on Solana Labs system_processor::allocate() */
     158             : 
     159             : static int
     160             : fd_system_program_allocate( fd_exec_instr_ctx_t *   ctx,
     161             :                             fd_borrowed_account_t * account,
     162             :                             ulong                   space,
     163             :                             fd_pubkey_t const *     authority,
     164           0 :                             fd_pubkey_t const *     base ) {
     165           0 :   int err;
     166             : 
     167             :   /* Assumes that acct_idx was bounds checked */
     168             : 
     169             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L78-L85 */
     170             : 
     171           0 :   if( FD_UNLIKELY( !fd_exec_instr_ctx_any_signed( ctx, authority ) ) ) {
     172             :     /* Max msg_sz: 35 - 2 + 125 = 158 */
     173           0 :     fd_log_collector_printf_inefficient_max_512( ctx,
     174           0 :       "Allocate: 'to' account %s must sign", fd_log_address_type( ctx->txn_ctx->spad, account->acct->pubkey, base ) );
     175           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     176           0 :   }
     177             : 
     178             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L87-L96 */
     179             : 
     180           0 :   if( FD_UNLIKELY( ( fd_borrowed_account_get_data_len( account ) != 0UL ) ||
     181           0 :                    ( 0!=memcmp( fd_borrowed_account_get_owner( account ), fd_solana_system_program_id.uc, 32UL ) ) ) ) {
     182             :     /* Max msg_sz: 35 - 2 + 125 = 158 */
     183           0 :     fd_log_collector_printf_inefficient_max_512( ctx,
     184           0 :       "Allocate: account %s already in use", fd_log_address_type( ctx->txn_ctx->spad, account->acct->pubkey, base ) );
     185           0 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
     186           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     187           0 :   }
     188             : 
     189             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L98-L106 */
     190             : 
     191           0 :   if( FD_UNLIKELY( space > FD_RUNTIME_ACC_SZ_MAX ) ) {
     192             :     /* Max msg_sz: 48 - 6 + 2*20 = 82 < 127 => we can use printf */
     193           0 :     fd_log_collector_printf_dangerous_max_127( ctx,
     194           0 :       "Allocate: requested %lu, max allowed %lu", space, FD_RUNTIME_ACC_SZ_MAX );
     195           0 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN;
     196           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     197           0 :   }
     198             : 
     199             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L108 */
     200             : 
     201           0 :   err = fd_borrowed_account_set_data_length( account, space );
     202           0 :   if( FD_UNLIKELY( err ) ) {
     203           0 :     return err;
     204           0 :   }
     205             : 
     206           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     207           0 : }
     208             : 
     209             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L113-L131
     210             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L112
     211             : 
     212             :    Based on Solana Labs system_processor::assign() */
     213             : 
     214             : static int
     215             : fd_system_program_assign( fd_exec_instr_ctx_t *   ctx,
     216             :                           fd_borrowed_account_t * account,
     217             :                           fd_pubkey_t const *     owner,
     218             :                           fd_pubkey_t const *     authority,
     219           0 :                           fd_pubkey_t const *     base ) {
     220             :   /* Assumes addr_idx was bounds checked */
     221             : 
     222             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L121-L123 */
     223             : 
     224           0 :   if( 0==memcmp( fd_borrowed_account_get_owner( account ), owner->uc, sizeof(fd_pubkey_t) ) )
     225           0 :     return 0;
     226             : 
     227             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L125-L128 */
     228             : 
     229           0 :   if( FD_UNLIKELY( !fd_exec_instr_ctx_any_signed( ctx, authority ) ) ) {
     230             :     /* Max msg_sz: 28 - 2 + 125 = 151 */
     231           0 :     fd_log_collector_printf_inefficient_max_512( ctx,
     232           0 :       "Assign: account %s must sign", fd_log_address_type( ctx->txn_ctx->spad, account->acct->pubkey, base ) );
     233           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     234           0 :   }
     235             : 
     236           0 :   return fd_borrowed_account_set_owner( account, owner );
     237           0 : }
     238             : 
     239             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L133-L143
     240             : 
     241             :    Based on Solana Labs system_processor::allocate_and_assign() */
     242             : 
     243             : static int
     244             : fd_system_program_allocate_and_assign( fd_exec_instr_ctx_t *   ctx,
     245             :                                        fd_borrowed_account_t * account,
     246             :                                        ulong                   space,
     247             :                                        fd_pubkey_t const *     owner,
     248             :                                        fd_pubkey_t const *     authority,
     249           0 :                                        fd_pubkey_t const *     base ) {
     250             : 
     251           0 :   do {
     252           0 :     int err = fd_system_program_allocate( ctx, account, space, authority, base );
     253           0 :     if( FD_UNLIKELY( err ) ) return err;
     254           0 :   } while(0);
     255           0 :   return fd_system_program_assign( ctx, account, owner, authority, base );
     256             : 
     257           0 : }
     258             : 
     259             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L146-L181
     260             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L145
     261             : 
     262             :    Matches Solana Labs system_processor::create_account() */
     263             : 
     264             : static int
     265             : fd_system_program_create_account( fd_exec_instr_ctx_t * ctx,
     266             :                                   ushort                from_acct_idx,
     267             :                                   ushort                to_acct_idx,
     268             :                                   ulong                 lamports,
     269             :                                   ulong                 space,
     270             :                                   fd_pubkey_t const *   owner,
     271             :                                   fd_pubkey_t const *   authority,
     272           0 :                                   fd_pubkey_t const *   base ) {
     273           0 :   int err;
     274             : 
     275             :   /* if it looks like the to account is already in use, bail
     276             :      https://github.com/anza-xyz/agave/blob/v2.1.14/programs/system/src/system_processor.rs#L159-L172 */
     277             : 
     278           0 :   do {
     279             :     /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L160-L161 */
     280             : 
     281           0 :     fd_guarded_borrowed_account_t to = {0};
     282           0 :     FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, to_acct_idx, &to );
     283             : 
     284             :     /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L162-L169 */
     285             : 
     286           0 :     if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &to ) ) ) {
     287             :       /* Max msg_sz: 41 - 2 + 125 = 164 */
     288           0 :       fd_log_collector_printf_inefficient_max_512( ctx,
     289           0 :         "Create Account: account %s already in use", fd_log_address_type( ctx->txn_ctx->spad, to.acct->pubkey, base ) );
     290           0 :       ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
     291           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     292           0 :     }
     293             : 
     294             :     /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L171 */
     295             : 
     296           0 :     err = fd_system_program_allocate_and_assign( ctx, &to, space, owner, authority, base );
     297           0 :     if( FD_UNLIKELY( err ) ) return err;
     298             : 
     299             :     /* Implicit drop
     300             :        https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L172 */
     301           0 :   } while (0);
     302             : 
     303             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L173-L180 */
     304             : 
     305           0 :   return fd_system_program_transfer( ctx, lamports, from_acct_idx, to_acct_idx );
     306           0 : }
     307             : 
     308             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L327-L352
     309             : 
     310             :    Matches Solana Labs system_processor SystemInstruction::CreateAccount { ... } => { ... } */
     311             : 
     312             : int
     313             : fd_system_program_exec_create_account( fd_exec_instr_ctx_t *                                  ctx,
     314           0 :                                        fd_system_program_instruction_create_account_t const * create_acc ) {
     315             : 
     316             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L332 */
     317             : 
     318           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
     319           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     320             : 
     321             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L333-L339
     322             :      Authorization check is lifted out from 'allocate' to here. */
     323             : 
     324           0 :   ushort const from_acct_idx = 0UL;
     325           0 :   ushort const to_acct_idx   = 1UL;
     326             : 
     327             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/programs/system/src/system_processor.rs#L317-L320 */
     328           0 :   fd_pubkey_t const * authority = NULL;
     329           0 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, to_acct_idx, &authority );
     330           0 :   if( FD_UNLIKELY( err ) ) return err;
     331             : 
     332           0 :   return fd_system_program_create_account(
     333           0 :       ctx,
     334           0 :       from_acct_idx,
     335           0 :       to_acct_idx,
     336           0 :       create_acc->lamports,
     337           0 :       create_acc->space,
     338           0 :       &create_acc->owner,
     339           0 :       authority,
     340           0 :       NULL );
     341           0 : }
     342             : 
     343             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L381-L393
     344             : 
     345             :    Matches Solana Labs system_processor SystemInstruction::Assign { ... } => { ... } */
     346             : 
     347             : int
     348             : fd_system_program_exec_assign( fd_exec_instr_ctx_t * ctx,
     349           0 :                                fd_pubkey_t const *   owner ) {
     350           0 :   int err;
     351             : 
     352             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L382 */
     353             : 
     354           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     355           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     356             : 
     357             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L383-L384 */
     358             : 
     359           0 :   fd_guarded_borrowed_account_t account = {0};
     360           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
     361             : 
     362             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L385-L391
     363             :      system_processor::Address::create eliminated (dead code) */
     364             : 
     365             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L392 */
     366             : 
     367           0 :   err = fd_system_program_assign( ctx, &account, owner, account.acct->pubkey, NULL );
     368           0 :   if( FD_UNLIKELY( err ) ) return err;
     369             : 
     370             :   /* Implicit drop */
     371             : 
     372           0 :   return 0;
     373           0 : }
     374             : 
     375             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L394-L404
     376             : 
     377             :    Matches Solana Labs system_processor SystemInstruction::Transfer { ... } => { ... } */
     378             : 
     379             : int
     380             : fd_system_program_exec_transfer( fd_exec_instr_ctx_t * ctx,
     381           0 :                                  ulong                 transfer_amount ) {
     382             : 
     383             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L395 */
     384             : 
     385           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
     386           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     387             : 
     388             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L396-L402 */
     389             : 
     390           0 :   return fd_system_program_transfer( ctx, transfer_amount, 0UL, 1UL );
     391           0 : }
     392             : 
     393             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L353
     394             : 
     395             :    Matches Solana Labs system_processor SystemInstruction::CreateAccountWithSeed { ... } => { ... } */
     396             : 
     397             : int
     398             : fd_system_program_exec_create_account_with_seed( fd_exec_instr_ctx_t *                                            ctx,
     399           0 :                                                  fd_system_program_instruction_create_account_with_seed_t const * args ) {
     400             : 
     401             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L360 */
     402             : 
     403           0 :   if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( ctx, 2UL) ) )
     404           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     405             : 
     406             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L361-L367 */
     407             : 
     408           0 :   fd_pubkey_t const * to_address = NULL;
     409           0 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 1UL, &to_address );
     410           0 :   if( FD_UNLIKELY( err ) ) return err;
     411             : 
     412           0 :   do {
     413           0 :     int err = verify_seed_address(
     414           0 :         ctx,
     415           0 :         to_address,
     416           0 :         &args->base,
     417           0 :         (char const *)args->seed,
     418           0 :         args->seed_len,
     419           0 :         &args->owner );
     420           0 :     if( FD_UNLIKELY( err ) ) return err;
     421           0 :   } while(0);
     422             : 
     423             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L368-L379 */
     424             : 
     425           0 :   ushort const from_acct_idx = 0UL;
     426           0 :   ushort const to_acct_idx   = 1UL;
     427           0 :   return fd_system_program_create_account(
     428           0 :       ctx,
     429           0 :       from_acct_idx,
     430           0 :       to_acct_idx,
     431           0 :       args->lamports,
     432           0 :       args->space,
     433           0 :       &args->owner,
     434           0 :       &args->base,
     435           0 :       &args->base );
     436           0 : }
     437             : 
     438             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L504-L516
     439             : 
     440             :    Matches Solana Labs system_processor SystemInstruction::Allocate { ... } => { ... } */
     441             : 
     442             : int
     443             : fd_system_program_exec_allocate( fd_exec_instr_ctx_t * ctx,
     444           0 :                                  ulong                 space ) {
     445           0 :   int err;
     446             : 
     447             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L505 */
     448             : 
     449           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     450           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     451             : 
     452             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L506-L507 */
     453           0 :   fd_guarded_borrowed_account_t account = {0};
     454           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
     455             : 
     456             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L508-L514
     457             :      system_processor::Address::create eliminated (dead code) */
     458             : 
     459             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L515
     460             :      Authorization check is lifted out from 'allocate' to here. */
     461             : 
     462           0 :   err = fd_system_program_allocate( ctx, &account, space, account.acct->pubkey, NULL );
     463           0 :   if( FD_UNLIKELY( err ) ) return err;
     464             : 
     465             :   /* Implicit drop */
     466             : 
     467           0 :   return 0;
     468           0 : }
     469             : 
     470             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L517-L541
     471             : 
     472             :    Matches Solana Labs system_processor SystemInstruction::AllocateWithSeed { ... } => { ... } */
     473             : 
     474             : int
     475             : fd_system_program_exec_allocate_with_seed( fd_exec_instr_ctx_t *                                      ctx,
     476           0 :                                            fd_system_program_instruction_allocate_with_seed_t const * args ) {
     477           0 :   int err;
     478             : 
     479             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L523 */
     480             : 
     481           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     482           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     483             : 
     484             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#524-525 */
     485             : 
     486           0 :   fd_guarded_borrowed_account_t account = {0};
     487           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
     488             : 
     489             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L526-L532 */
     490             : 
     491           0 :   err = verify_seed_address(
     492           0 :     ctx,
     493           0 :     account.acct->pubkey,
     494           0 :     &args->base,
     495           0 :     (char const *)args->seed,
     496           0 :     args->seed_len,
     497           0 :     &args->owner );
     498           0 :   if( FD_UNLIKELY( err ) ) return err;
     499             : 
     500             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L533-L540
     501             :      Authorization check is lifted out from 'allocate' to here. */
     502             : 
     503           0 :   err = fd_system_program_allocate_and_assign(
     504           0 :     ctx,
     505           0 :     &account,
     506           0 :     args->space,
     507           0 :     &args->owner,
     508           0 :     &args->base,
     509           0 :     &args->base );
     510           0 :   if( FD_UNLIKELY( err ) ) return err;
     511             : 
     512             :   /* Implicit drop */
     513             : 
     514           0 :   return 0;
     515           0 : }
     516             : 
     517             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L542-L554
     518             : 
     519             :    Matches Solana Labs system_processor SystemInstruction::AssignWithSeed { ... } => { ... } */
     520             : 
     521             : int
     522             : fd_system_program_exec_assign_with_seed( fd_exec_instr_ctx_t *                                    ctx,
     523           0 :                                          fd_system_program_instruction_assign_with_seed_t const * args ) {
     524           0 :   int err;
     525             : 
     526             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#543 */
     527             : 
     528           0 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     529           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     530             : 
     531             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L544-L545 */
     532             : 
     533           0 :   fd_guarded_borrowed_account_t account = {0};
     534           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
     535             : 
     536             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L546-L552 */
     537             : 
     538           0 :   err = verify_seed_address(
     539           0 :     ctx,
     540           0 :     account.acct->pubkey,
     541           0 :     &args->base,
     542           0 :     (char const *)args->seed,
     543           0 :     args->seed_len,
     544           0 :     &args->owner );
     545           0 :   if( FD_UNLIKELY( err ) ) return err;
     546             : 
     547             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L553
     548             :      Authorization check is lifted out from 'assign' to here. */
     549             : 
     550           0 :   err = fd_system_program_assign( ctx, &account, &args->owner, &args->base, &args->base );
     551           0 :   if( FD_UNLIKELY( err ) ) return err;
     552             : 
     553             :   /* Implicit drop */
     554             : 
     555           0 :   return 0;
     556           0 : }
     557             : 
     558             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L405-L422
     559             : 
     560             :    Matches Solana Labs system_processor SystemInstruction::TransferWithSeed { ... } => { ... } */
     561             : 
     562             : int
     563             : fd_system_program_exec_transfer_with_seed( fd_exec_instr_ctx_t *                                      ctx,
     564           0 :                                            fd_system_program_instruction_transfer_with_seed_t const * args ) {
     565             : 
     566             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L410 */
     567             : 
     568           0 :   if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( ctx, 3UL ) ) )
     569           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     570             : 
     571             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L411-L421
     572             :      Inlined call to system_processor::transfer_with_seed */
     573             : 
     574           0 :   ushort const from_idx      = 0UL;
     575           0 :   ushort const from_base_idx = 1UL;
     576           0 :   ushort const to_idx        = 2UL;
     577             : 
     578           0 :   int instr_err_code = 0;
     579           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, from_base_idx, &instr_err_code ) ) ) {
     580             :     /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
     581           0 :     if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
     582             :     /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
     583           0 :     ushort idx_in_txn = ctx->instr->accounts[ from_base_idx ].index_in_transaction;
     584           0 :     fd_log_collector_printf_dangerous_max_127( ctx,
     585           0 :       "Transfer: 'from' account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->txn_ctx->account_keys[ idx_in_txn ] ) );
     586           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     587           0 :   }
     588             : 
     589             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/system/src/system_processor.rs#L267-L274 */
     590             : 
     591           0 :   fd_pubkey_t const * base = NULL;
     592           0 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, from_base_idx, &base );
     593           0 :   if( FD_UNLIKELY( err ) ) return err;
     594             : 
     595           0 :   fd_pubkey_t address_from_seed[1];
     596           0 :   do {
     597           0 :     int err = fd_pubkey_create_with_seed(
     598           0 :         ctx,
     599           0 :         base->uc,
     600           0 :         (char const *)args->from_seed,
     601           0 :         args->from_seed_len,
     602           0 :         args->from_owner.uc,
     603           0 :         address_from_seed->uc );
     604           0 :     if( FD_UNLIKELY( err ) ) return err;
     605           0 :   } while(0);
     606             : 
     607             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/system/src/system_processor.rs#L276-L287 */
     608           0 :   fd_pubkey_t const * from_key = NULL;
     609           0 :   err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, from_idx, &from_key );
     610           0 :   if( FD_UNLIKELY( err ) ) return err;
     611             : 
     612           0 :   if( FD_UNLIKELY( 0!=memcmp( address_from_seed->uc,
     613           0 :                               from_key->uc,
     614           0 :                               sizeof(fd_pubkey_t) ) ) ) {
     615             :     /* Log msg_sz can be more or less than 127 bytes */
     616           0 :     fd_log_collector_printf_inefficient_max_512( ctx,
     617           0 :       "Transfer: 'from' address %s does not match derived address %s",
     618           0 :       FD_BASE58_ENC_32_ALLOCA( from_key ),
     619           0 :       FD_BASE58_ENC_32_ALLOCA( address_from_seed ) );
     620           0 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
     621           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     622           0 :   }
     623             : 
     624             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L305-L312 */
     625           0 :   return fd_system_program_transfer_verified( ctx, args->lamports, from_idx, to_idx );
     626           0 : }
     627             : 
     628             : int
     629           0 : fd_system_program_execute( fd_exec_instr_ctx_t * ctx ) {
     630           0 :   FD_EXEC_CU_UPDATE( ctx, 150UL );
     631             : 
     632             :   /* Deserialize the SystemInstruction enum */
     633           0 :   uchar * data = ctx->instr->data;
     634           0 :   if( FD_UNLIKELY( data==NULL ) ) {
     635           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     636           0 :   }
     637             : 
     638           0 :   int decode_err;
     639           0 :   ulong decoded_sz;
     640           0 :   fd_system_program_instruction_t * instruction = fd_bincode_decode1_spad(
     641           0 :       system_program_instruction, ctx->txn_ctx->spad,
     642           0 :       data, ctx->instr->data_sz,
     643           0 :       &decode_err, &decoded_sz );
     644           0 :   if( FD_UNLIKELY( decode_err ) ) {
     645           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     646           0 :   }
     647           0 :   if( FD_UNLIKELY( decoded_sz > FD_TXN_MTU ) ) {
     648           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     649           0 :   }
     650             : 
     651           0 :   int result = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     652             : 
     653           0 :   switch( instruction->discriminant ) {
     654           0 :   case fd_system_program_instruction_enum_create_account: {
     655           0 :     result = fd_system_program_exec_create_account(
     656           0 :         ctx, &instruction->inner.create_account );
     657           0 :     break;
     658           0 :   }
     659           0 :   case fd_system_program_instruction_enum_assign: {
     660           0 :     result = fd_system_program_exec_assign(
     661           0 :         ctx, &instruction->inner.assign );
     662           0 :     break;
     663           0 :   }
     664           0 :   case fd_system_program_instruction_enum_transfer: {
     665           0 :     result = fd_system_program_exec_transfer(
     666           0 :         ctx, instruction->inner.transfer );
     667           0 :     break;
     668           0 :   }
     669           0 :   case fd_system_program_instruction_enum_create_account_with_seed: {
     670           0 :     result = fd_system_program_exec_create_account_with_seed(
     671           0 :         ctx, &instruction->inner.create_account_with_seed );
     672           0 :     break;
     673           0 :   }
     674           0 :   case fd_system_program_instruction_enum_advance_nonce_account: {
     675           0 :     result = fd_system_program_exec_advance_nonce_account( ctx );
     676           0 :     break;
     677           0 :   }
     678           0 :   case fd_system_program_instruction_enum_withdraw_nonce_account: {
     679           0 :     result = fd_system_program_exec_withdraw_nonce_account(
     680           0 :         ctx, instruction->inner.withdraw_nonce_account );
     681           0 :     break;
     682           0 :   }
     683           0 :   case fd_system_program_instruction_enum_initialize_nonce_account: {
     684           0 :     result = fd_system_program_exec_initialize_nonce_account(
     685           0 :         ctx, &instruction->inner.initialize_nonce_account );
     686           0 :     break;
     687           0 :   }
     688           0 :   case fd_system_program_instruction_enum_authorize_nonce_account: {
     689           0 :     result = fd_system_program_exec_authorize_nonce_account(
     690           0 :         ctx, &instruction->inner.authorize_nonce_account );
     691           0 :     break;
     692           0 :   }
     693           0 :   case fd_system_program_instruction_enum_allocate: {
     694           0 :     result = fd_system_program_exec_allocate( ctx, instruction->inner.allocate );
     695           0 :     break;
     696           0 :   }
     697           0 :   case fd_system_program_instruction_enum_allocate_with_seed: {
     698             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L525
     699           0 :     result = fd_system_program_exec_allocate_with_seed(
     700           0 :         ctx, &instruction->inner.allocate_with_seed );
     701           0 :     break;
     702           0 :   }
     703           0 :   case fd_system_program_instruction_enum_assign_with_seed: {
     704             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L545
     705           0 :     result = fd_system_program_exec_assign_with_seed(
     706           0 :         ctx, &instruction->inner.assign_with_seed );
     707           0 :     break;
     708           0 :   }
     709           0 :   case fd_system_program_instruction_enum_transfer_with_seed: {
     710             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L412
     711           0 :     result = fd_system_program_exec_transfer_with_seed(
     712           0 :         ctx, &instruction->inner.transfer_with_seed );
     713           0 :     break;
     714           0 :   }
     715           0 :   case fd_system_program_instruction_enum_upgrade_nonce_account: {
     716             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L491
     717           0 :     result = fd_system_program_exec_upgrade_nonce_account( ctx );
     718           0 :     break;
     719           0 :   }
     720           0 :   }
     721             : 
     722           0 :   return result;
     723           0 : }
     724             : 
     725             : /**********************************************************************/
     726             : /* Public API                                                         */
     727             : /**********************************************************************/
     728             : 
     729             : int
     730             : fd_get_system_account_kind( fd_txn_account_t * account,
     731           0 :                             fd_spad_t *        exec_spad ) {
     732             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L56 */
     733           0 :   if( FD_UNLIKELY( memcmp( fd_txn_account_get_owner( account ), fd_solana_system_program_id.uc, sizeof(fd_pubkey_t) ) ) ) {
     734           0 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     735           0 :   }
     736             : 
     737             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L57-L58 */
     738           0 :   if( FD_LIKELY( !fd_txn_account_get_data_len( account ) ) ) {
     739           0 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_SYSTEM;
     740           0 :   }
     741             : 
     742             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L59 */
     743           0 :   if( FD_UNLIKELY( fd_txn_account_get_data_len( account )!=FD_SYSTEM_PROGRAM_NONCE_DLEN ) ) {
     744           0 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     745           0 :   }
     746             : 
     747             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L60-L64 */
     748           0 :   int err;
     749           0 :   fd_nonce_state_versions_t * versions = fd_bincode_decode_spad(
     750           0 :       nonce_state_versions, exec_spad,
     751           0 :       fd_txn_account_get_data( account ),
     752           0 :       fd_txn_account_get_data_len( account ),
     753           0 :       &err );
     754           0 :   if( FD_UNLIKELY( err ) ) {
     755           0 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     756           0 :   }
     757             : 
     758           0 :   fd_nonce_state_t * state = NULL;
     759           0 :   if( fd_nonce_state_versions_is_current( versions ) ) {
     760           0 :     state = &versions->inner.current;
     761           0 :   } else {
     762           0 :     state = &versions->inner.legacy;
     763           0 :   }
     764             : 
     765           0 :   if( FD_LIKELY( fd_nonce_state_is_initialized( state ) ) ) {
     766           0 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_NONCE;
     767           0 :   }
     768             : 
     769           0 :   return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     770           0 : }

Generated by: LCOV version 1.14