LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_txn_account.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 153 425 36.0 %
Date: 2025-07-01 05:00:49 Functions: 21 67 31.3 %

          Line data    Source code
       1             : #include "fd_txn_account.h"
       2             : #include "fd_runtime.h"
       3             : 
       4             : fd_txn_account_t *
       5         102 : fd_txn_account_init( void * ptr ) {
       6         102 :   if( FD_UNLIKELY( !ptr ) ) {
       7           0 :     FD_LOG_WARNING(( "NULL ptr" ));
       8           0 :     return NULL;
       9           0 :   }
      10             : 
      11         102 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)ptr, alignof(fd_txn_account_t) ) ) ) {
      12           0 :     FD_LOG_WARNING(( "misaligned ptr" ));
      13           0 :     return NULL;
      14           0 :   }
      15             : 
      16         102 :   memset( ptr, 0, FD_TXN_ACCOUNT_FOOTPRINT );
      17             : 
      18         102 :   fd_txn_account_t * ret = (fd_txn_account_t *)ptr;
      19         102 :   ret->private_state.meta_gaddr = 0UL;
      20         102 :   ret->private_state.data_gaddr = 0UL;
      21         102 :   ret->starting_dlen            = ULONG_MAX;
      22         102 :   ret->starting_lamports        = ULONG_MAX;
      23             : 
      24         102 :   ret->private_state.const_data = NULL;
      25         102 :   ret->private_state.const_meta = NULL;
      26         102 :   ret->private_state.meta       = NULL;
      27         102 :   ret->private_state.data       = NULL;
      28             : 
      29             :   /* Defaults to writable vtable */
      30         102 :   ret->vt                       = &fd_txn_account_writable_vtable;
      31             : 
      32         102 :   FD_COMPILER_MFENCE();
      33         102 :   ret->magic = FD_TXN_ACCOUNT_MAGIC;
      34         102 :   FD_COMPILER_MFENCE();
      35             : 
      36         102 :   return ret;
      37         102 : }
      38             : 
      39             : /* A common setup helper function that sets
      40             :    default values for the txn account */
      41             : void
      42          45 : fd_txn_account_setup_common( fd_txn_account_t * acct ) {
      43          45 :   fd_account_meta_t const * meta = acct->private_state.const_meta ?
      44          45 :                                    acct->private_state.const_meta : acct->private_state.meta;
      45             : 
      46             :   /* TODO: Why ULONG_MAX check here? */
      47          45 :   if( ULONG_MAX == acct->starting_dlen ) {
      48          45 :     acct->starting_dlen = meta->dlen;
      49          45 :   }
      50             : 
      51          45 :   if( ULONG_MAX == acct->starting_lamports ) {
      52          45 :     acct->starting_lamports = meta->info.lamports;
      53          45 :   }
      54          45 : }
      55             : 
      56             : void
      57             : fd_txn_account_init_from_meta_and_data_mutable( fd_txn_account_t *  acct,
      58             :                                                 fd_account_meta_t * meta,
      59           0 :                                                 uchar *             data ) {
      60           0 :   acct->private_state.const_data = data;
      61           0 :   acct->private_state.const_meta = meta;
      62           0 :   acct->private_state.data       = data;
      63           0 :   acct->private_state.meta       = meta;
      64           0 :   acct->vt                       = &fd_txn_account_writable_vtable;
      65           0 : }
      66             : 
      67             : void
      68             : fd_txn_account_init_from_meta_and_data_readonly( fd_txn_account_t *        acct,
      69             :                                                  fd_account_meta_t const * meta,
      70           0 :                                                  uchar const *             data ) {
      71             : 
      72           0 :   acct->private_state.const_data = data;
      73           0 :   acct->private_state.const_meta = meta;
      74           0 :   acct->vt                       = &fd_txn_account_readonly_vtable;
      75           0 : }
      76             : 
      77             : void
      78             : fd_txn_account_setup_sentinel_meta_readonly( fd_txn_account_t * acct,
      79             :                                              fd_spad_t *        spad,
      80           0 :                                              fd_wksp_t *        spad_wksp ) {
      81             : 
      82           0 :   fd_account_meta_t * sentinel = fd_spad_alloc( spad, FD_ACCOUNT_REC_ALIGN, sizeof(fd_account_meta_t) );
      83           0 :   fd_memset( sentinel, 0, sizeof(fd_account_meta_t) );
      84             : 
      85           0 :   sentinel->magic                = FD_ACCOUNT_META_MAGIC;
      86           0 :   sentinel->info.rent_epoch      = ULONG_MAX;
      87           0 :   acct->private_state.const_meta = sentinel;
      88           0 :   acct->starting_lamports        = 0UL;
      89           0 :   acct->starting_dlen            = 0UL;
      90           0 :   acct->private_state.meta_gaddr = fd_wksp_gaddr( spad_wksp, sentinel );
      91           0 : }
      92             : 
      93             : void
      94             : fd_txn_account_setup_meta_mutable( fd_txn_account_t * acct,
      95             :                                    fd_spad_t *        spad,
      96           0 :                                    ulong              sz ) {
      97           0 :   fd_account_meta_t * meta = fd_spad_alloc( spad, alignof(fd_account_meta_t), sizeof(fd_account_meta_t) + sz );
      98           0 :   void * data = (uchar *)meta + sizeof(fd_account_meta_t);
      99             : 
     100           0 :   acct->private_state.const_meta = acct->private_state.meta = meta;
     101           0 :   acct->private_state.const_data = acct->private_state.data = data;
     102           0 :   acct->vt                       = &fd_txn_account_writable_vtable;
     103           0 : }
     104             : 
     105             : void
     106             : fd_txn_account_setup_readonly( fd_txn_account_t *        acct,
     107             :                                fd_pubkey_t const *       pubkey,
     108          15 :                                fd_account_meta_t const * meta ) {
     109          15 :   fd_memcpy(acct->pubkey, pubkey, sizeof(fd_pubkey_t));
     110             : 
     111             :   /* We don't copy the metadata into a buffer here, because we assume
     112             :      that we are holding read locks on the account, because we are inside
     113             :      a transaction. */
     114          15 :   acct->private_state.const_meta = meta;
     115          15 :   acct->private_state.const_data = (uchar const *)meta + meta->hlen;
     116          15 :   acct->vt                       = &fd_txn_account_readonly_vtable;
     117             : 
     118          15 :   fd_txn_account_setup_common( acct );
     119          15 : }
     120             : 
     121             : void
     122             : fd_txn_account_setup_mutable( fd_txn_account_t *        acct,
     123             :                               fd_pubkey_t const *       pubkey,
     124          30 :                               fd_account_meta_t *       meta ) {
     125          30 :   fd_memcpy(acct->pubkey, pubkey, sizeof(fd_pubkey_t));
     126             : 
     127          30 :   acct->private_state.const_rec  = acct->private_state.rec;
     128          30 :   acct->private_state.const_meta = acct->private_state.meta = meta;
     129          30 :   acct->private_state.const_data = acct->private_state.data = (uchar *)meta + meta->hlen;
     130          30 :   acct->vt                       = &fd_txn_account_writable_vtable;
     131             : 
     132          30 :   fd_txn_account_setup_common( acct );
     133          30 : }
     134             : 
     135             : /* Operators impl */
     136             : 
     137             : /* Internal helper to initialize account data */
     138             : uchar *
     139           0 : fd_txn_account_init_data( fd_txn_account_t * acct, void * buf ) {
     140             :   /* Assumes that buf is pointing to account data */
     141           0 :   uchar * new_raw_data = (uchar *)buf;
     142           0 :   ulong   dlen         = ( acct->private_state.const_meta != NULL ) ? acct->private_state.const_meta->dlen : 0;
     143             : 
     144           0 :   if( acct->private_state.const_meta != NULL ) {
     145           0 :     fd_memcpy( new_raw_data, (uchar *)acct->private_state.const_meta, sizeof(fd_account_meta_t)+dlen );
     146           0 :   } else {
     147             :     /* Account did not exist, set up metadata */
     148           0 :     fd_account_meta_init( (fd_account_meta_t *)new_raw_data );
     149           0 :   }
     150             : 
     151           0 :   return new_raw_data;
     152           0 : }
     153             : 
     154             : fd_txn_account_t *
     155             : fd_txn_account_make_mutable( fd_txn_account_t * acct,
     156             :                              void *             buf,
     157           0 :                              fd_wksp_t *        wksp ) {
     158           0 :   if( FD_UNLIKELY( acct->private_state.data != NULL ) ) {
     159           0 :     FD_LOG_ERR(( "borrowed account is already mutable" ));
     160           0 :   }
     161             : 
     162           0 :   ulong   dlen         = ( acct->private_state.const_meta != NULL ) ? acct->private_state.const_meta->dlen : 0UL;
     163           0 :   uchar * new_raw_data = fd_txn_account_init_data( acct, buf );
     164             : 
     165           0 :   acct->private_state.const_meta = acct->private_state.meta = (fd_account_meta_t *)new_raw_data;
     166           0 :   acct->private_state.const_data = acct->private_state.data = new_raw_data + sizeof(fd_account_meta_t);
     167           0 :   acct->private_state.meta->dlen = dlen;
     168             : 
     169             :   /* update global addresses of meta and data after copying into buffer */
     170           0 :   acct->private_state.meta_gaddr = fd_wksp_gaddr( wksp, acct->private_state.meta );
     171           0 :   acct->private_state.data_gaddr = fd_wksp_gaddr( wksp, acct->private_state.data );
     172           0 :   acct->vt                       = &fd_txn_account_writable_vtable;
     173             : 
     174           0 :   return acct;
     175           0 : }
     176             : 
     177             : /* Factory constructors from funk */
     178             : 
     179             : int
     180             : fd_txn_account_init_from_funk_readonly( fd_txn_account_t *    acct,
     181             :                                         fd_pubkey_t const *   pubkey,
     182             :                                         fd_funk_t const *     funk,
     183          18 :                                         fd_funk_txn_t const * funk_txn ) {
     184          18 :   fd_txn_account_init( acct );
     185             : 
     186          18 :   int err = FD_ACC_MGR_SUCCESS;
     187          18 :   fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly( funk,
     188          18 :                                                                   funk_txn,
     189          18 :                                                                   pubkey,
     190          18 :                                                                   &acct->private_state.const_rec,
     191          18 :                                                                   &err,
     192          18 :                                                                   NULL );
     193             : 
     194          18 :   if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
     195           3 :     return err;
     196           3 :   }
     197             : 
     198          15 :   if( FD_UNLIKELY( !fd_account_meta_exists( meta ) ) ) {
     199           0 :     return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
     200           0 :   }
     201             : 
     202          15 :   if( FD_UNLIKELY( acct->magic!=FD_TXN_ACCOUNT_MAGIC ) ) {
     203           0 :     return FD_ACC_MGR_ERR_WRONG_MAGIC;
     204           0 :   }
     205             : 
     206             :   /* setup global addresses of meta and data for exec and replay tile sharing */
     207          15 :   fd_wksp_t * funk_wksp          = fd_funk_wksp( funk );
     208          15 :   acct->private_state.meta_gaddr = fd_wksp_gaddr( funk_wksp, acct->private_state.const_meta );
     209          15 :   acct->private_state.data_gaddr = fd_wksp_gaddr( funk_wksp, acct->private_state.const_data );
     210             : 
     211          15 :   fd_txn_account_setup_readonly( acct, pubkey, meta );
     212             : 
     213          15 :   return FD_ACC_MGR_SUCCESS;
     214          15 : }
     215             : 
     216             : int
     217             : fd_txn_account_init_from_funk_mutable( fd_txn_account_t *  acct,
     218             :                                        fd_pubkey_t const * pubkey,
     219             :                                        fd_funk_t *         funk,
     220             :                                        fd_funk_txn_t *     funk_txn,
     221             :                                        int                 do_create,
     222          30 :                                        ulong               min_data_sz ) {
     223          30 :   fd_txn_account_init( acct );
     224             : 
     225          30 :   fd_funk_rec_prepare_t prepare = {0};
     226          30 :   int err = FD_ACC_MGR_SUCCESS;
     227          30 :   fd_account_meta_t * meta = fd_funk_get_acc_meta_mutable( funk,
     228          30 :                                                            funk_txn,
     229          30 :                                                            pubkey,
     230          30 :                                                            do_create,
     231          30 :                                                            min_data_sz,
     232          30 :                                                            &acct->private_state.rec,
     233          30 :                                                            &prepare,
     234          30 :                                                            &err );
     235             : 
     236          30 :   if( FD_UNLIKELY( !meta ) ) {
     237           0 :     return err;
     238           0 :   }
     239             : 
     240          30 :   if( FD_UNLIKELY( meta->magic!=FD_ACCOUNT_META_MAGIC ) ) {
     241           0 :     return FD_ACC_MGR_ERR_WRONG_MAGIC;
     242           0 :   }
     243             : 
     244             :   /* exec tile should never call this function, so the global addresses of
     245             :      meta and data should never be used. Instead, populate the prepared_rec
     246             :      field so that any created records can be published with fd_txn_account_mutable_fini. */
     247          30 :   acct->prepared_rec = prepare;
     248          30 :   fd_txn_account_setup_mutable( acct, pubkey, meta );
     249             : 
     250             :   /* trigger a segfault if the exec tile calls this function,
     251             :      as funk will be mapped read-only */
     252          30 :   acct->private_state.data[0] = acct->private_state.data[0];
     253             : 
     254          30 :   return FD_ACC_MGR_SUCCESS;
     255          30 : }
     256             : 
     257             : /* Funk save function impl */
     258             : 
     259             : int
     260             : fd_txn_account_save_internal( fd_txn_account_t * acct,
     261           0 :                               fd_funk_t *        funk ) {
     262           0 :   if( acct->private_state.rec == NULL ) {
     263           0 :     return FD_ACC_MGR_ERR_WRITE_FAILED;
     264           0 :   }
     265             : 
     266           0 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
     267           0 :   ulong reclen = sizeof(fd_account_meta_t)+acct->private_state.const_meta->dlen;
     268           0 :   uchar * raw = fd_funk_val( acct->private_state.rec, wksp );
     269           0 :   fd_memcpy( raw, acct->private_state.meta, reclen );
     270             : 
     271           0 :   return FD_ACC_MGR_SUCCESS;
     272           0 : }
     273             : 
     274             : int
     275             : fd_txn_account_save( fd_txn_account_t * acct,
     276             :                      fd_funk_t *        funk,
     277             :                      fd_funk_txn_t *    txn,
     278           0 :                      fd_wksp_t *        acc_data_wksp ) {
     279           0 :   acct->private_state.meta = fd_wksp_laddr( acc_data_wksp, acct->private_state.meta_gaddr );
     280           0 :   acct->private_state.data = fd_wksp_laddr( acc_data_wksp, acct->private_state.data_gaddr );
     281             : 
     282           0 :   if( acct->private_state.meta == NULL ) {
     283             :     /* The meta is NULL so the account is not writable. */
     284           0 :     FD_LOG_DEBUG(( "fd_txn_account_save: account is not writable: %s", FD_BASE58_ENC_32_ALLOCA( acct->pubkey ) ));
     285           0 :     return FD_ACC_MGR_ERR_WRITE_FAILED;
     286           0 :   }
     287             : 
     288           0 :   acct->private_state.const_meta = acct->private_state.meta;
     289           0 :   acct->private_state.const_data = acct->private_state.data;
     290             : 
     291           0 :   fd_funk_rec_key_t key = fd_funk_acc_key( acct->pubkey );
     292             : 
     293             :   /* Remove previous incarnation of the account's record from the transaction, so that we don't hash it twice */
     294           0 :   fd_funk_rec_hard_remove( funk, txn, &key );
     295             : 
     296           0 :   int err;
     297           0 :   fd_funk_rec_prepare_t prepare[1];
     298           0 :   fd_funk_rec_t * rec = fd_funk_rec_prepare( funk, txn, &key, prepare, &err );
     299           0 :   if( rec == NULL ) FD_LOG_ERR(( "unable to insert a new record, error %d", err ));
     300             : 
     301           0 :   acct->private_state.rec = rec;
     302           0 :   ulong       reclen = sizeof(fd_account_meta_t)+acct->private_state.const_meta->dlen;
     303           0 :   fd_wksp_t * wksp   = fd_funk_wksp( funk );
     304           0 :   if( fd_funk_val_truncate(
     305           0 :       rec,
     306           0 :       fd_funk_alloc( funk ),
     307           0 :       wksp,
     308           0 :       0UL,
     309           0 :       reclen,
     310           0 :       &err ) == NULL ) {
     311           0 :     FD_LOG_ERR(( "fd_funk_val_truncate(sz=%lu) for account failed (%i-%s)", reclen, err, fd_funk_strerror( err ) ));
     312           0 :   }
     313           0 :   err = fd_txn_account_save_internal( acct, funk );
     314           0 :   if( FD_UNLIKELY( err ) ) {
     315           0 :     FD_LOG_ERR(( "fd_txn_account_save_internal() failed (%i-%s)", err, fd_funk_strerror( err ) ));
     316           0 :   }
     317             : 
     318           0 :   fd_funk_rec_publish( funk, prepare );
     319             : 
     320           0 :   return err;
     321           0 : }
     322             : 
     323             : void
     324             : fd_txn_account_mutable_fini( fd_txn_account_t * acct,
     325             :                              fd_funk_t *        funk,
     326          30 :                              fd_funk_txn_t *    txn ) {
     327          30 :   fd_funk_rec_query_t query[1];
     328             : 
     329          30 :   fd_funk_rec_key_t key = fd_funk_acc_key( acct->pubkey );
     330          30 :   fd_funk_rec_t *   rec = (fd_funk_rec_t *)fd_funk_rec_query_try( funk, txn, &key, query );
     331             : 
     332             :   /* Check that the prepared record is still valid -
     333             :      if these invariants are broken something is very wrong. */
     334          30 :   if( acct->prepared_rec.rec ) {
     335             :     /* Check that the prepared record is not the Funk null value */
     336          24 :     if( !acct->prepared_rec.rec->val_gaddr ) {
     337           0 :       FD_LOG_ERR(( "invalid prepared record for %s: unexpected NULL funk record value. the record might have been modified by another thread",
     338           0 :                    FD_BASE58_ENC_32_ALLOCA( acct->pubkey ) ));
     339           0 :     }
     340             : 
     341             :     /* Ensure that the prepared record key still matches our key. */
     342          24 :     if( FD_UNLIKELY( memcmp( acct->prepared_rec.rec->pair.key, &key, sizeof(fd_funk_rec_key_t) )!=0 ) ) {
     343           0 :       FD_LOG_ERR(( "invalid prepared record for %s: the record might have been modified by another thread",
     344           0 :                   FD_BASE58_ENC_32_ALLOCA( acct->pubkey ) ));
     345           0 :     }
     346          24 :   }
     347             : 
     348             :   /* We have a prepared record, but a record already exists funk */
     349          30 :   if( rec!=NULL && acct->prepared_rec.rec!=NULL ) {
     350           0 :     FD_LOG_ERR(( "invalid prepared record for %s: trying to publish new record that is already present",
     351           0 :                    FD_BASE58_ENC_32_ALLOCA( acct->pubkey ) ));
     352           0 :   }
     353             : 
     354             :   /* Publish the record if the record is not in the current funk transaction
     355             :      and there exists a record in preparation in the fd_txn_account_t object */
     356          30 :   if( rec==NULL && acct->prepared_rec.rec!=NULL ) {
     357          24 :     fd_funk_rec_publish( funk, &acct->prepared_rec );
     358          24 :   }
     359          30 : }
     360             : 
     361             : /* read/write mutual exclusion */
     362             : 
     363             : FD_FN_PURE int
     364           0 : fd_txn_account_acquire_write_is_safe( fd_txn_account_t const * acct ) {
     365           0 :   return (!acct->private_state.refcnt_excl);
     366           0 : }
     367             : 
     368             : /* fd_txn_account_acquire_write acquires write/exclusive access.
     369             :    Causes all other write or read acquire attempts will fail.  Returns 1
     370             :    on success, 0 on failure.
     371             : 
     372             :    Mirrors a try_borrow_mut() call in Agave. */
     373             : int
     374           0 : fd_txn_account_acquire_write( fd_txn_account_t * acct ) {
     375           0 :   if( FD_UNLIKELY( !fd_txn_account_acquire_write_is_safe( acct ) ) ) {
     376           0 :     return 0;
     377           0 :   }
     378           0 :   acct->private_state.refcnt_excl = (ushort)1;
     379           0 :   return 1;
     380           0 : }
     381             : 
     382             : /* fd_txn_account_release_write{_private} releases a write/exclusive
     383             :    access handle. The private version should only be used by fd_borrowed_account_drop
     384             :    and fd_borrowed_account_destroy. */
     385             : void
     386           0 : fd_txn_account_release_write( fd_txn_account_t * acct ) {
     387           0 :   FD_TEST( acct->private_state.refcnt_excl==1U );
     388           0 :   acct->private_state.refcnt_excl = (ushort)0;
     389           0 : }
     390             : 
     391             : void
     392           0 : fd_txn_account_release_write_private( fd_txn_account_t * acct ) {
     393             :   /* Only release if it is not yet released */
     394           0 :   if( !fd_txn_account_acquire_write_is_safe( acct ) ) {
     395           0 :     fd_txn_account_release_write( acct );
     396           0 :   }
     397           0 : }
     398             : 
     399             : /* Vtable API Impls */
     400             : 
     401             : fd_account_meta_t const *
     402           0 : fd_txn_account_get_acc_meta( fd_txn_account_t const * acct ) {
     403           0 :   return acct->private_state.const_meta;
     404           0 : }
     405             : 
     406             : uchar const *
     407          12 : fd_txn_account_get_acc_data( fd_txn_account_t const * acct ) {
     408          12 :   return acct->private_state.const_data;
     409          12 : }
     410             : 
     411             : fd_funk_rec_t const *
     412           0 : fd_txn_account_get_acc_rec( fd_txn_account_t const * acct ) {
     413           0 :   return acct->private_state.const_rec;
     414           0 : }
     415             : 
     416             : uchar *
     417          18 : fd_txn_account_get_acc_data_mut_writable( fd_txn_account_t const * acct ) {
     418          18 :   return acct->private_state.data;
     419          18 : }
     420             : 
     421             : void
     422             : fd_txn_account_set_meta_readonly( fd_txn_account_t *        acct,
     423           0 :                                   fd_account_meta_t const * meta ) {
     424           0 :   acct->private_state.const_meta = meta;
     425           0 : }
     426             : 
     427             : void
     428             : fd_txn_account_set_meta_mutable_writable( fd_txn_account_t *  acct,
     429           0 :                                  fd_account_meta_t * meta ) {
     430           0 :   acct->private_state.const_meta = acct->private_state.meta = meta;
     431           0 : }
     432             : 
     433             : ulong
     434          12 : fd_txn_account_get_data_len( fd_txn_account_t const * acct ) {
     435          12 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) FD_LOG_ERR(("account is not setup" ));
     436          12 :   return acct->private_state.const_meta->dlen;
     437          12 : }
     438             : 
     439             : int
     440           0 : fd_txn_account_is_executable( fd_txn_account_t const * acct ) {
     441           0 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) FD_LOG_ERR(("account is not setup" ));
     442           0 :   return !!acct->private_state.const_meta->info.executable;
     443           0 : }
     444             : 
     445             : fd_pubkey_t const *
     446          51 : fd_txn_account_get_owner( fd_txn_account_t const * acct ) {
     447          51 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) FD_LOG_ERR(("account is not setup" ));
     448          51 :   return (fd_pubkey_t const *)acct->private_state.const_meta->info.owner;
     449          51 : }
     450             : 
     451             : ulong
     452           0 : fd_txn_account_get_lamports( fd_txn_account_t const * acct ) {
     453             :   /* (!const_meta_) considered an internal error */
     454           0 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) return 0UL;
     455           0 :   return acct->private_state.const_meta->info.lamports;
     456           0 : }
     457             : 
     458             : ulong
     459           0 : fd_txn_account_get_rent_epoch( fd_txn_account_t const * acct ) {
     460           0 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) FD_LOG_ERR(("account is not setup" ));
     461           0 :   return acct->private_state.const_meta->info.rent_epoch;
     462           0 : }
     463             : 
     464             : fd_hash_t const *
     465           0 : fd_txn_account_get_hash( fd_txn_account_t const * acct ) {
     466           0 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) FD_LOG_ERR(("account is not setup" ));
     467           0 :   return (fd_hash_t const *)acct->private_state.const_meta->hash;
     468           0 : }
     469             : 
     470             : fd_solana_account_meta_t const *
     471           0 : fd_txn_account_get_info( fd_txn_account_t const * acct ) {
     472           0 :   if( FD_UNLIKELY( !acct->private_state.const_meta ) ) FD_LOG_ERR(("account is not setup" ));
     473           0 :   return &acct->private_state.const_meta->info;
     474           0 : }
     475             : 
     476             : void
     477          12 : fd_txn_account_set_executable_writable( fd_txn_account_t * acct, int is_executable ) {
     478          12 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     479          12 :   acct->private_state.meta->info.executable = !!is_executable;
     480          12 : }
     481             : 
     482             : void
     483          12 : fd_txn_account_set_owner_writable( fd_txn_account_t * acct, fd_pubkey_t const * owner ) {
     484          12 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     485          12 :   fd_memcpy( acct->private_state.meta->info.owner, owner, sizeof(fd_pubkey_t) );
     486          12 : }
     487             : 
     488             : void
     489          12 : fd_txn_account_set_lamports_writable( fd_txn_account_t * acct, ulong lamports ) {
     490          12 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     491          12 :   acct->private_state.meta->info.lamports = lamports;
     492          12 : }
     493             : 
     494             : int
     495           0 : fd_txn_account_checked_add_lamports_writable( fd_txn_account_t * acct, ulong lamports ) {
     496           0 :   ulong balance_post = 0UL;
     497           0 :   int err = fd_ulong_checked_add( acct->vt->get_lamports( acct ), lamports, &balance_post );
     498           0 :   if( FD_UNLIKELY( err ) ) {
     499           0 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     500           0 :   }
     501             : 
     502           0 :   acct->vt->set_lamports( acct, balance_post );
     503           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     504           0 : }
     505             : 
     506             : int
     507           0 : fd_txn_account_checked_sub_lamports_writable( fd_txn_account_t * acct, ulong lamports ) {
     508           0 :   ulong balance_post = 0UL;
     509           0 :   int err = fd_ulong_checked_sub( acct->vt->get_lamports( acct ),
     510           0 :                                   lamports,
     511           0 :                                   &balance_post );
     512           0 :   if( FD_UNLIKELY( err ) ) {
     513           0 :     return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     514           0 :   }
     515             : 
     516           0 :   acct->vt->set_lamports( acct, balance_post );
     517           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     518           0 : }
     519             : 
     520             : void
     521          12 : fd_txn_account_set_rent_epoch_writable( fd_txn_account_t * acct, ulong rent_epoch ) {
     522          12 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     523          12 :   acct->private_state.meta->info.rent_epoch = rent_epoch;
     524          12 : }
     525             : 
     526             : void
     527             : fd_txn_account_set_data_writable( fd_txn_account_t * acct,
     528             :                                   void const *       data,
     529          12 :                                   ulong              data_sz) {
     530          12 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     531          12 :   acct->private_state.meta->dlen = data_sz;
     532          12 :   fd_memcpy( acct->private_state.data, data, data_sz );
     533          12 : }
     534             : 
     535             : void
     536             : fd_txn_account_set_data_len_writable( fd_txn_account_t * acct,
     537          18 :                                       ulong              data_len ) {
     538          18 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     539          18 :   acct->private_state.meta->dlen = data_len;
     540          18 : }
     541             : 
     542             : void
     543             : fd_txn_account_set_slot_writable( fd_txn_account_t * acct,
     544          18 :                          ulong              slot ) {
     545          18 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     546          18 :   acct->private_state.meta->slot = slot;
     547          18 : }
     548             : 
     549             : void
     550             : fd_txn_account_set_hash_writable( fd_txn_account_t * acct,
     551          18 :                                   fd_hash_t const *  hash ) {
     552          18 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     553          18 :   memcpy( acct->private_state.meta->hash, hash->hash, sizeof(fd_hash_t) );
     554          18 : }
     555             : 
     556             : void
     557           0 : fd_txn_account_clear_owner_writable( fd_txn_account_t * acct ) {
     558           0 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     559           0 :   fd_memset( acct->private_state.meta->info.owner, 0, sizeof(fd_pubkey_t) );
     560           0 : }
     561             : 
     562             : void
     563             : fd_txn_account_set_meta_info_writable( fd_txn_account_t *               acct,
     564          18 :                                        fd_solana_account_meta_t const * info ) {
     565          18 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     566          18 :   acct->private_state.meta->info = *info;
     567          18 : }
     568             : 
     569             : void
     570             : fd_txn_account_resize_writable( fd_txn_account_t * acct,
     571           0 :                                 ulong              dlen ) {
     572           0 :   if( FD_UNLIKELY( !acct->private_state.meta ) ) FD_LOG_ERR(("account is not mutable" ));
     573             :   /* Because the memory for an account is preallocated for the transaction
     574             :      up to the max account size, we only need to zero out bytes (for the case
     575             :      where the account grew) and update the account dlen. */
     576           0 :   ulong old_sz    = acct->private_state.meta->dlen;
     577           0 :   ulong new_sz    = dlen;
     578           0 :   ulong memset_sz = fd_ulong_sat_sub( new_sz, old_sz );
     579           0 :   fd_memset( acct->private_state.data+old_sz, 0, memset_sz );
     580             : 
     581           0 :   acct->private_state.meta->dlen = dlen;
     582           0 : }
     583             : 
     584             : uchar *
     585           0 : fd_txn_account_get_acc_data_mut_readonly( fd_txn_account_t const * acct FD_PARAM_UNUSED ) {
     586           0 :   FD_LOG_ERR(( "account is not mutable" ));
     587           0 :   return NULL;
     588           0 : }
     589             : 
     590             : void
     591             : fd_txn_account_set_meta_mutable_readonly( fd_txn_account_t *  acct FD_PARAM_UNUSED,
     592           0 :                                           fd_account_meta_t * meta FD_PARAM_UNUSED ) {
     593           0 :   FD_LOG_ERR(( "cannot set meta as mutable in a readonly account!" ));
     594           0 : }
     595             : 
     596             : void
     597             : fd_txn_account_set_executable_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     598           0 :                                         int                is_executable FD_PARAM_UNUSED ) {
     599           0 :   FD_LOG_ERR(( "cannot set executable in a readonly account!" ));
     600           0 : }
     601             : 
     602             : void
     603             : fd_txn_account_set_owner_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     604           0 :                                    fd_pubkey_t const * owner FD_PARAM_UNUSED ) {
     605           0 :   FD_LOG_ERR(( "cannot set owner in a readonly account!" ));
     606           0 : }
     607             : 
     608             : void
     609             : fd_txn_account_set_lamports_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     610           0 :                                       ulong lamports FD_PARAM_UNUSED ) {
     611           0 :   FD_LOG_ERR(( "cannot set lamports in a readonly account!" ));
     612           0 : }
     613             : 
     614             : int
     615             : fd_txn_account_checked_add_lamports_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     616           0 :                                               ulong              lamports FD_PARAM_UNUSED ) {
     617           0 :   FD_LOG_ERR(( "cannot do a checked add to lamports in a readonly account!" ));
     618           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     619           0 : }
     620             : 
     621             : int
     622             : fd_txn_account_checked_sub_lamports_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     623           0 :                                               ulong              lamports FD_PARAM_UNUSED ) {
     624           0 :   FD_LOG_ERR(( "cannot do a checked sub to lamports in a readonly account!" ));
     625           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     626           0 : }
     627             : 
     628             : void
     629             : fd_txn_account_set_rent_epoch_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     630           0 :                                         ulong              rent_epoch FD_PARAM_UNUSED ) {
     631           0 :   FD_LOG_ERR(( "cannot set rent epoch in a readonly account!" ));
     632           0 : }
     633             : 
     634             : void
     635             : fd_txn_account_set_data_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     636             :                                   void const *       data FD_PARAM_UNUSED,
     637           0 :                                   ulong              data_sz FD_PARAM_UNUSED ) {
     638           0 :   FD_LOG_ERR(( "cannot set data in a readonly account!" ));
     639           0 : }
     640             : 
     641             : void
     642             : fd_txn_account_set_data_len_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     643           0 :                                       ulong              data_len FD_PARAM_UNUSED ) {
     644           0 :   FD_LOG_ERR(( "cannot set data_len in a readonly account!" ));
     645           0 : }
     646             : 
     647             : void
     648             : fd_txn_account_set_slot_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     649           0 :                                   ulong              slot FD_PARAM_UNUSED ) {
     650           0 :   FD_LOG_ERR(("cannot set slot in a readonly account!"));
     651           0 : }
     652             : 
     653             : void
     654             : fd_txn_account_set_hash_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     655           0 :                                   fd_hash_t const *  hash FD_PARAM_UNUSED ) {
     656           0 :   FD_LOG_ERR(("cannot set hash in a readonly account!"));
     657           0 : }
     658             : 
     659             : void
     660           0 : fd_txn_account_clear_owner_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED ) {
     661           0 :   FD_LOG_ERR(("cannot clear owner in a readonly account!"));
     662           0 : }
     663             : 
     664             : void
     665             : fd_txn_account_set_meta_info_readonly( fd_txn_account_t *               acct FD_PARAM_UNUSED,
     666           0 :                                        fd_solana_account_meta_t const * info FD_PARAM_UNUSED ) {
     667           0 :   FD_LOG_ERR(("cannot set meta info in a readonly account!"));
     668           0 : }
     669             : 
     670             : void
     671             : fd_txn_account_resize_readonly( fd_txn_account_t * acct FD_PARAM_UNUSED,
     672           0 :                                 ulong              dlen FD_PARAM_UNUSED ) {
     673           0 :   FD_LOG_ERR(( "cannot resize a readonly account!" ));
     674           0 : }
     675             : 
     676             : ushort
     677           0 : fd_txn_account_is_borrowed( fd_txn_account_t const * acct ) {
     678           0 :   return !!acct->private_state.refcnt_excl;
     679           0 : }
     680             : 
     681             : int
     682           0 : fd_txn_account_is_mutable( fd_txn_account_t const * acct ) {
     683             :   /* A txn account is mutable if meta is non NULL */
     684           0 :   return acct->private_state.meta != NULL;
     685           0 : }
     686             : 
     687             : int
     688           0 : fd_txn_account_is_readonly( fd_txn_account_t const * acct ) {
     689             :   /* A txn account is readonly if only the const_meta_ field is non NULL */
     690           0 :   return acct->private_state.const_meta!=NULL && acct->private_state.meta==NULL;
     691           0 : }
     692             : 
     693             : int
     694           0 : fd_txn_account_try_borrow_mut( fd_txn_account_t * acct ) {
     695           0 :   return fd_txn_account_acquire_write( acct );
     696           0 : }
     697             : 
     698             : void
     699           0 : fd_txn_account_drop( fd_txn_account_t * acct ) {
     700           0 :   fd_txn_account_release_write_private( acct );
     701           0 : }
     702             : 
     703             : void
     704          12 : fd_txn_account_set_readonly( fd_txn_account_t * acct ) {
     705          12 :   acct->private_state.meta = NULL;
     706          12 :   acct->private_state.data = NULL;
     707          12 :   acct->private_state.rec  = NULL;
     708          12 :   acct->vt                 = &fd_txn_account_readonly_vtable;
     709          12 : }
     710             : 
     711             : void
     712           0 : fd_txn_account_set_mutable( fd_txn_account_t * acct ) {
     713           0 :   acct->private_state.meta = (void *)acct->private_state.const_meta;
     714           0 :   acct->private_state.data = (void *)acct->private_state.const_data;
     715           0 :   acct->private_state.rec  = (void *)acct->private_state.const_rec;
     716           0 :   acct->vt                 = &fd_txn_account_writable_vtable;
     717           0 : }
     718             : 
     719             : /* vtable definitions */
     720             : 
     721             : #define FD_TXN_ACCOUNT_VTABLE_DEF( type )                             \
     722             : const fd_txn_account_vtable_t                                         \
     723             : fd_txn_account_##type##_vtable = {                                    \
     724             :   .get_meta             = fd_txn_account_get_acc_meta,                \
     725             :   .get_data             = fd_txn_account_get_acc_data,                \
     726             :   .get_rec              = fd_txn_account_get_acc_rec,                 \
     727             :                                                                       \
     728             :   .get_data_mut         = fd_txn_account_get_acc_data_mut_##type,     \
     729             :                                                                       \
     730             :   .set_meta_readonly    = fd_txn_account_set_meta_readonly,           \
     731             :   .set_meta_mutable     = fd_txn_account_set_meta_mutable_##type,     \
     732             :                                                                       \
     733             :   .get_data_len         = fd_txn_account_get_data_len,                \
     734             :   .is_executable        = fd_txn_account_is_executable,               \
     735             :   .get_owner            = fd_txn_account_get_owner,                   \
     736             :   .get_lamports         = fd_txn_account_get_lamports,                \
     737             :   .get_rent_epoch       = fd_txn_account_get_rent_epoch,              \
     738             :   .get_hash             = fd_txn_account_get_hash,                    \
     739             :   .get_info             = fd_txn_account_get_info,                    \
     740             :                                                                       \
     741             :   .set_executable       = fd_txn_account_set_executable_##type,       \
     742             :   .set_owner            = fd_txn_account_set_owner_##type,            \
     743             :   .set_lamports         = fd_txn_account_set_lamports_##type,         \
     744             :   .checked_add_lamports = fd_txn_account_checked_add_lamports_##type, \
     745             :   .checked_sub_lamports = fd_txn_account_checked_sub_lamports_##type, \
     746             :   .set_rent_epoch       = fd_txn_account_set_rent_epoch_##type,       \
     747             :   .set_data             = fd_txn_account_set_data_##type,             \
     748             :   .set_data_len         = fd_txn_account_set_data_len_##type,         \
     749             :   .set_slot             = fd_txn_account_set_slot_##type,             \
     750             :   .set_hash             = fd_txn_account_set_hash_##type,             \
     751             :   .clear_owner          = fd_txn_account_clear_owner_##type,          \
     752             :   .set_info             = fd_txn_account_set_meta_info_##type,        \
     753             :   .resize               = fd_txn_account_resize_##type,               \
     754             :                                                                       \
     755             :   .is_borrowed          = fd_txn_account_is_borrowed,                 \
     756             :   .is_mutable           = fd_txn_account_is_mutable,                  \
     757             :   .is_readonly          = fd_txn_account_is_readonly,                 \
     758             :                                                                       \
     759             :   .try_borrow_mut       = fd_txn_account_try_borrow_mut,              \
     760             :   .drop                 = fd_txn_account_drop,                        \
     761             :                                                                       \
     762             :   .set_readonly         = fd_txn_account_set_readonly,                \
     763             :   .set_mutable          = fd_txn_account_set_mutable                  \
     764             : }
     765             : 
     766             : FD_TXN_ACCOUNT_VTABLE_DEF( readonly );
     767             : FD_TXN_ACCOUNT_VTABLE_DEF( writable );
     768             : 
     769             : #undef FD_TXN_ACCOUNT_VTABLE_DEF

Generated by: LCOV version 1.14