LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_borrowed_account.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 71 118 60.2 %
Date: 2026-05-26 08:02:49 Functions: 7 8 87.5 %

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

Generated by: LCOV version 1.14