LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_system_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 157 390 40.3 %
Date: 2026-05-15 07:18:56 Functions: 11 19 57.9 %

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

Generated by: LCOV version 1.14