LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_borrowed_account.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 66 108 61.1 %
Date: 2026-07-11 05:27:41 Functions: 7 8 87.5 %

          Line data    Source code
       1             : #include "fd_borrowed_account.h"
       2             : #include "fd_runtime.h"
       3             : 
       4             : int
       5             : fd_borrowed_account_get_data_mut( fd_borrowed_account_t * borrowed_acct,
       6             :                                   uchar * *               data_out,
       7          24 :                                   ulong *                 dlen_out ) {
       8             : 
       9             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L824 */
      10          24 :   int err;
      11          24 :   fd_borrowed_account_can_data_be_changed( borrowed_acct, &err );
      12          24 :   if( FD_UNLIKELY( err ) ) {
      13           0 :     return err;
      14           0 :   }
      15             : 
      16          24 :   if ( data_out != NULL )
      17          24 :     *data_out = borrowed_acct->acc->data;
      18          24 :   if ( dlen_out != NULL )
      19          24 :     *dlen_out = borrowed_acct->acc->data_len;
      20             : 
      21          24 :   return FD_EXECUTOR_INSTR_SUCCESS;
      22          24 : }
      23             : 
      24             : int
      25             : fd_borrowed_account_set_owner( fd_borrowed_account_t * borrowed_acct,
      26         333 :                                fd_pubkey_t const *     owner ) {
      27             : 
      28             :   /* Only the owner can assign a new owner
      29             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L741 */
      30         333 :   if( FD_UNLIKELY( !fd_borrowed_account_is_owned_by_current_program( borrowed_acct ) ) ) {
      31           0 :     return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID;
      32           0 :   }
      33             : 
      34             :   /* And only if the account is writable
      35             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L745 */
      36         333 :   if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) {
      37           0 :     return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID;
      38           0 :   }
      39             : 
      40             :   /* And only if the data is zero-initialized or empty
      41             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L753 */
      42         333 :   if( FD_UNLIKELY( !fd_borrowed_account_is_zeroed( borrowed_acct ) ) ) {
      43           0 :     return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID;
      44           0 :   }
      45             : 
      46             :   /* Don't copy the account if the owner does not change
      47             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L757 */
      48         333 :   if( !memcmp( borrowed_acct->acc->owner, owner, sizeof(fd_pubkey_t) ) ) {
      49           0 :     return FD_EXECUTOR_INSTR_SUCCESS;
      50           0 :   }
      51             : 
      52             :   /* Agave self.touch() is a no-op */
      53             : 
      54             :   /* Copy into owner
      55             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L761 */
      56         333 :   fd_memcpy( borrowed_acct->acc->owner, owner, sizeof(fd_pubkey_t) );
      57         333 :   return FD_EXECUTOR_INSTR_SUCCESS;
      58         333 : }
      59             : 
      60             : /* Overwrites the number of lamports of this account (transaction wide)
      61             :    https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L773 */
      62             : int
      63             : fd_borrowed_account_set_lamports( fd_borrowed_account_t * borrowed_acct,
      64         357 :                                   ulong                   lamports ) {
      65             : 
      66             :   /* An account not owned by the program cannot have its blanace decrease
      67             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L775 */
      68         357 :   if( FD_UNLIKELY( (!fd_borrowed_account_is_owned_by_current_program( borrowed_acct )) &&
      69         357 :                    (lamports<borrowed_acct->acc->lamports) ) ) {
      70           0 :     return FD_EXECUTOR_INSTR_ERR_EXTERNAL_ACCOUNT_LAMPORT_SPEND;
      71           0 :   }
      72             : 
      73             :   /* The balance of read-only may not change
      74             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L779 */
      75         357 :   if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) {
      76           0 :     return FD_EXECUTOR_INSTR_ERR_READONLY_LAMPORT_CHANGE;
      77           0 :   }
      78             : 
      79             :   /* Don't copy the account if the lamports do not change
      80             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L787 */
      81         357 :   if( borrowed_acct->acc->lamports==lamports ) {
      82           0 :     return FD_EXECUTOR_INSTR_SUCCESS;
      83           0 :   }
      84             : 
      85             :   /* Agave self.touch() is a no-op */
      86             : 
      87         357 :   borrowed_acct->acc->lamports = lamports;
      88         357 :   return FD_EXECUTOR_INSTR_SUCCESS;
      89         357 : }
      90             : 
      91             : int
      92             : fd_borrowed_account_set_data_from_slice( fd_borrowed_account_t * borrowed_acct,
      93             :                                          uchar const *           data,
      94        4632 :                                          ulong                   data_sz ) {
      95             : 
      96             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/transaction-context/src/instruction_accounts.rs#L181-L184 */
      97        4632 :   int err;
      98        4632 :   if ( FD_UNLIKELY( !fd_borrowed_account_can_data_be_resized( borrowed_acct, data_sz, &err ) ) ) {
      99           0 :     return err;
     100           0 :   }
     101             : 
     102             :   /* Agave self.touch() is a no-op */
     103             : 
     104             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L868 */
     105        4632 :   if( FD_UNLIKELY( !fd_borrowed_account_update_accounts_resize_delta( borrowed_acct, data_sz, &err ) ) ) {
     106           0 :     return err;
     107           0 :   }
     108             : 
     109             :   /* AccountSharedData::set_data_from_slice() */
     110        4632 :   borrowed_acct->acc->data_len = (uint)data_sz;
     111        4632 :   fd_memcpy( borrowed_acct->acc->data, data, data_sz );
     112             : 
     113        4632 :   return FD_EXECUTOR_INSTR_SUCCESS;
     114        4632 : }
     115             : 
     116             : int
     117             : fd_borrowed_account_set_data_length( fd_borrowed_account_t * borrowed_acct,
     118         225 :                                      ulong                   new_len ) {
     119         225 :   int err = FD_EXECUTOR_INSTR_SUCCESS;
     120             : 
     121             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/transaction-context/src/instruction_accounts.rs#L197-L204 */
     122         225 :   if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_resized( borrowed_acct, new_len, &err ) ) ) {
     123           3 :     return err;
     124           3 :   }
     125             : 
     126         222 :   ulong old_len = borrowed_acct->acc->data_len;
     127             : 
     128             :   /* Don't copy the account if the length does not change
     129             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L886 */
     130         222 :   if( old_len==new_len ) {
     131           3 :     return FD_EXECUTOR_INSTR_SUCCESS;
     132           3 :   }
     133             : 
     134             :   /* Agave self.touch() is a no-op */
     135             : 
     136             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L890 */
     137         219 :   if( FD_UNLIKELY( !fd_borrowed_account_update_accounts_resize_delta( borrowed_acct, new_len, &err ) ) ) {
     138           0 :     return err;
     139           0 :   }
     140             : 
     141             :   /* Resize the account
     142             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L891 */
     143         219 :   ulong memset_sz = fd_ulong_sat_sub( new_len, borrowed_acct->acc->data_len );
     144         219 :   fd_memset( borrowed_acct->acc->data+borrowed_acct->acc->data_len, 0, memset_sz );
     145         219 :   borrowed_acct->acc->data_len = (uint)new_len;
     146             : 
     147         219 :   return FD_EXECUTOR_INSTR_SUCCESS;
     148         219 : }
     149             : 
     150             : int
     151             : fd_borrowed_account_set_executable( fd_borrowed_account_t * borrowed_acct,
     152           0 :                                     int                     is_executable ) {
     153             :   /* To become executable an account must be rent exempt
     154             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1003-L1006 */
     155           0 :   fd_rent_t const * rent = &borrowed_acct->instr_ctx->bank->f.rent;
     156           0 :   if( FD_UNLIKELY( borrowed_acct->acc->lamports<fd_rent_exempt_minimum_balance( rent, borrowed_acct->acc->data_len ) ) ) {
     157           0 :     return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_ACCOUNT_NOT_RENT_EXEMPT;
     158           0 :   }
     159             : 
     160             :   /* Only the owner can set the exectuable flag
     161             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1011 */
     162           0 :   if( FD_UNLIKELY( !fd_borrowed_account_is_owned_by_current_program( borrowed_acct ) ) ) {
     163           0 :     return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED;
     164           0 :   }
     165             : 
     166             :   /* And only if the account is writable
     167             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1015 */
     168           0 :   if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) {
     169           0 :     return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED;
     170           0 :   }
     171             : 
     172             :   /* Don't copy the account if the exectuable flag does not change
     173             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1023 */
     174           0 :   if( fd_borrowed_account_is_executable( borrowed_acct ) == is_executable ) {
     175           0 :     return FD_EXECUTOR_INSTR_SUCCESS;
     176           0 :   }
     177             : 
     178             :   /* Agave self.touch() is a no-op */
     179             : 
     180             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1027 */
     181           0 :   borrowed_acct->acc->executable = !!is_executable;
     182             : 
     183           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     184           0 : }
     185             : 
     186             : int
     187             : fd_borrowed_account_update_accounts_resize_delta( fd_borrowed_account_t * borrowed_acct,
     188             :                                                   ulong                   new_len,
     189        4851 :                                                   int *                   err ) {
     190        4851 :   fd_exec_instr_ctx_t const * instr_ctx  = borrowed_acct->instr_ctx;
     191        4851 :   long                        size_delta = fd_long_sat_sub( (long)new_len, (long)borrowed_acct->acc->data_len );
     192             : 
     193             :   /* https://github.com/anza-xyz/agave/blob/v3.1.8/transaction-context/src/transaction_accounts.rs#L303-L313 */
     194        4851 :   instr_ctx->txn_out->details.accounts_resize_delta = fd_long_sat_add( instr_ctx->txn_out->details.accounts_resize_delta, size_delta );
     195        4851 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     196        4851 :   return 1;
     197        4851 : }
     198             : 
     199             : int
     200             : fd_borrowed_account_can_data_be_resized( fd_borrowed_account_t const * borrowed_acct,
     201             :                                          ulong                         new_length,
     202        8511 :                                          int *                         err ) {
     203             :   /* The new length can not exceed the maximum permitted length
     204             :      https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/transaction-context/src/transaction_accounts.rs#L319-L322 */
     205        8511 :   if( FD_UNLIKELY( new_length>MAX_PERMITTED_DATA_LENGTH ) ) {
     206           0 :     *err = FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     207           0 :     return 0;
     208           0 :   }
     209             : 
     210             :   /* The resize can not exceed the per-transaction maximum
     211             :      https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/transaction-context/src/transaction_accounts.rs#L323-L329 */
     212        8511 :   long length_delta              = fd_long_sat_sub( (long)new_length, (long)borrowed_acct->acc->data_len );
     213        8511 :   long new_accounts_resize_delta = fd_long_sat_add( borrowed_acct->instr_ctx->txn_out->details.accounts_resize_delta, length_delta );
     214        8511 :   if( FD_UNLIKELY( new_accounts_resize_delta>MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN ) ) {
     215           3 :     *err = FD_EXECUTOR_INSTR_ERR_MAX_ACCS_DATA_ALLOCS_EXCEEDED;
     216           3 :     return 0;
     217           3 :   }
     218             : 
     219             :   /* The account data can only be resized if it can be changed
     220             :      https://github.com/anza-xyz/agave/blob/v4.2.0-beta.0/transaction-context/src/instruction_accounts.rs#L351-L357 */
     221        8508 :   return fd_borrowed_account_can_data_be_changed( borrowed_acct, err );
     222        8511 : }

Generated by: LCOV version 1.14