LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_txn_account.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 180 356 50.6 %
Date: 2025-09-19 04:41:14 Functions: 21 38 55.3 %

          Line data    Source code
       1             : #include "fd_txn_account.h"
       2             : #include "fd_runtime.h"
       3             : 
       4             : void *
       5             : fd_txn_account_new( void *              mem,
       6             :                     fd_pubkey_t const * pubkey,
       7             :                     fd_account_meta_t * meta,
       8        1029 :                     int                 is_mutable ) {
       9        1029 :   if( FD_UNLIKELY( !mem ) ) {
      10           3 :     FD_LOG_WARNING(( "NULL mem" ));
      11           3 :     return NULL;
      12           3 :   }
      13             : 
      14        1026 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_txn_account_t) ) ) ) {
      15           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      16           0 :     return NULL;
      17           0 :   }
      18             : 
      19        1026 :   if( FD_UNLIKELY( !pubkey ) ) {
      20           3 :     FD_LOG_WARNING(( "NULL pubkey" ));
      21           3 :     return NULL;
      22           3 :   }
      23             : 
      24        1023 :   if( FD_UNLIKELY( !meta ) ) {
      25           3 :     FD_LOG_WARNING(( "NULL meta" ));
      26           3 :     return NULL;
      27           3 :   }
      28             : 
      29        1020 :   fd_txn_account_t * txn_account = (fd_txn_account_t *)mem;
      30             : 
      31        1020 :   fd_memcpy( txn_account->pubkey, pubkey, sizeof(fd_pubkey_t) );
      32             : 
      33        1020 :   fd_wksp_t * wksp = fd_wksp_containing( meta );
      34             : 
      35        1020 :   txn_account->magic             = FD_TXN_ACCOUNT_MAGIC;
      36             : 
      37        1020 :   txn_account->starting_dlen     = meta->dlen;
      38        1020 :   txn_account->starting_lamports = meta->lamports;
      39             : 
      40        1020 :   uchar * data = (uchar *)meta + sizeof(fd_account_meta_t);
      41             : 
      42        1020 :   txn_account->meta_gaddr = fd_wksp_gaddr( wksp, meta );
      43        1020 :   if( FD_UNLIKELY( !txn_account->meta_gaddr ) ) {
      44           0 :     FD_LOG_WARNING(( "meta_gaddr is 0" ));
      45           0 :     return NULL;
      46           0 :   }
      47             : 
      48        1020 :   txn_account->data_gaddr = fd_wksp_gaddr( wksp, data );
      49        1020 :   if( FD_UNLIKELY( !txn_account->data_gaddr ) ) {
      50           0 :     FD_LOG_WARNING(( "data_gaddr is 0" ));
      51           0 :     return NULL;
      52           0 :   }
      53             : 
      54        1020 :   txn_account->meta       = meta;
      55        1020 :   txn_account->data       = data;
      56        1020 :   txn_account->is_mutable = is_mutable;
      57             : 
      58        1020 :   return mem;
      59        1020 : }
      60             : 
      61             : fd_txn_account_t *
      62        1035 : fd_txn_account_join( void * mem, fd_wksp_t * data_wksp ) {
      63        1035 :   if( FD_UNLIKELY( !mem ) ) {
      64           3 :     FD_LOG_WARNING(( "NULL mem" ));
      65           3 :     return NULL;
      66           3 :   }
      67             : 
      68        1032 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_txn_account_t) ) ) ) {
      69           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      70           0 :     return NULL;
      71           0 :   }
      72             : 
      73        1032 :   if( FD_UNLIKELY( !data_wksp ) ) {
      74           3 :     FD_LOG_WARNING(( "NULL data_wksp" ));
      75           3 :     return NULL;
      76           3 :   }
      77             : 
      78        1029 :   fd_txn_account_t * txn_account = (fd_txn_account_t *)mem;
      79             : 
      80        1029 :   if( FD_UNLIKELY( txn_account->magic != FD_TXN_ACCOUNT_MAGIC ) ) {
      81           6 :     FD_LOG_WARNING(( "wrong magic" ));
      82           6 :     return NULL;
      83           6 :   }
      84             : 
      85        1023 :   if( FD_UNLIKELY( txn_account->meta_gaddr==0UL ) ) {
      86           0 :     FD_LOG_WARNING(( "`meta gaddr is 0" ));
      87           0 :     return NULL;
      88           0 :   }
      89             : 
      90        1023 :   txn_account->meta = fd_wksp_laddr( data_wksp, txn_account->meta_gaddr );
      91        1023 :   if( FD_UNLIKELY( !txn_account->meta ) ) {
      92           0 :     FD_LOG_WARNING(( "meta is NULL" ));
      93           0 :     return NULL;
      94           0 :   }
      95             : 
      96        1023 :   txn_account->data = fd_wksp_laddr( data_wksp, txn_account->data_gaddr );
      97        1023 :   if( FD_UNLIKELY( !txn_account->data && txn_account->meta->dlen ) ) {
      98           0 :     FD_LOG_WARNING(( "data is NULL" ));
      99           0 :     return NULL;
     100           0 :   }
     101             : 
     102        1023 :   return txn_account;
     103        1023 : }
     104             : 
     105             : void *
     106          15 : fd_txn_account_leave( fd_txn_account_t * acct ) {
     107             : 
     108          15 :   if( FD_UNLIKELY( !acct ) ) {
     109           3 :     FD_LOG_WARNING(( "NULL acct" ));
     110           3 :     return NULL;
     111           3 :   }
     112             : 
     113          12 :   if( FD_UNLIKELY( acct->magic != FD_TXN_ACCOUNT_MAGIC ) ) {
     114           0 :     FD_LOG_WARNING(( "wrong magic" ));
     115           0 :     return NULL;
     116           0 :   }
     117             : 
     118          12 :   acct->meta = NULL;
     119          12 :   acct->data = NULL;
     120             : 
     121          12 :   return acct;
     122          12 : }
     123             : 
     124             : void *
     125           9 : fd_txn_account_delete( void * mem ) {
     126           9 :   if( FD_UNLIKELY( !mem ) ) {
     127           3 :     FD_LOG_WARNING(( "NULL mem" ));
     128           3 :     return NULL;
     129           3 :   }
     130             : 
     131           6 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_txn_account_t) ) ) ) {
     132           0 :     FD_LOG_WARNING(( "misaligned mem" ));
     133           0 :     return NULL;
     134           0 :   }
     135             : 
     136           6 :   fd_txn_account_t * txn_account = (fd_txn_account_t *)mem;
     137             : 
     138           6 :   if( FD_UNLIKELY( txn_account->magic != FD_TXN_ACCOUNT_MAGIC ) ) {
     139           0 :     FD_LOG_WARNING(( "wrong magic" ));
     140           0 :     return NULL;
     141           0 :   }
     142             : 
     143           6 :   txn_account->magic = 0UL;
     144             : 
     145           6 :   return mem;
     146           6 : }
     147             : 
     148             : /* Factory constructors from funk */
     149             : 
     150             : int
     151             : fd_txn_account_init_from_funk_readonly( fd_txn_account_t *    acct,
     152             :                                         fd_pubkey_t const *   pubkey,
     153             :                                         fd_funk_t const *     funk,
     154        4194 :                                         fd_funk_txn_t const * funk_txn ) {
     155             : 
     156        4194 :   int err = FD_ACC_MGR_SUCCESS;
     157        4194 :   fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly(
     158        4194 :       funk,
     159        4194 :       funk_txn,
     160        4194 :       pubkey,
     161        4194 :       NULL,
     162        4194 :       &err,
     163        4194 :       NULL );
     164             : 
     165        4194 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
     166        3675 :     return err;
     167        3675 :   }
     168             : 
     169         519 :   if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new(
     170         519 :         acct,
     171         519 :         pubkey,
     172         519 :         (fd_account_meta_t *)meta,
     173         519 :         0 ), fd_funk_wksp( funk ) ) ) ) {
     174           0 :     FD_LOG_CRIT(( "Failed to join txn account" ));
     175           0 :   }
     176             : 
     177         519 :   return FD_ACC_MGR_SUCCESS;
     178         519 : }
     179             : 
     180             : int
     181             : fd_txn_account_init_from_funk_mutable( fd_txn_account_t *      acct,
     182             :                                        fd_pubkey_t const *     pubkey,
     183             :                                        fd_funk_t *             funk,
     184             :                                        fd_funk_txn_t *         funk_txn,
     185             :                                        int                     do_create,
     186             :                                        ulong                   min_data_sz,
     187         495 :                                        fd_funk_rec_prepare_t * prepare_out ) {
     188         495 :   memset( prepare_out, 0, sizeof(fd_funk_rec_prepare_t) );
     189         495 :   int err = FD_ACC_MGR_SUCCESS;
     190         495 :   fd_account_meta_t * meta = fd_funk_get_acc_meta_mutable(
     191         495 :       funk,
     192         495 :       funk_txn,
     193         495 :       pubkey,
     194         495 :       do_create,
     195         495 :       min_data_sz,
     196         495 :       NULL,
     197         495 :       prepare_out,
     198         495 :       &err );
     199             : 
     200         495 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
     201           0 :     return err;
     202           0 :   }
     203             : 
     204             :   /* exec tile should never call this function, so the global addresses
     205             :      of meta and data should never be used. Instead, populate the
     206             :      prepared_rec field so that any created records can be published
     207             :      with fd_txn_account_mutable_fini. */
     208             : 
     209         495 :   if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new(
     210         495 :         acct,
     211         495 :         pubkey,
     212         495 :         (fd_account_meta_t *)meta,
     213         495 :         1 ), fd_funk_wksp( funk ) ) ) ) {
     214           0 :     FD_LOG_CRIT(( "Failed to join txn account" ));
     215           0 :   }
     216             : 
     217         495 :   return FD_ACC_MGR_SUCCESS;
     218         495 : }
     219             : 
     220             : void
     221             : fd_txn_account_mutable_fini( fd_txn_account_t *      acct,
     222             :                              fd_funk_t *             funk,
     223             :                              fd_funk_txn_t *         txn,
     224         495 :                              fd_funk_rec_prepare_t * prepare ) {
     225         495 :   (void)txn;
     226         495 :   fd_funk_rec_key_t key = fd_funk_acc_key( acct->pubkey );
     227             : 
     228             :   /* Check that the prepared record is still valid -
     229             :      if these invariants are broken something is very wrong. */
     230         495 :   if( prepare->rec ) {
     231             :     /* Check that the prepared record is not the Funk null value */
     232          39 :     if( !prepare->rec->val_gaddr ) {
     233           0 :       FD_LOG_CRIT(( "invalid prepared record for %s: unexpected NULL funk record value. the record might have been modified by another thread",
     234           0 :                    FD_BASE58_ENC_32_ALLOCA( acct->pubkey ) ));
     235           0 :     }
     236             : 
     237             :     /* Ensure that the prepared record key still matches our key. */
     238          39 :     if( FD_UNLIKELY( memcmp( prepare->rec->pair.key, &key, sizeof(fd_funk_rec_key_t) )!=0 ) ) {
     239           0 :       FD_LOG_CRIT(( "invalid prepared record for %s: the record might have been modified by another thread",
     240           0 :                   FD_BASE58_ENC_32_ALLOCA( acct->pubkey ) ));
     241           0 :     }
     242             : 
     243             :     /* Crashes the app if this key already exists in funk (conflicting
     244             :        write) */
     245          39 :     fd_funk_rec_publish( funk, prepare );
     246          39 :   }
     247         495 : }
     248             : 
     249             : /* read/write mutual exclusion */
     250             : 
     251             : FD_FN_PURE int
     252           0 : fd_txn_account_acquire_write_is_safe( fd_txn_account_t const * acct ) {
     253           0 :   return !acct->refcnt_excl;
     254           0 : }
     255             : 
     256             : /* fd_txn_account_acquire_write acquires write/exclusive access.
     257             :    Causes all other write or read acquire attempts will fail.  Returns 1
     258             :    on success, 0 on failure.
     259             : 
     260             :    Mirrors a try_borrow_mut() call in Agave. */
     261             : int
     262           0 : fd_txn_account_acquire_write( fd_txn_account_t * acct ) {
     263           0 :   if( FD_UNLIKELY( !fd_txn_account_acquire_write_is_safe( acct ) ) ) {
     264           0 :     return 0;
     265           0 :   }
     266           0 :   acct->refcnt_excl = (ushort)1;
     267           0 :   return 1;
     268           0 : }
     269             : 
     270             : /* fd_txn_account_release_write{_private} releases a write/exclusive
     271             :    access handle. The private version should only be used by fd_borrowed_account_drop
     272             :    and fd_borrowed_account_destroy. */
     273             : void
     274           0 : fd_txn_account_release_write( fd_txn_account_t * acct ) {
     275           0 :   if( FD_UNLIKELY( acct->refcnt_excl!=1 ) ) {
     276           0 :     FD_LOG_CRIT(( "refcnt_excl is %d, expected 1", acct->refcnt_excl ));
     277           0 :   }
     278           0 :   acct->refcnt_excl = (ushort)0;
     279           0 : }
     280             : 
     281             : void
     282           0 : fd_txn_account_release_write_private( fd_txn_account_t * acct ) {
     283             :   /* Only release if it is not yet released */
     284           0 :   if( !fd_txn_account_acquire_write_is_safe( acct ) ) {
     285           0 :     fd_txn_account_release_write( acct );
     286           0 :   }
     287           0 : }
     288             : 
     289             : fd_pubkey_t const *
     290         174 : fd_txn_account_get_owner( fd_txn_account_t const * acct ) {
     291         174 :   if( FD_UNLIKELY( !acct->meta ) ) {
     292           0 :     FD_LOG_CRIT(( "account is not setup" ));
     293           0 :   }
     294         174 :   return (fd_pubkey_t const *)acct->meta->owner;
     295         174 : }
     296             : 
     297             : fd_account_meta_t const *
     298         927 : fd_txn_account_get_meta( fd_txn_account_t const * acct ) {
     299         927 :   return acct->meta;
     300         927 : }
     301             : 
     302             : uchar const *
     303        1434 : fd_txn_account_get_data( fd_txn_account_t const * acct ) {
     304        1434 :   return acct->data;
     305        1434 : }
     306             : 
     307             : uchar *
     308           0 : fd_txn_account_get_data_mut( fd_txn_account_t const * acct ) {
     309           0 :   return acct->data;
     310           0 : }
     311             : 
     312             : ulong
     313         516 : fd_txn_account_get_data_len( fd_txn_account_t const * acct ) {
     314         516 :   if( FD_UNLIKELY( !acct->meta ) ) {
     315           0 :     FD_LOG_CRIT(( "account is not setup" ));
     316           0 :   }
     317         516 :   return acct->meta->dlen;
     318         516 : }
     319             : 
     320             : int
     321           0 : fd_txn_account_is_executable( fd_txn_account_t const * acct ) {
     322           0 :   if( FD_UNLIKELY( !acct->meta ) ) {
     323           0 :     FD_LOG_CRIT(( "account is not setup" ));
     324           0 :   }
     325           0 :   return !!acct->meta->executable;
     326           0 : }
     327             : 
     328             : ulong
     329         936 : fd_txn_account_get_lamports( fd_txn_account_t const * acct ) {
     330         936 :   if( FD_UNLIKELY( !acct->meta ) ) {
     331           0 :     FD_LOG_CRIT(( "account is not setup" ));
     332           0 :   }
     333         936 :   return acct->meta->lamports;
     334         936 : }
     335             : 
     336             : ulong
     337           6 : fd_txn_account_get_rent_epoch( fd_txn_account_t const * acct ) {
     338           6 :   (void)acct;
     339           6 :   return ULONG_MAX;
     340           6 : }
     341             : 
     342             : void
     343           0 : fd_txn_account_set_meta( fd_txn_account_t * acct, fd_account_meta_t * meta ) {
     344           0 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     345           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     346           0 :   }
     347           0 :   if( FD_UNLIKELY( !meta ) ) {
     348           0 :     FD_LOG_CRIT(( "account is not setup" ));
     349           0 :   }
     350           0 :   acct->meta = meta;
     351           0 : }
     352             : 
     353             : void
     354          30 : fd_txn_account_set_executable( fd_txn_account_t * acct, int is_executable ) {
     355          30 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     356           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     357           0 :   }
     358          30 :   if( FD_UNLIKELY( !acct->meta ) ) {
     359           0 :     FD_LOG_CRIT(( "account is not setup" ));
     360           0 :   }
     361          30 :   acct->meta->executable = !!is_executable;
     362          30 : }
     363             : 
     364             : void
     365         492 : fd_txn_account_set_owner( fd_txn_account_t * acct, fd_pubkey_t const * owner ) {
     366         492 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     367           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     368           0 :   }
     369         492 :   if( FD_UNLIKELY( !acct->meta ) ) {
     370           0 :     FD_LOG_CRIT(( "account is not setup" ));
     371           0 :   }
     372         492 :   fd_memcpy( acct->meta->owner, owner, sizeof(fd_pubkey_t) );
     373         492 : }
     374             : 
     375             : void
     376         495 : fd_txn_account_set_lamports( fd_txn_account_t * acct, ulong lamports ) {
     377         495 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     378           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     379           0 :   }
     380         495 :   if( FD_UNLIKELY( !acct->meta ) ) {
     381           0 :     FD_LOG_CRIT(( "account is not setup" ));
     382           0 :   }
     383         495 :   acct->meta->lamports = lamports;
     384         495 : }
     385             : 
     386             : int
     387           0 : fd_txn_account_checked_add_lamports( fd_txn_account_t * acct, ulong lamports ) {
     388           0 :   ulong balance_post = 0UL;
     389           0 :   int err = fd_ulong_checked_add( fd_txn_account_get_lamports( acct ), lamports, &balance_post );
     390           0 :   if( FD_UNLIKELY( err ) ) {
     391           0 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     392           0 :   }
     393             : 
     394           0 :   fd_txn_account_set_lamports( acct, balance_post );
     395           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     396           0 : }
     397             : 
     398             : int
     399           0 : fd_txn_account_checked_sub_lamports( fd_txn_account_t * acct, ulong lamports ) {
     400           0 :   ulong balance_post = 0UL;
     401           0 :   int err = fd_ulong_checked_sub( fd_txn_account_get_lamports( acct ),
     402           0 :                                   lamports,
     403           0 :                                   &balance_post );
     404           0 :   if( FD_UNLIKELY( err ) ) {
     405           0 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     406           0 :   }
     407             : 
     408           0 :   fd_txn_account_set_lamports( acct, balance_post );
     409           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     410           0 : }
     411             : 
     412             : void
     413             : fd_txn_account_set_data( fd_txn_account_t * acct,
     414             :                          void const *       data,
     415         495 :                          ulong              data_sz ) {
     416         495 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     417           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     418           0 :   }
     419         495 :   if( FD_UNLIKELY( !acct->meta ) ) {
     420           0 :     FD_LOG_CRIT(( "account is not setup" ));
     421           0 :   }
     422         495 :   acct->meta->dlen = (uint)data_sz;
     423         495 :   fd_memcpy( acct->data, data, data_sz );
     424         495 : }
     425             : 
     426             : void
     427           3 : fd_txn_account_set_data_len( fd_txn_account_t * acct, ulong data_len ) {
     428           3 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     429           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     430           0 :   }
     431           3 :   if( FD_UNLIKELY( !acct->meta ) ) {
     432           0 :     FD_LOG_CRIT(( "account is not setup" ));
     433           0 :   }
     434           3 :   acct->meta->dlen = (uint)data_len;
     435           3 : }
     436             : 
     437             : void
     438         462 : fd_txn_account_set_slot( fd_txn_account_t * acct, ulong slot ) {
     439         462 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     440           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     441           0 :   }
     442         462 :   if( FD_UNLIKELY( !acct->meta ) ) {
     443           0 :     FD_LOG_CRIT(( "account is not setup" ));
     444           0 :   }
     445         462 :   acct->meta->slot = slot;
     446         462 : }
     447             : 
     448             : void
     449           0 : fd_txn_account_clear_owner( fd_txn_account_t * acct ) {
     450           0 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     451           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     452           0 :   }
     453           0 :   if( FD_UNLIKELY( !acct->meta ) ) {
     454           0 :     FD_LOG_CRIT(( "account is not setup" ));
     455           0 :   }
     456           0 :   fd_memset( acct->meta->owner, 0, sizeof(fd_pubkey_t) );
     457           0 : }
     458             : 
     459             : void
     460             : fd_txn_account_resize( fd_txn_account_t * acct,
     461           0 :                        ulong              dlen ) {
     462           0 :   if( FD_UNLIKELY( !acct->is_mutable ) ) {
     463           0 :     FD_LOG_CRIT(( "account is not mutable" ));
     464           0 :   }
     465           0 :   if( FD_UNLIKELY( !acct->meta ) ) {
     466           0 :     FD_LOG_CRIT(( "account is not setup" ));
     467           0 :   }
     468             :   /* Because the memory for an account is preallocated for the transaction
     469             :      up to the max account size, we only need to zero out bytes (for the case
     470             :      where the account grew) and update the account dlen. */
     471           0 :   ulong old_sz    = acct->meta->dlen;
     472           0 :   ulong new_sz    = dlen;
     473           0 :   ulong memset_sz = fd_ulong_sat_sub( new_sz, old_sz );
     474           0 :   fd_memset( acct->data+old_sz, 0, memset_sz );
     475             : 
     476           0 :   acct->meta->dlen = (uint)dlen;
     477           0 : }
     478             : 
     479             : ushort
     480           0 : fd_txn_account_is_borrowed( fd_txn_account_t const * acct ) {
     481           0 :   return !!acct->refcnt_excl;
     482           0 : }
     483             : 
     484             : int
     485           6 : fd_txn_account_is_mutable( fd_txn_account_t const * acct ) {
     486             :   /* A txn account is mutable if meta is non NULL */
     487           6 :   return acct->is_mutable;
     488           6 : }
     489             : 
     490             : int
     491           6 : fd_txn_account_is_readonly( fd_txn_account_t const * acct ) {
     492             :   /* A txn account is readonly if only the meta_ field is non NULL */
     493           6 :   return !acct->is_mutable;
     494           6 : }
     495             : 
     496             : int
     497           0 : fd_txn_account_try_borrow_mut( fd_txn_account_t * acct ) {
     498           0 :   return fd_txn_account_acquire_write( acct );
     499           0 : }
     500             : 
     501             : void
     502           0 : fd_txn_account_drop( fd_txn_account_t * acct ) {
     503           0 :   fd_txn_account_release_write_private( acct );
     504           0 : }
     505             : 
     506             : void
     507           0 : fd_txn_account_set_readonly( fd_txn_account_t * acct ) {
     508           0 :   acct->is_mutable = 0;
     509           0 : }
     510             : 
     511             : void
     512           0 : fd_txn_account_set_mutable( fd_txn_account_t * acct ) {
     513           0 :   acct->is_mutable = 1;
     514           0 : }
     515             : 
     516             : fd_solana_account_meta_t
     517           0 : fd_txn_account_get_solana_meta( fd_txn_account_t const * acct ) {
     518           0 :   fd_solana_account_meta_t meta = {
     519           0 :     .lamports   = acct->meta->lamports,
     520             :     .rent_epoch = ULONG_MAX,
     521           0 :     .executable = acct->meta->executable,
     522           0 :   };
     523           0 :   memcpy( meta.owner, acct->meta->owner, sizeof(fd_pubkey_t) );
     524           0 :   return meta;
     525           0 : }

Generated by: LCOV version 1.14