LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_borrowed_account.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 34 118 28.8 %
Date: 2025-12-19 05:07:08 Functions: 4 8 50.0 %

          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           0 :                                   ulong *                 dlen_out ) {
       7             : 
       8             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L824 */
       9           0 :   int err;
      10           0 :   fd_borrowed_account_can_data_be_changed( borrowed_acct, &err );
      11           0 :   if( FD_UNLIKELY( err ) ) {
      12           0 :     return err;
      13           0 :   }
      14             : 
      15           0 :   if ( data_out != NULL )
      16           0 :     *data_out = fd_account_data( borrowed_acct->meta );
      17           0 :   if ( dlen_out != NULL )
      18           0 :     *dlen_out = borrowed_acct->meta->dlen;
      19             : 
      20           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      21           0 : }
      22             : 
      23             : int
      24             : fd_borrowed_account_set_owner( fd_borrowed_account_t * borrowed_acct,
      25           0 :                                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           0 :   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           0 :   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           0 :   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           0 :   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           0 :   fd_memcpy( borrowed_acct->meta->owner, owner, sizeof(fd_pubkey_t) );
      56           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      57           0 : }
      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          48 :                                   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          48 :   if( FD_UNLIKELY( (!fd_borrowed_account_is_owned_by_current_program( borrowed_acct )) &&
      68          48 :                    (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          48 :   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          48 :   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           0 :   borrowed_acct->meta->lamports = lamports;
      87           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      88          48 : }
      89             : 
      90             : int
      91             : fd_borrowed_account_set_data_from_slice( fd_borrowed_account_t * borrowed_acct,
      92             :                                          uchar const *           data,
      93          48 :                                          ulong                   data_sz ) {
      94             : 
      95             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L865 */
      96          48 :   int err;
      97          48 :   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          48 :   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          48 :   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          48 :   borrowed_acct->meta->dlen = (uint)data_sz;
     115          48 :   fd_memcpy( fd_account_data( borrowed_acct->meta ), data, data_sz );
     116             : 
     117          48 :   return FD_EXECUTOR_INSTR_SUCCESS;
     118          48 : }
     119             : 
     120             : int
     121             : fd_borrowed_account_set_data_length( fd_borrowed_account_t * borrowed_acct,
     122           0 :                                      ulong                   new_len ) {
     123           0 :   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           0 :   if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_resized( borrowed_acct, new_len, &err ) ) ) {
     127           0 :     return err;
     128           0 :   }
     129             : 
     130             :   /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L884 */
     131           0 :   if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_changed( borrowed_acct, &err ) ) ) {
     132           0 :     return err;
     133           0 :   }
     134             : 
     135           0 :   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           0 :   if( old_len==new_len ) {
     140           0 :     return FD_EXECUTOR_INSTR_SUCCESS;
     141           0 :   }
     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           0 :   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           0 :   fd_account_meta_resize( borrowed_acct->meta, new_len );
     153             : 
     154           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     155           0 : }
     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 = fd_bank_rent_query( borrowed_acct->instr_ctx->bank );
     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          48 :                                                   int *                   err ) {
     197          48 :   fd_exec_instr_ctx_t const * instr_ctx  = borrowed_acct->instr_ctx;
     198          48 :   ulong                       size_delta = fd_ulong_sat_sub( new_len, borrowed_acct->meta->dlen );
     199             : 
     200             :   /* TODO: The size delta should never exceed the value of ULONG_MAX so this
     201             :      could be replaced with a normal addition. However to match execution with
     202             :      the agave client, this is being left as a sat add */
     203          48 :   instr_ctx->txn_out->details.accounts_resize_delta = fd_ulong_sat_add( instr_ctx->txn_out->details.accounts_resize_delta, size_delta );
     204          48 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     205          48 :   return 1;
     206          48 : }
     207             : 
     208             : int
     209             : fd_borrowed_account_can_data_be_resized( fd_borrowed_account_t const * borrowed_acct,
     210             :                                          ulong                         new_length,
     211          96 :                                          int *                         err ) {
     212             : 
     213             :   /* Only the owner can change the length of the data
     214             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1095 */
     215          96 :   if( FD_UNLIKELY( (borrowed_acct->meta->dlen!=new_length) &
     216          96 :                    (!fd_borrowed_account_is_owned_by_current_program( borrowed_acct )) ) ) {
     217           0 :     *err = FD_EXECUTOR_INSTR_ERR_ACC_DATA_SIZE_CHANGED;
     218           0 :     return 0;
     219           0 :   }
     220             : 
     221             :   /* The new length can not exceed the maximum permitted length
     222             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1099 */
     223          96 :   if( FD_UNLIKELY( new_length>MAX_PERMITTED_DATA_LENGTH ) ) {
     224           0 :     *err = FD_EXECUTOR_INSTR_ERR_INVALID_REALLOC;
     225           0 :     return 0;
     226           0 :   }
     227             : 
     228             :   /* The resize can not exceed the per-transaction maximum
     229             :      https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1104-L1108 */
     230          96 :   ulong length_delta              = fd_ulong_sat_sub( new_length, borrowed_acct->meta->dlen );
     231          96 :   ulong new_accounts_resize_delta = fd_ulong_sat_add( borrowed_acct->instr_ctx->txn_out->details.accounts_resize_delta, length_delta );
     232          96 :   if( FD_UNLIKELY( new_accounts_resize_delta > MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN ) ) {
     233           0 :     *err = FD_EXECUTOR_INSTR_ERR_MAX_ACCS_DATA_ALLOCS_EXCEEDED;
     234           0 :     return 0;
     235           0 :   }
     236             : 
     237          96 :   *err = FD_EXECUTOR_INSTR_SUCCESS;
     238          96 :   return 1;
     239          96 : }

Generated by: LCOV version 1.14