LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_system_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 378 389 97.2 %
Date: 2026-10-22 18:10:43 Functions: 19 19 100.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             : 
       9             : #define FD_FMT_ADDRESS(account_b58, base, out_fmt)                                                 \
      10         464 :   char out_fmt[ 128UL ];                                                                           \
      11         464 :   if( base ) {                                                                                     \
      12         133 :     FD_BASE58_ENCODE_32_BYTES( base->key, base_b58 );                                              \
      13         133 :     snprintf( out_fmt, 128UL, "Address { address: %s, base: Some(%s) }", account_b58, base_b58 );  \
      14         331 :   } else {                                                                                         \
      15         331 :     snprintf( out_fmt, 128UL, "Address { address: %s, base: None }", account_b58 );                \
      16         331 :   }
      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         986 :                      fd_pubkey_t const *   owner ) {
      32             : 
      33         986 :   fd_pubkey_t actual[1];
      34         986 :   do {
      35         986 :     int err = fd_pubkey_create_with_seed(
      36         986 :         ctx,
      37         986 :         base->uc,
      38         986 :         seed,
      39         986 :         seed_sz,
      40         986 :         owner->uc,
      41         986 :         actual->uc );
      42         986 :     if( FD_UNLIKELY( err ) ) return err;
      43         986 :   } while(0);
      44             : 
      45         976 :   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         388 :     FD_BASE58_ENCODE_32_BYTES( expected->key, expected_b58 );
      48         388 :     FD_BASE58_ENCODE_32_BYTES( actual->key,   actual_b58   );
      49         388 :     fd_log_collector_printf_inefficient_max_512( ctx,
      50         388 :       "Create: address %s does not match derived address %s",
      51         388 :       expected_b58, actual_b58 );
      52         388 :     ctx->txn_out->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
      53         388 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      54         388 :   }
      55             : 
      56         588 :   return 0;
      57         976 : }
      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        1382 :                                      ushort                to_acct_idx ) {
      69        1382 :   int err;
      70             : 
      71             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L191-L192 */
      72             : 
      73        1382 :   fd_guarded_borrowed_account_t from = {0};
      74        1382 :   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        1382 :   if( fd_borrowed_account_get_data_len( &from ) != 0UL ) {
      79          49 :     fd_log_collector_msg_literal( ctx, "Transfer: `from` must not carry data" );
      80          49 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
      81          49 :   }
      82             : 
      83             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L197-L205 */
      84             : 
      85        1333 :   if( transfer_amount > fd_borrowed_account_get_lamports( &from ) ) {
      86             :     /* Max msg_sz: 45 - 6 + 20 + 20 = 79 < 127 => we can use printf */
      87          21 :     fd_log_collector_printf_dangerous_max_127( ctx, "Transfer: insufficient lamports %lu, need %lu", fd_borrowed_account_get_lamports( &from ), transfer_amount );
      88          21 :     ctx->txn_out->err.custom_err = FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS;
      89          21 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      90          21 :   }
      91             : 
      92             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L207 */
      93             : 
      94        1312 :   err = fd_borrowed_account_checked_sub_lamports( &from, transfer_amount );
      95             :   /* Note: this err can never happen because of the check above */
      96        1312 :   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        1285 :   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        1285 :   fd_guarded_borrowed_account_t to = {0};
     105        1285 :   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        1285 :   err = fd_borrowed_account_checked_add_lamports( &to, transfer_amount );
     110        1285 :   if( FD_UNLIKELY( err ) ) return err;
     111             : 
     112        1249 :   return 0;
     113        1285 : }
     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         981 :                             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         981 :   int instr_err_code = 0;
     128         981 :   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          21 :     if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
     131             :     /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
     132          21 :     ushort idx_in_txn = ctx->instr->accounts[ from_acct_idx ].index_in_transaction;
     133          21 :     FD_BASE58_ENCODE_32_BYTES( ctx->txn_out->accounts.keys[ idx_in_txn ].uc, key_b58 );
     134          21 :     fd_log_collector_printf_dangerous_max_127( ctx,
     135          21 :       "Transfer: `from` account %s must sign", key_b58 );
     136          21 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     137          21 :   }
     138             : 
     139             :   /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L234-L241 */
     140             : 
     141         960 :   return fd_system_program_transfer_verified( ctx, transfer_amount, from_acct_idx, to_acct_idx );
     142         981 : }
     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         910 :                             fd_pubkey_t const *     base ) {
     155         910 :   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         910 :   if( FD_UNLIKELY( !fd_exec_instr_ctx_any_signed( ctx, authority ) ) ) {
     162             :     /* Max msg_sz: 35 - 2 + 125 = 158 */
     163         121 :     FD_BASE58_ENCODE_32_BYTES( account->acc->pubkey, account_b58 );
     164         121 :     FD_FMT_ADDRESS( account_b58, base, address_fmt );
     165         121 :     fd_log_collector_printf_inefficient_max_512( ctx,
     166         121 :       "Allocate: 'to' account %s must sign",
     167         121 :       address_fmt );
     168         121 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     169         121 :   }
     170             : 
     171             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L87-L96 */
     172             : 
     173         789 :   if( FD_UNLIKELY( ( fd_borrowed_account_get_data_len( account ) != 0UL ) ||
     174         789 :                    ( 0!=memcmp( fd_borrowed_account_get_owner( account ), fd_solana_system_program_id.uc, 32UL ) ) ) ) {
     175             :     /* Max msg_sz: 35 - 2 + 125 = 158 */
     176         190 :     FD_BASE58_ENCODE_32_BYTES( account->acc->pubkey, account_b58 );
     177         190 :     FD_FMT_ADDRESS( account_b58, base, address_fmt );
     178         190 :     fd_log_collector_printf_inefficient_max_512( ctx,
     179         190 :       "Allocate: account %s already in use",
     180         190 :       address_fmt );
     181         190 :     ctx->txn_out->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
     182         190 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     183         190 :   }
     184             : 
     185             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L98-L106 */
     186             : 
     187         599 :   if( FD_UNLIKELY( space > FD_RUNTIME_ACC_SZ_MAX ) ) {
     188             :     /* Max msg_sz: 48 - 6 + 2*20 = 82 < 127 => we can use printf */
     189          15 :     fd_log_collector_printf_dangerous_max_127( ctx,
     190          15 :       "Allocate: requested %lu, max allowed %lu", space, FD_RUNTIME_ACC_SZ_MAX );
     191          15 :     ctx->txn_out->err.custom_err = FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN;
     192          15 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     193          15 :   }
     194             : 
     195             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L108 */
     196             : 
     197         584 :   err = fd_borrowed_account_set_data_length( account, space );
     198         584 :   if( FD_UNLIKELY( err ) ) {
     199          20 :     return err;
     200          20 :   }
     201             : 
     202         564 :   return FD_EXECUTOR_INSTR_SUCCESS;
     203         584 : }
     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        1396 :                           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        1396 :   if( 0==memcmp( fd_borrowed_account_get_owner( account ), owner->uc, sizeof(fd_pubkey_t) ) )
     221          16 :     return 0;
     222             : 
     223             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L125-L128 */
     224             : 
     225        1380 :   if( FD_UNLIKELY( !fd_exec_instr_ctx_any_signed( ctx, authority ) ) ) {
     226             :     /* Max msg_sz: 28 - 2 + 125 = 151 */
     227          63 :     FD_BASE58_ENCODE_32_BYTES( account->acc->pubkey, account_b58 );
     228          63 :     FD_FMT_ADDRESS( account_b58, base, address_fmt );
     229          63 :     fd_log_collector_printf_inefficient_max_512( ctx,
     230          63 :       "Assign: account %s must sign",
     231          63 :       address_fmt );
     232          63 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     233          63 :   }
     234             : 
     235        1317 :   return fd_borrowed_account_set_owner( account, owner );
     236        1380 : }
     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         640 :                                        fd_pubkey_t const *     base ) {
     249             : 
     250         640 :   do {
     251         640 :     int err = fd_system_program_allocate( ctx, account, space, authority, base );
     252         640 :     if( FD_UNLIKELY( err ) ) return err;
     253         640 :   } while(0);
     254         508 :   return fd_system_program_assign( ctx, account, owner, authority, base );
     255             : 
     256         640 : }
     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         567 :                                   fd_pubkey_t const *   base ) {
     272         567 :   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         567 :   do {
     278             :     /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L160-L161 */
     279             : 
     280         567 :     fd_guarded_borrowed_account_t to = {0};
     281         567 :     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         567 :     if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &to ) ) ) {
     286             :       /* Max msg_sz: 41 - 2 + 125 = 164 */
     287          90 :       FD_BASE58_ENCODE_32_BYTES( to.acc->pubkey, to_b58 );
     288          90 :       FD_FMT_ADDRESS( to_b58, base, address_fmt );
     289          90 :       fd_log_collector_printf_inefficient_max_512( ctx,
     290          90 :         "Create Account: account %s already in use",
     291          90 :         address_fmt );
     292          90 :       ctx->txn_out->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
     293          90 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     294          90 :     }
     295             : 
     296             :     /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L171 */
     297             : 
     298         477 :     err = fd_system_program_allocate_and_assign( ctx, &to, space, owner, authority, base );
     299         477 :     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         477 :   } while (0);
     304             : 
     305             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L173-L180 */
     306             : 
     307         382 :   return fd_system_program_transfer( ctx, lamports, from_acct_idx, to_acct_idx );
     308         567 : }
     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          85 :                                                 ushort               from_acct_idx ) {
     320          85 :   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          85 :   do {
     324          85 :     fd_guarded_borrowed_account_t to = {0};
     325          85 :     FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, to_acct_idx, &to );
     326          85 :     err = fd_system_program_allocate_and_assign( ctx, &to, space, owner, to_address, NULL );
     327          85 :     if( FD_UNLIKELY( err ) ) return err;
     328          85 :   } 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          85 :   if( FD_LIKELY( lamports > 0 ) ) {
     332          85 :     return fd_system_program_transfer( ctx, lamports, from_acct_idx, to_acct_idx );
     333          85 :   }
     334             : 
     335           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     336          85 : }
     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         438 :                                        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         438 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
     349           4 :     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         434 :   ushort const from_acct_idx = 0UL;
     355         434 :   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         434 :   fd_pubkey_t const * authority = NULL;
     359         434 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, to_acct_idx, &authority );
     360         434 :   if( FD_UNLIKELY( err ) ) return err;
     361             : 
     362         434 :   return fd_system_program_create_account(
     363         434 :       ctx,
     364         434 :       from_acct_idx,
     365         434 :       to_acct_idx,
     366         434 :       create_acc->lamports,
     367         434 :       create_acc->space,
     368         434 :       &create_acc->owner,
     369         434 :       authority,
     370         434 :       NULL );
     371         434 : }
     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          85 :                                                      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          85 :   if( FD_UNLIKELY( !FD_FEATURE_ACTIVE_BANK( ctx->bank, create_account_allow_prefund ) ) ) {
     381           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     382           0 :   }
     383             : 
     384             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/programs/system/src/system_processor.rs#L541-L547 */
     385          85 :   ushort from_acct_idx = 0;
     386          85 :   if( args->lamports > 0 ) {
     387          85 :     if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( ctx, 2U ) ) ) {
     388           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     389           0 :     }
     390          85 :     from_acct_idx = 1;
     391          85 :   } else {
     392           0 :     if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( ctx, 1U ) ) ) {
     393           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
     394           0 :     }
     395           0 :   }
     396             : 
     397             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.2/programs/system/src/system_processor.rs#L548-L552 */
     398          85 :   ushort const to_acct_idx       = 0;
     399          85 :   fd_pubkey_t const * to_address = NULL;
     400          85 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, to_acct_idx, &to_address );
     401          85 :   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          85 :   return fd_system_program_create_account_allow_prefund(
     405          85 :       ctx, to_acct_idx, args->lamports, args->space, &args->owner, to_address, from_acct_idx );
     406          85 : }
     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         515 :                                fd_pubkey_t const *   owner ) {
     415         515 :   int err;
     416             : 
     417             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L382 */
     418             : 
     419         515 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     420           6 :     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         509 :   fd_guarded_borrowed_account_t account = {0};
     425         509 :   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         509 :   err = fd_system_program_assign( ctx, &account, owner, (fd_pubkey_t*)account.acc->pubkey, NULL );
     433         509 :   if( FD_UNLIKELY( err ) ) return err;
     434             : 
     435             :   /* Implicit drop */
     436             : 
     437         372 :   return 0;
     438         509 : }
     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         522 :                                  ulong                 transfer_amount ) {
     447             : 
     448             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L395 */
     449             : 
     450         522 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
     451          10 :     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         512 :   return fd_system_program_transfer( ctx, transfer_amount, 0UL, 1UL );
     456         522 : }
     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         394 :                                                  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         394 :   if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( ctx, 2UL) ) )
     469           4 :     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         390 :   fd_pubkey_t const * to_address = NULL;
     474         390 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 1UL, &to_address );
     475         390 :   if( FD_UNLIKELY( err ) ) return err;
     476             : 
     477         390 :   do {
     478         390 :     int err = verify_seed_address(
     479         390 :         ctx,
     480         390 :         to_address,
     481         390 :         &args->base,
     482         390 :         (char const *)args->seed,
     483         390 :         args->seed_len,
     484         390 :         &args->owner );
     485         390 :     if( FD_UNLIKELY( err ) ) return err;
     486         390 :   } while(0);
     487             : 
     488             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L368-L379 */
     489             : 
     490         133 :   ushort const from_acct_idx = 0UL;
     491         133 :   ushort const to_acct_idx   = 1UL;
     492         133 :   return fd_system_program_create_account(
     493         133 :       ctx,
     494         133 :       from_acct_idx,
     495         133 :       to_acct_idx,
     496         133 :       args->lamports,
     497         133 :       args->space,
     498         133 :       &args->owner,
     499         133 :       &args->base,
     500         133 :       &args->base );
     501         390 : }
     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         287 :                                  ulong                 space ) {
     510         287 :   int err;
     511             : 
     512             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L505 */
     513             : 
     514         287 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     515          16 :     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         271 :   fd_guarded_borrowed_account_t account = {0};
     519         271 :   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         271 :   err = fd_system_program_allocate( ctx, &account, space, (fd_pubkey_t*)account.acc->pubkey, NULL );
     528         271 :   if( FD_UNLIKELY( err ) ) return err;
     529             : 
     530             :   /* Implicit drop */
     531             : 
     532          56 :   return 0;
     533         271 : }
     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         139 :                                            allocate_with_seed_t const * args ) {
     542         139 :   int err;
     543             : 
     544             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L523 */
     545             : 
     546         139 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     547           2 :     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         137 :   fd_guarded_borrowed_account_t account = {0};
     552         137 :   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         137 :   err = verify_seed_address(
     557         137 :     ctx,
     558         137 :     (fd_pubkey_t*)account.acc->pubkey,
     559         137 :     &args->base,
     560         137 :     (char const *)args->seed,
     561         137 :     args->seed_len,
     562         137 :     &args->owner );
     563         137 :   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          77 :   err = fd_system_program_allocate_and_assign(
     569          77 :     ctx,
     570          77 :     &account,
     571          77 :     args->space,
     572          77 :     &args->owner,
     573          77 :     &args->base,
     574          77 :     &args->base );
     575          77 :   if( FD_UNLIKELY( err ) ) return err;
     576             : 
     577             :   /* Implicit drop */
     578             : 
     579          40 :   return 0;
     580          77 : }
     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         461 :                                          assign_with_seed_t const * args ) {
     589         461 :   int err;
     590             : 
     591             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#543 */
     592             : 
     593         461 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     594           2 :     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         459 :   fd_guarded_borrowed_account_t account = {0};
     599         459 :   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         459 :   err = verify_seed_address(
     604         459 :     ctx,
     605         459 :     (fd_pubkey_t*)account.acc->pubkey,
     606         459 :     &args->base,
     607         459 :     (char const *)args->seed,
     608         459 :     args->seed_len,
     609         459 :     &args->owner );
     610         459 :   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         378 :   err = fd_system_program_assign( ctx, &account, &args->owner, &args->base, &args->base );
     616         378 :   if( FD_UNLIKELY( err ) ) return err;
     617             : 
     618             :   /* Implicit drop */
     619             : 
     620         347 :   return 0;
     621         378 : }
     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         665 :                                            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         665 :   if( FD_UNLIKELY( fd_exec_instr_ctx_check_num_insn_accounts( ctx, 3UL ) ) )
     634           3 :     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         662 :   ushort const from_idx      = 0UL;
     640         662 :   ushort const from_base_idx = 1UL;
     641         662 :   ushort const to_idx        = 2UL;
     642             : 
     643         662 :   int instr_err_code = 0;
     644         662 :   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         114 :     if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
     647             :     /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
     648         114 :     ushort idx_in_txn = ctx->instr->accounts[ from_base_idx ].index_in_transaction;
     649         114 :     FD_BASE58_ENCODE_32_BYTES( ctx->txn_out->accounts.keys[ idx_in_txn ].uc, key_b58 );
     650         114 :     fd_log_collector_printf_dangerous_max_127( ctx,
     651         114 :       "Transfer: 'from' account %s must sign", key_b58 );
     652         114 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     653         114 :   }
     654             : 
     655             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/system/src/system_processor.rs#L267-L274 */
     656             : 
     657         548 :   fd_pubkey_t const * base = NULL;
     658         548 :   int err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, from_base_idx, &base );
     659         548 :   if( FD_UNLIKELY( err ) ) return err;
     660             : 
     661         548 :   fd_pubkey_t address_from_seed[1];
     662         548 :   do {
     663         548 :     int err = fd_pubkey_create_with_seed(
     664         548 :         ctx,
     665         548 :         base->uc,
     666         548 :         (char const *)args->from_seed,
     667         548 :         args->from_seed_len,
     668         548 :         args->from_owner.uc,
     669         548 :         address_from_seed->uc );
     670         548 :     if( FD_UNLIKELY( err ) ) return err;
     671         548 :   } while(0);
     672             : 
     673             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/system/src/system_processor.rs#L276-L287 */
     674         545 :   fd_pubkey_t const * from_key = NULL;
     675         545 :   err = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, from_idx, &from_key );
     676         545 :   if( FD_UNLIKELY( err ) ) return err;
     677             : 
     678         545 :   if( FD_UNLIKELY( 0!=memcmp( address_from_seed->uc,
     679         545 :                               from_key->uc,
     680         545 :                               sizeof(fd_pubkey_t) ) ) ) {
     681             :     /* Log msg_sz can be more or less than 127 bytes */
     682         124 :     FD_BASE58_ENCODE_32_BYTES( from_key->key,          from_key_b58          );
     683         124 :     FD_BASE58_ENCODE_32_BYTES( address_from_seed->key, address_from_seed_b58 );
     684         124 :     fd_log_collector_printf_inefficient_max_512( ctx,
     685         124 :       "Transfer: 'from' address %s does not match derived address %s",
     686         124 :       from_key_b58,
     687         124 :       address_from_seed_b58 );
     688         124 :     ctx->txn_out->err.custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
     689         124 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     690         124 :   }
     691             : 
     692             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L305-L312 */
     693         421 :   return fd_system_program_transfer_verified( ctx, args->lamports, from_idx, to_idx );
     694         545 : }
     695             : 
     696             : int
     697        8334 : fd_system_program_execute( fd_exec_instr_ctx_t * ctx ) {
     698        8334 :   FD_EXEC_CU_UPDATE( ctx, 150UL );
     699             : 
     700        7879 :   fd_system_program_instruction_t instruction;
     701        7879 :   if( FD_UNLIKELY( fd_system_program_instruction_decode( &instruction,
     702        7879 :                                                          ctx->instr->data,
     703        7879 :                                                          ctx->instr->data_sz ) ) ) {
     704        1244 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     705        1244 :   }
     706             : 
     707        6635 :   switch( instruction.discriminant ) {
     708         438 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT:
     709         438 :     return fd_system_program_exec_create_account( ctx, &instruction.inner.create_account );
     710         515 :   case FD_SYSTEM_PROGRAM_INSTR_ASSIGN:
     711         515 :     return fd_system_program_exec_assign( ctx, &instruction.inner.assign );
     712         522 :   case FD_SYSTEM_PROGRAM_INSTR_TRANSFER:
     713         522 :     return fd_system_program_exec_transfer( ctx, instruction.inner.transfer );
     714         394 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_WITH_SEED:
     715         394 :     return fd_system_program_exec_create_account_with_seed( ctx, &instruction.inner.create_account_with_seed );
     716         797 :   case FD_SYSTEM_PROGRAM_INSTR_ADVANCE_NONCE_ACCOUNT:
     717         797 :     return fd_system_program_exec_advance_nonce_account( ctx );
     718         696 :   case FD_SYSTEM_PROGRAM_INSTR_WITHDRAW_NONCE_ACCOUNT:
     719         696 :     return fd_system_program_exec_withdraw_nonce_account( ctx, instruction.inner.withdraw_nonce_account );
     720         490 :   case FD_SYSTEM_PROGRAM_INSTR_INITIALIZE_NONCE_ACCOUNT:
     721         490 :     return fd_system_program_exec_initialize_nonce_account( ctx, &instruction.inner.initialize_nonce_account );
     722         696 :   case FD_SYSTEM_PROGRAM_INSTR_AUTHORIZE_NONCE_ACCOUNT:
     723         696 :     return fd_system_program_exec_authorize_nonce_account( ctx, &instruction.inner.authorize_nonce_account );
     724         287 :   case FD_SYSTEM_PROGRAM_INSTR_ALLOCATE:
     725         287 :     return fd_system_program_exec_allocate( ctx, instruction.inner.allocate );
     726         139 :   case FD_SYSTEM_PROGRAM_INSTR_ALLOCATE_WITH_SEED:
     727         139 :     return fd_system_program_exec_allocate_with_seed( ctx, &instruction.inner.allocate_with_seed );
     728         461 :   case FD_SYSTEM_PROGRAM_INSTR_ASSIGN_WITH_SEED:
     729         461 :     return fd_system_program_exec_assign_with_seed( ctx, &instruction.inner.assign_with_seed );
     730         665 :   case FD_SYSTEM_PROGRAM_INSTR_TRANSFER_WITH_SEED:
     731         665 :     return fd_system_program_exec_transfer_with_seed( ctx, &instruction.inner.transfer_with_seed );
     732         471 :   case FD_SYSTEM_PROGRAM_INSTR_UPGRADE_NONCE_ACCOUNT:
     733         471 :     return fd_system_program_exec_upgrade_nonce_account( ctx );
     734          85 :   case FD_SYSTEM_PROGRAM_INSTR_CREATE_ACCOUNT_ALLOW_PREFUND:
     735          85 :     return fd_system_program_exec_create_account_allow_prefund( ctx, &instruction.inner.create_account_allow_prefund );
     736           0 :   default:
     737           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     738        6635 :   }
     739        6635 : }
     740             : 
     741             : /**********************************************************************/
     742             : /* Public API                                                         */
     743             : /**********************************************************************/
     744             : 
     745             : int
     746        6394 : fd_get_system_account_kind( fd_acc_t const * acc ) {
     747             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L56 */
     748        6394 :   if( FD_UNLIKELY( memcmp( acc->owner, fd_solana_system_program_id.uc, sizeof(fd_pubkey_t) ) ) ) {
     749           5 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     750           5 :   }
     751             : 
     752             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L57-L58 */
     753        6389 :   if( FD_LIKELY( !acc->data_len ) ) {
     754        6364 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_SYSTEM;
     755        6364 :   }
     756             : 
     757             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L59 */
     758          25 :   if( FD_UNLIKELY( acc->data_len!=FD_SYSTEM_PROGRAM_NONCE_DLEN ) ) {
     759           1 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     760           1 :   }
     761             : 
     762             :   /* https://github.com/anza-xyz/solana-sdk/blob/nonce-account%40v2.2.1/nonce-account/src/lib.rs#L60-L64 */
     763          24 :   fd_nonce_state_versions_t state[1];
     764          24 :   if( FD_UNLIKELY( fd_nonce_state_versions_decode( state, acc->data, acc->data_len ) ) ) {
     765           2 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     766           2 :   }
     767             : 
     768          22 :   if( FD_LIKELY( state->kind==FD_NONCE_STATE_INITIALIZED ) ) {
     769          21 :     return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_NONCE;
     770          21 :   }
     771             : 
     772           1 :   return FD_SYSTEM_PROGRAM_NONCE_ACCOUNT_KIND_UNKNOWN;
     773          22 : }

Generated by: LCOV version 1.14