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

Generated by: LCOV version 1.14