LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_system_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 340 353 96.3 %
Date: 2024-11-13 11:58:15 Functions: 16 16 100.0 %

          Line data    Source code
       1             : #include "../fd_executor.h"
       2             : #include "fd_system_program.h"
       3             : #include "../fd_acc_mgr.h"
       4             : #include "../fd_account.h"
       5             : #include "../fd_system_ids.h"
       6             : #include "../fd_pubkey_utils.h"
       7             : #include "../sysvar/fd_sysvar_rent.h"
       8             : #include "../context/fd_exec_epoch_ctx.h"
       9             : #include "../context/fd_exec_slot_ctx.h"
      10             : #include "../context/fd_exec_txn_ctx.h"
      11             : 
      12             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L42-L68
      13             : 
      14             :    Partial port of system_processor::Address::create, only covering the
      15             :    case of the "seed" input actually existing.  Note that this doesn't
      16             :    "create" an address, but rather re-derives from PDA inputs and checks
      17             :    that the result matches some expected value. */
      18             : 
      19             : static int
      20             : verify_seed_address( fd_exec_instr_ctx_t * ctx,
      21             :                      fd_pubkey_t const *   expected,
      22             :                      fd_pubkey_t const *   base,
      23             :                      char const *          seed,
      24             :                      ulong                 seed_sz,
      25        2730 :                      fd_pubkey_t const *   owner ) {
      26             : 
      27        2730 :   fd_pubkey_t actual[1];
      28        2730 :   do {
      29        2730 :     int err = fd_pubkey_create_with_seed(
      30        2730 :         ctx,
      31        2730 :         base->uc,
      32        2730 :         seed,
      33        2730 :         seed_sz,
      34        2730 :         owner->uc,
      35        2730 :         actual->uc );
      36        2730 :     if( FD_UNLIKELY( err ) ) return err;
      37        2730 :   } while(0);
      38             : 
      39        2697 :   if( FD_UNLIKELY( 0!=memcmp( actual->uc, expected->uc, sizeof(fd_pubkey_t) ) ) ) {
      40             :     /* Log msg_sz can be more or less than 127 bytes */
      41        1152 :     fd_log_collector_printf_inefficient_max_512( ctx,
      42        1152 :       "Create: address %s does not match derived address %s",
      43        1152 :       FD_BASE58_ENC_32_ALLOCA( expected ),
      44        1152 :       FD_BASE58_ENC_32_ALLOCA( actual ) );
      45        1152 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
      46        1152 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      47        1152 :   }
      48             : 
      49        1545 :   return 0;
      50        2697 : }
      51             : 
      52             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L183
      53             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L182
      54             : 
      55             :    Matches Solana Labs system_processor::transfer_verified */
      56             : 
      57             : static int
      58             : fd_system_program_transfer_verified( fd_exec_instr_ctx_t * ctx,
      59             :                                      ulong                 transfer_amount,
      60             :                                      ulong                 from_acct_idx,
      61        2343 :                                      ulong                 to_acct_idx ) {
      62             : 
      63             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L191-L192 */
      64             : 
      65        9372 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, from_acct_idx, from) {
      66             : 
      67             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L193-L196 */
      68             : 
      69        2343 :   if( from->const_meta->dlen != 0UL ) {
      70         225 :     fd_log_collector_msg_literal( ctx, "Transfer: `from` must not carry data" );
      71         225 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
      72         225 :   }
      73             : 
      74             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L197-L205 */
      75             : 
      76        2118 :   if( transfer_amount > from->const_meta->info.lamports ) {
      77             :     /* Max msg_sz: 45 - 6 + 20 + 20 = 79 < 127 => we can use printf */
      78          81 :     fd_log_collector_printf_dangerous_max_127( ctx, "Transfer: insufficient lamports %lu, need %lu", from->const_meta->info.lamports, transfer_amount );
      79          81 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS;
      80          81 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      81          81 :   }
      82             : 
      83             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L207 */
      84             : 
      85        2037 :   do {
      86        2037 :     int err = fd_account_checked_sub_lamports( ctx, from_acct_idx, transfer_amount );
      87             :     /* Note: this err can never happen because of the check above */
      88        2037 :     if( FD_UNLIKELY( err ) ) return err;
      89        2037 :   } while(0);
      90             : 
      91             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L208 */
      92             : 
      93        2343 :   } FD_BORROWED_ACCOUNT_DROP( from );
      94             : 
      95             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L209-L210 */
      96             : 
      97        7560 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, to_acct_idx, to ) {
      98             : 
      99             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L211 */
     100             : 
     101        1890 :   do {
     102        1890 :     int err = fd_account_checked_add_lamports( ctx, to_acct_idx, transfer_amount );
     103        1890 :     if( FD_UNLIKELY( err ) ) return err;
     104        1890 :   } while(0);
     105             : 
     106        1890 :   } FD_BORROWED_ACCOUNT_DROP( to );
     107             : 
     108        1785 :   return 0;
     109        1890 : }
     110             : 
     111             : /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L214
     112             : 
     113             :    Matches system_processor::transfer */
     114             : 
     115             : static int
     116             : fd_system_program_transfer( fd_exec_instr_ctx_t * ctx,
     117             :                             ulong                 transfer_amount,
     118             :                             ulong                 from_acct_idx,
     119        1917 :                             ulong                 to_acct_idx ) {
     120             : 
     121             :   /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L222-L232 */
     122             : 
     123        1917 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, from_acct_idx ) ) ) {
     124             :     /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
     125          87 :     fd_log_collector_printf_dangerous_max_127( ctx,
     126          87 :       "Transfer: `from` account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->instr->acct_pubkeys[ from_acct_idx ] ) );
     127          87 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     128          87 :   }
     129             : 
     130             :   /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L234-L241 */
     131             : 
     132        1830 :   return fd_system_program_transfer_verified( ctx, transfer_amount, from_acct_idx, to_acct_idx );
     133        1917 : }
     134             : 
     135             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L71-L111
     136             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L70
     137             : 
     138             :    Based on Solana Labs system_processor::allocate() */
     139             : 
     140             : static int
     141             : fd_system_program_allocate( fd_exec_instr_ctx_t * ctx,
     142             :                             ulong                 acct_idx,
     143             :                             ulong                 space,
     144        2805 :                             fd_pubkey_t const *   authority ) {
     145             : 
     146             :   /* Assumes that acct_idx was bounds checked */
     147             : 
     148        2805 :   fd_borrowed_account_t * account = ctx->instr->borrowed_accounts[ acct_idx ];
     149             : 
     150             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L78-L85 */
     151             : 
     152        2805 :   if( FD_UNLIKELY( !fd_instr_any_signed( ctx->instr, authority ) ) ) {
     153             :     /* Max msg_sz: 35 - 2 + 45 = 78 < 127 => we can use printf */
     154         336 :     fd_log_collector_printf_dangerous_max_127( ctx,
     155         336 :       "Allocate: 'to' account %s must sign", FD_BASE58_ENC_32_ALLOCA( authority ) );
     156         336 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     157         336 :   }
     158             : 
     159             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L87-L96 */
     160             : 
     161        2469 :   if( FD_UNLIKELY( ( account->const_meta->dlen != 0UL ) |
     162        2469 :                    ( 0!=memcmp( account->const_meta->info.owner, fd_solana_system_program_id.uc, 32UL ) ) ) ) {
     163             :     /* Max msg_sz: 35 - 2 + 45 = 78 < 127 => we can use printf */
     164         600 :     fd_log_collector_printf_dangerous_max_127( ctx,
     165         600 :       "Allocate: account %s already in use", FD_BASE58_ENC_32_ALLOCA( account->pubkey ) );
     166         600 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
     167         600 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     168         600 :   }
     169             : 
     170             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L98-L106 */
     171             : 
     172        1869 :   if( FD_UNLIKELY( space > FD_ACC_SZ_MAX ) ) {
     173             :     /* Max msg_sz: 48 - 6 + 2*20 = 82 < 127 => we can use printf */
     174          48 :     fd_log_collector_printf_dangerous_max_127( ctx,
     175          48 :       "Allocate: requested %lu, max allowed %lu", space, FD_ACC_SZ_MAX );
     176          48 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN;
     177          48 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     178          48 :   }
     179             : 
     180             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L108 */
     181             : 
     182        1821 :   do {
     183        1821 :     int err = fd_account_set_data_length( ctx, acct_idx, space );
     184        1821 :     if( FD_UNLIKELY( err ) ) {
     185          87 :       return err;
     186          87 :     }
     187        1821 :   } while(0);
     188             : 
     189        1734 :   return FD_EXECUTOR_INSTR_SUCCESS;
     190        1821 : }
     191             : 
     192             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L113-L131
     193             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L112
     194             : 
     195             :    Based on Solana Labs system_processor::assign() */
     196             : 
     197             : static int
     198             : fd_system_program_assign( fd_exec_instr_ctx_t * ctx,
     199             :                           ulong                 acct_idx,
     200             :                           fd_pubkey_t const *   owner,
     201        2463 :                           fd_pubkey_t const *   authority ) {
     202             : 
     203             :   /* Assumes addr_idx was bounds checked */
     204             : 
     205        2463 :   fd_borrowed_account_t * account = ctx->instr->borrowed_accounts[ acct_idx ];
     206             : 
     207             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L121-L123 */
     208             : 
     209        2463 :   if( 0==memcmp( account->const_meta->info.owner, owner->uc, sizeof(fd_pubkey_t) ) )
     210          72 :     return 0;
     211             : 
     212             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L125-L128 */
     213             : 
     214        2391 :   if( FD_UNLIKELY( !fd_instr_any_signed( ctx->instr, authority ) ) ) {
     215             :     /* Max msg_sz: 28 - 2 + 45 = 71 < 127 => we can use printf */
     216         159 :     fd_log_collector_printf_dangerous_max_127( ctx,
     217         159 :       "Assign: account %s must sign", FD_BASE58_ENC_32_ALLOCA( authority ) );
     218         159 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     219         159 :   }
     220             : 
     221             :   /* Implicit writable acquire */
     222        2232 :   do {
     223        2232 :     int err = fd_instr_borrowed_account_modify_idx( ctx, acct_idx, 0UL, &account );
     224        2232 :     if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
     225        2232 :   } while(0);
     226             : 
     227        2232 :   return fd_account_set_owner( ctx, acct_idx, owner );
     228        2232 : }
     229             : 
     230             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L133-L143
     231             : 
     232             :    Based on Solana Labs system_processor::allocate_and_assign() */
     233             : 
     234             : static int
     235             : fd_system_program_allocate_and_assign( fd_exec_instr_ctx_t * ctx,
     236             :                                        ulong                 acct_idx,
     237             :                                        ulong                 space,
     238             :                                        fd_pubkey_t const *   owner,
     239        1779 :                                        fd_pubkey_t const *   authority ) {
     240             : 
     241        1779 :   do {
     242        1779 :     int err = fd_system_program_allocate( ctx, acct_idx, space, authority );
     243        1779 :     if( FD_UNLIKELY( err ) ) return err;
     244        1779 :   } while(0);
     245        1362 :   return fd_system_program_assign( ctx, acct_idx, owner, authority );
     246             : 
     247        1779 : }
     248             : 
     249             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L146-L181
     250             :    https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L145
     251             : 
     252             :    Matches Solana Labs system_processor::create_account() */
     253             : 
     254             : static int
     255             : fd_system_program_create_account( fd_exec_instr_ctx_t * ctx,
     256             :                                   ulong                 from_acct_idx,
     257             :                                   ulong                 to_acct_idx,
     258             :                                   ulong                 lamports,
     259             :                                   ulong                 space,
     260             :                                   fd_pubkey_t const *   owner,
     261        1530 :                                   fd_pubkey_t const *   authority ) {
     262             : 
     263             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L160-L161 */
     264             : 
     265        6120 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, to_acct_idx, to ) {
     266             : 
     267             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L162-L169 */
     268             : 
     269        1530 :   if( FD_UNLIKELY( to->const_meta->info.lamports ) ) {
     270             :     /* Max msg_sz: 41 - 2 + 45 = 84 < 127 => we can use printf */
     271         204 :     fd_log_collector_printf_dangerous_max_127( ctx,
     272         204 :       "Create Account: account %s already in use", FD_BASE58_ENC_32_ALLOCA( to->pubkey ) );
     273         204 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
     274         204 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     275         204 :   }
     276             : 
     277             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L171 */
     278             : 
     279        1326 :   do {
     280        1326 :     int err = fd_system_program_allocate_and_assign( ctx, to_acct_idx, space, owner, authority );
     281        1326 :     if( FD_UNLIKELY( err ) ) return err;
     282        1326 :   } while(0);
     283             : 
     284             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L172
     285             :      Implicit drop */
     286             : 
     287        1530 :   } FD_BORROWED_ACCOUNT_DROP( to );
     288             : 
     289             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L173-L180 */
     290             : 
     291        1005 :   return fd_system_program_transfer( ctx, lamports, from_acct_idx, to_acct_idx );
     292        1530 : }
     293             : 
     294             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L327-L352
     295             : 
     296             :    Matches Solana Labs system_processor SystemInstruction::CreateAccount { ... } => { ... } */
     297             : 
     298             : int
     299             : fd_system_program_exec_create_account( fd_exec_instr_ctx_t *                                  ctx,
     300         801 :                                        fd_system_program_instruction_create_account_t const * create_acc ) {
     301             : 
     302             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L332 */
     303             : 
     304         801 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
     305          12 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     306             : 
     307             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L333-L339
     308             :      Authorization check is lifted out from 'allocate' to here. */
     309             : 
     310         789 :   ulong const from_acct_idx    = 0UL;
     311         789 :   ulong const to_acct_idx      = 1UL;
     312         789 :   return fd_system_program_create_account(
     313         789 :       ctx,
     314         789 :       from_acct_idx,
     315         789 :       to_acct_idx,
     316         789 :       create_acc->lamports,
     317         789 :       create_acc->space,
     318         789 :       &create_acc->owner,
     319         789 :       &ctx->instr->acct_pubkeys[to_acct_idx] );
     320         801 : }
     321             : 
     322             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L381-L393
     323             : 
     324             :    Matches Solana Labs system_processor SystemInstruction::Assign { ... } => { ... } */
     325             : 
     326             : int
     327             : fd_system_program_exec_assign( fd_exec_instr_ctx_t * ctx,
     328         771 :                                fd_pubkey_t const *   owner ) {
     329             : 
     330             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L382 */
     331             : 
     332         771 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     333          21 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     334             : 
     335             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L383-L384 */
     336             : 
     337        3000 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, 0, account ) {
     338             : 
     339             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L385-L391
     340             :      system_processor::Address::create eliminated (dead code) */
     341             : 
     342             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L392 */
     343             : 
     344         750 :   ulong const acct_idx = 0UL;
     345         750 :   do {
     346         750 :     int err = fd_system_program_assign( ctx, acct_idx, owner, account->pubkey );
     347         750 :     if( FD_UNLIKELY( err ) ) return err;
     348         750 :   } while(0);
     349             : 
     350             :   /* Implicit drop */
     351         750 :   } FD_BORROWED_ACCOUNT_DROP( account );
     352             : 
     353         327 :   return 0;
     354         750 : }
     355             : 
     356             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L394-L404
     357             : 
     358             :    Matches Solana Labs system_processor SystemInstruction::Transfer { ... } => { ... } */
     359             : 
     360             : int
     361             : fd_system_program_exec_transfer( fd_exec_instr_ctx_t * ctx,
     362         945 :                                  ulong                 transfer_amount ) {
     363             : 
     364             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L395 */
     365             : 
     366         945 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
     367          33 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     368             : 
     369             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L396-L402 */
     370             : 
     371         912 :   return fd_system_program_transfer( ctx, transfer_amount, 0UL, 1UL );
     372         945 : }
     373             : 
     374             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L353
     375             : 
     376             :    Matches Solana Labs system_processor SystemInstruction::CreateAccountWithSeed { ... } => { ... } */
     377             : 
     378             : int
     379             : fd_system_program_exec_create_account_with_seed( fd_exec_instr_ctx_t *                                            ctx,
     380        1518 :                                                  fd_system_program_instruction_create_account_with_seed_t const * args ) {
     381             : 
     382        1518 :   fd_instr_info_t const * instr = ctx->instr;
     383             : 
     384             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L360 */
     385             : 
     386        1518 :   if( FD_UNLIKELY( instr->acct_cnt < 2 ) )
     387          12 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     388             : 
     389             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L361-L367 */
     390             : 
     391        1506 :   do {
     392        1506 :     int err = verify_seed_address(
     393        1506 :         ctx,
     394        1506 :         &instr->acct_pubkeys[1],
     395        1506 :         &args->base,
     396        1506 :         (char const *)args->seed,
     397        1506 :         args->seed_len,
     398        1506 :         &args->owner );
     399        1506 :     if( FD_UNLIKELY( err ) ) return err;
     400        1506 :   } while(0);
     401             : 
     402             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L368-L379 */
     403             : 
     404         741 :   ulong const from_acct_idx    = 0UL;
     405         741 :   ulong const to_acct_idx      = 1UL;
     406         741 :   return fd_system_program_create_account(
     407         741 :       ctx,
     408         741 :       from_acct_idx,
     409         741 :       to_acct_idx,
     410         741 :       args->lamports,
     411         741 :       args->space,
     412         741 :       &args->owner,
     413         741 :       &args->base );
     414        1506 : }
     415             : 
     416             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L504-L516
     417             : 
     418             :    Matches Solana Labs system_processor SystemInstruction::Allocate { ... } => { ... } */
     419             : 
     420             : int
     421             : fd_system_program_exec_allocate( fd_exec_instr_ctx_t * ctx,
     422        1077 :                                  ulong                 space ) {
     423             : 
     424             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L505 */
     425             : 
     426        1077 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     427          51 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     428             : 
     429             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L506-L507 */
     430             : 
     431        4104 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, 0, account ) {
     432             : 
     433             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L508-L514
     434             :      system_processor::Address::create eliminated (dead code) */
     435             : 
     436             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L515
     437             :      Authorization check is lifted out from 'allocate' to here. */
     438             : 
     439        1026 :   ulong const acct_idx = 0UL;
     440        1026 :   do {
     441        1026 :     int err = fd_system_program_allocate( ctx, acct_idx, space, account->pubkey );
     442        1026 :     if( FD_UNLIKELY( err ) ) return err;
     443        1026 :   } while(0);
     444             : 
     445             :   /* Implicit drop */
     446        1026 :    } FD_BORROWED_ACCOUNT_DROP( account );
     447             : 
     448         372 :   return 0;
     449        1026 : }
     450             : 
     451             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L517-L541
     452             : 
     453             :    Matches Solana Labs system_processor SystemInstruction::AllocateWithSeed { ... } => { ... } */
     454             : 
     455             : int
     456             : fd_system_program_exec_allocate_with_seed( fd_exec_instr_ctx_t *                                      ctx,
     457         633 :                                            fd_system_program_instruction_allocate_with_seed_t const * args ) {
     458             : 
     459             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L523 */
     460             : 
     461         633 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     462           6 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     463             : 
     464             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#524-525 */
     465             : 
     466        2508 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, 0, account ) {
     467             : 
     468             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L526-L532 */
     469             : 
     470         627 :   do {
     471         627 :     int err = verify_seed_address(
     472         627 :         ctx,
     473         627 :         account->pubkey,
     474         627 :         &args->base,
     475         627 :         (char const *)args->seed,
     476         627 :         args->seed_len,
     477         627 :         &args->owner );
     478         627 :     if( FD_UNLIKELY( err ) ) return err;
     479         627 :   } while(0);
     480             : 
     481             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L533-L540
     482             :      Authorization check is lifted out from 'allocate' to here. */
     483             : 
     484         453 :   ulong const acct_idx = 0UL;
     485         453 :   do {
     486         453 :     int err = fd_system_program_allocate_and_assign(
     487         453 :         ctx,
     488         453 :         acct_idx,
     489         453 :         args->space,
     490         453 :         &args->owner,
     491         453 :         &args->base );
     492         453 :     if( FD_UNLIKELY( err ) ) return err;
     493         453 :   } while(0);
     494             : 
     495             :   /* Implicit drop */
     496         627 :   } FD_BORROWED_ACCOUNT_DROP( account );
     497             : 
     498         357 :   return 0;
     499         627 : }
     500             : 
     501             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L542-L554
     502             : 
     503             :    Matches Solana Labs system_processor SystemInstruction::AssignWithSeed { ... } => { ... } */
     504             : 
     505             : int
     506             : fd_system_program_exec_assign_with_seed( fd_exec_instr_ctx_t *                                    ctx,
     507         603 :                                          fd_system_program_instruction_assign_with_seed_t const * args ) {
     508             : 
     509             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#543 */
     510             : 
     511         603 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
     512           6 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     513             : 
     514             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L544-L545 */
     515             : 
     516        2388 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, 0, account ) {
     517             : 
     518             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L546-L552 */
     519             : 
     520         597 :   do {
     521         597 :     int err = verify_seed_address(
     522         597 :         ctx,
     523         597 :         account->pubkey,
     524         597 :         &args->base,
     525         597 :         (char const *)args->seed,
     526         597 :         args->seed_len,
     527         597 :         &args->owner );
     528         597 :     if( FD_UNLIKELY( err ) ) return err;
     529         597 :   } while(0);
     530             : 
     531             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L553
     532             :      Authorization check is lifted out from 'assign' to here. */
     533             : 
     534         351 :   ulong const acct_idx = 0UL;
     535         351 :   do {
     536         351 :     int err = fd_system_program_assign( ctx, acct_idx, &args->owner, &args->base );
     537         351 :     if( FD_UNLIKELY( err ) ) return err;
     538         351 :   } while(0);
     539             : 
     540             :   /* Implicit drop */
     541         597 :   } FD_BORROWED_ACCOUNT_DROP( account );
     542             : 
     543         282 :   return 0;
     544         597 : }
     545             : 
     546             : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L405-L422
     547             : 
     548             :    Matches Solana Labs system_processor SystemInstruction::TransferWithSeed { ... } => { ... } */
     549             : 
     550             : int
     551             : fd_system_program_exec_transfer_with_seed( fd_exec_instr_ctx_t *                                      ctx,
     552        1239 :                                            fd_system_program_instruction_transfer_with_seed_t const * args ) {
     553             : 
     554             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L410 */
     555             : 
     556        1239 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 3 ) )
     557           9 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     558             : 
     559             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L411-L421
     560             :      Inlined call to system_processor::transfer_with_seed */
     561             : 
     562        1230 :   ulong const from_idx      = 0UL;
     563        1230 :   ulong const from_base_idx = 1UL;
     564        1230 :   ulong const to_idx        = 2UL;
     565             : 
     566        1230 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, from_base_idx ) ) ) {
     567             :     /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
     568         342 :     fd_log_collector_printf_dangerous_max_127( ctx,
     569         342 :       "Transfer: 'from' account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->instr->acct_pubkeys[ from_base_idx ] ) );
     570         342 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     571         342 :   }
     572             : 
     573             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L283-L290 */
     574             : 
     575         888 :   fd_pubkey_t address_from_seed[1];
     576         888 :   do {
     577         888 :     int err = fd_pubkey_create_with_seed(
     578         888 :         ctx,
     579         888 :         ctx->instr->acct_pubkeys[ from_base_idx ].uc,
     580         888 :         (char const *)args->from_seed,
     581         888 :         args->from_seed_len,
     582         888 :         args->from_owner.uc,
     583         888 :         address_from_seed->uc );
     584         888 :     if( FD_UNLIKELY( err ) ) return err;
     585         888 :   } while(0);
     586             : 
     587             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L292-L303 */
     588             : 
     589         879 :   if( FD_UNLIKELY( 0!=memcmp( address_from_seed->uc,
     590         879 :                               ctx->instr->acct_pubkeys[ from_idx ].uc,
     591         879 :                               sizeof(fd_pubkey_t) ) ) ) {
     592             :     /* Log msg_sz can be more or less than 127 bytes */
     593         366 :     fd_log_collector_printf_inefficient_max_512( ctx,
     594         366 :       "Transfer: 'from' address %s does not match derived address %s",
     595         366 :       FD_BASE58_ENC_32_ALLOCA( &ctx->instr->acct_pubkeys[ from_idx ] ),
     596         366 :       FD_BASE58_ENC_32_ALLOCA( address_from_seed ) );
     597         366 :     ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
     598         366 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     599         366 :   }
     600             : 
     601             :   /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L305-L312 */
     602         513 :   return fd_system_program_transfer_verified( ctx, args->lamports, from_idx, to_idx );
     603         879 : }
     604             : 
     605             : int
     606       18303 : fd_system_program_execute( fd_exec_instr_ctx_t * ctx ) {
     607       18303 :   FD_EXEC_CU_UPDATE( ctx, 150UL );
     608             : 
     609             :   /* Deserialize the SystemInstruction enum */
     610       16926 :   uchar * data = ctx->instr->data;
     611       16926 :   if( FD_UNLIKELY( data==NULL ) ) {
     612         816 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     613         816 :   }
     614             : 
     615       16110 :   fd_system_program_instruction_t instruction;
     616       16110 :   fd_bincode_decode_ctx_t decode =
     617       16110 :     { .data    = data,
     618       16110 :       .dataend = data + ctx->instr->data_sz,
     619       16110 :       .valloc  = fd_scratch_virtual() };
     620             :   /* Fail if the number of bytes consumed by deserialize exceeds 1232 */
     621       16110 :   if( fd_system_program_instruction_decode( &instruction, &decode ) ||
     622       16110 :       (ulong)data + 1232UL < (ulong)decode.data )
     623        3003 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     624             : 
     625       13107 :   int result = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     626             : 
     627       13107 :   switch( instruction.discriminant ) {
     628         801 :   case fd_system_program_instruction_enum_create_account: {
     629         801 :     result = fd_system_program_exec_create_account(
     630         801 :         ctx, &instruction.inner.create_account );
     631         801 :     break;
     632           0 :   }
     633         771 :   case fd_system_program_instruction_enum_assign: {
     634         771 :     result = fd_system_program_exec_assign(
     635         771 :         ctx, &instruction.inner.assign );
     636         771 :     break;
     637           0 :   }
     638         945 :   case fd_system_program_instruction_enum_transfer: {
     639         945 :     result = fd_system_program_exec_transfer(
     640         945 :         ctx, instruction.inner.transfer );
     641         945 :     break;
     642           0 :   }
     643        1518 :   case fd_system_program_instruction_enum_create_account_with_seed: {
     644        1518 :     result = fd_system_program_exec_create_account_with_seed(
     645        1518 :         ctx, &instruction.inner.create_account_with_seed );
     646        1518 :     break;
     647           0 :   }
     648        1746 :   case fd_system_program_instruction_enum_advance_nonce_account: {
     649        1746 :     result = fd_system_program_exec_advance_nonce_account( ctx );
     650        1746 :     break;
     651           0 :   }
     652        1359 :   case fd_system_program_instruction_enum_withdraw_nonce_account: {
     653        1359 :     result = fd_system_program_exec_withdraw_nonce_account(
     654        1359 :         ctx, instruction.inner.withdraw_nonce_account );
     655        1359 :     break;
     656           0 :   }
     657         582 :   case fd_system_program_instruction_enum_initialize_nonce_account: {
     658         582 :     result = fd_system_program_exec_initialize_nonce_account(
     659         582 :         ctx, &instruction.inner.initialize_nonce_account );
     660         582 :     break;
     661           0 :   }
     662        1221 :   case fd_system_program_instruction_enum_authorize_nonce_account: {
     663        1221 :     result = fd_system_program_exec_authorize_nonce_account(
     664        1221 :         ctx, &instruction.inner.authorize_nonce_account );
     665        1221 :     break;
     666           0 :   }
     667        1077 :   case fd_system_program_instruction_enum_allocate: {
     668        1077 :     result = fd_system_program_exec_allocate( ctx, instruction.inner.allocate );
     669        1077 :     break;
     670           0 :   }
     671         633 :   case fd_system_program_instruction_enum_allocate_with_seed: {
     672             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L525
     673         633 :     result = fd_system_program_exec_allocate_with_seed(
     674         633 :         ctx, &instruction.inner.allocate_with_seed );
     675         633 :     break;
     676           0 :   }
     677         603 :   case fd_system_program_instruction_enum_assign_with_seed: {
     678             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L545
     679         603 :     result = fd_system_program_exec_assign_with_seed(
     680         603 :         ctx, &instruction.inner.assign_with_seed );
     681         603 :     break;
     682           0 :   }
     683        1239 :   case fd_system_program_instruction_enum_transfer_with_seed: {
     684             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L412
     685        1239 :     result = fd_system_program_exec_transfer_with_seed(
     686        1239 :         ctx, &instruction.inner.transfer_with_seed );
     687        1239 :     break;
     688           0 :   }
     689         612 :   case fd_system_program_instruction_enum_upgrade_nonce_account: {
     690             :     // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L491
     691         612 :     result = fd_system_program_exec_upgrade_nonce_account( ctx );
     692         612 :     break;
     693           0 :   }
     694       13107 :   }
     695             : 
     696       13107 :   fd_bincode_destroy_ctx_t destroy = { .valloc = ctx->valloc };
     697       13107 :   fd_system_program_instruction_destroy( &instruction, &destroy );
     698       13107 :   return result;
     699       13107 : }

Generated by: LCOV version 1.14