LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_acc_mgr.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 22 38 57.9 %
Date: 2025-08-05 05:04:49 Functions: 4 546 0.7 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_fd_acc_mgr_h
       2             : #define HEADER_fd_src_flamenco_runtime_fd_acc_mgr_h
       3             : 
       4             : /* fd_acc_mgr provides APIs for the Solana account database. */
       5             : 
       6             : #include "../fd_flamenco_base.h"
       7             : #include "../../ballet/txn/fd_txn.h"
       8             : #include "fd_txn_account.h"
       9             : 
      10             : #if FD_HAS_AVX
      11             : #include "../../util/simd/fd_avx.h"
      12             : #endif
      13             : 
      14             : /* FD_ACC_MGR_{SUCCESS,ERR{...}} are account management specific error codes.
      15             :    To be stored in an int. */
      16             : 
      17        6138 : #define FD_ACC_MGR_SUCCESS             (0)
      18        7806 : #define FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT (-1)
      19           0 : #define FD_ACC_MGR_ERR_WRITE_FAILED    (-2)
      20           0 : #define FD_ACC_MGR_ERR_READ_FAILED     (-3)
      21           0 : #define FD_ACC_MGR_ERR_WRONG_MAGIC     (-4)
      22             : 
      23             : /* FD_ACC_SZ_MAX is the hardcoded size limit of a Solana account. */
      24             : 
      25           0 : #define FD_ACC_SZ_MAX       (10UL<<20) /* 10MiB */
      26             : 
      27           0 : #define FD_ACC_NONCE_SZ_MAX (80UL)     /* 80 bytes */
      28             : 
      29             : /* FD_ACC_TOT_SZ_MAX is the size limit of a Solana account in the firedancer
      30             :    client. This means that it includes the max size of the account (10MiB)
      31             :    and the associated metadata. */
      32             : 
      33           0 : #define FD_ACC_TOT_SZ_MAX       (FD_ACC_SZ_MAX + sizeof(fd_account_meta_t))
      34             : 
      35           0 : #define FD_ACC_NONCE_TOT_SZ_MAX (FD_ACC_NONCE_SZ_MAX + sizeof(fd_account_meta_t))
      36             : 
      37             : FD_PROTOTYPES_BEGIN
      38             : 
      39             : /* Account Management APIs **************************************************/
      40             : 
      41             : /* The following account management APIs are helpers for fd_account_meta_t creation,
      42             :    existence, and retrieval from funk */
      43             : 
      44             : static inline void
      45          36 : fd_account_meta_init( fd_account_meta_t * m ) {
      46          36 :   fd_memset( m, 0, sizeof(fd_account_meta_t) );
      47          36 :   m->magic = FD_ACCOUNT_META_MAGIC;
      48          36 :   m->hlen  = sizeof(fd_account_meta_t);
      49          36 : }
      50             : 
      51             : /* fd_account_meta_exists checks if the account in a funk record exists or was
      52             :    deleted.  Handles NULL input safely.  Returns 0 if the account was
      53             :    deleted (zero lamports, empty data, zero owner).  Otherwise, returns
      54             :    1. */
      55             : 
      56             : static inline int
      57         513 : fd_account_meta_exists( fd_account_meta_t const * m ) {
      58             : 
      59         513 :   if( !m ) return 0;
      60             : 
      61         513 : # if FD_HAS_AVX
      62         513 :   wl_t o = wl_ldu( m->info.owner );
      63         513 :   int has_owner = !_mm256_testz_si256( o, o );
      64             : # else
      65             :   int has_owner = 0;
      66             :   for( ulong i=0UL; i<32UL; i++ )
      67             :     has_owner |= m->info.owner[i];
      68             :   has_owner = !!has_owner;
      69             : # endif
      70             : 
      71         513 :   return ( ( m->info.lamports > 0 ) |
      72         513 :            ( m->dlen          > 0 ) |
      73         513 :            ( has_owner            ) );
      74             : 
      75         513 : }
      76             : 
      77             : /* Account meta helpers */
      78             : static inline void *
      79           0 : fd_account_meta_get_data( fd_account_meta_t * m ) {
      80           0 :   return ((uchar *) m) + m->hlen;
      81           0 : }
      82             : 
      83             : static inline void const *
      84           0 : fd_account_meta_get_data_const( fd_account_meta_t const * m ) {
      85           0 :   return ((uchar const *) m) + m->hlen;
      86           0 : }
      87             : 
      88             : /* Funk key handling **************************************************/
      89             : 
      90             : /* fd_acc_funk_key returns a fd_funk database key given an account
      91             :    address. */
      92             : 
      93             : FD_FN_PURE static inline fd_funk_rec_key_t
      94        5166 : fd_funk_acc_key( fd_pubkey_t const * pubkey ) {
      95        5166 :   fd_funk_rec_key_t key = {0};
      96        5166 :   memcpy( key.uc, pubkey, sizeof(fd_pubkey_t) );
      97        5166 :   key.uc[ FD_FUNK_REC_KEY_FOOTPRINT - 1 ] = FD_FUNK_KEY_TYPE_ACC;
      98        5166 :   return key;
      99        5166 : }
     100             : 
     101             : /* fd_funk_key_is_acc returns 1 if given fd_funk key is an account
     102             :    and 0 otherwise. */
     103             : 
     104             : FD_FN_PURE static inline int
     105           0 : fd_funk_key_is_acc( fd_funk_rec_key_t const * id ) {
     106           0 :   return id->uc[ FD_FUNK_REC_KEY_FOOTPRINT - 1 ] == FD_FUNK_KEY_TYPE_ACC;
     107           0 : }
     108             : 
     109             : /* Account Access from Funk APIs *************************************************/
     110             : 
     111             : /* The following fd_funk_acc_mgr APIs translate between the runtime account DB abstraction
     112             :    and the actual funk database.
     113             : 
     114             :    ### Translation
     115             : 
     116             :    Each runtime account is backed by a funk record.  However, not all
     117             :    funk records contain an account.  Funk records may temporarily hold
     118             :    "deleted accounts".
     119             : 
     120             :    The memory layout of the account funk record data is
     121             :    (fd_account_meta_t, padding, account data). */
     122             : 
     123             : /* fd_funk_get_acc_meta_readonly requests a read-only handle to account data.
     124             :    funk is the database handle.  txn is the database
     125             :    transaction to query.  pubkey is the account key to query.
     126             : 
     127             :    On success:
     128             :    - loads the account data into in-memory cache
     129             :    - returns a pointer to it in the caller's local address space
     130             :    - if out_rec!=NULL, sets *out_rec to a pointer to the funk rec.
     131             :      This handle is suitable as opt_con_rec for fd_funk_get_acc_meta_readonly.
     132             :    - notably, leaves *opt_err untouched, even if opt_err!=NULL
     133             : 
     134             :    First byte of returned pointer is first byte of fd_account_meta_t.
     135             :    To find data region of account, add (fd_account_meta_t)->hlen.
     136             : 
     137             :    Lifetime of returned fd_funk_rec_t and account record pointers ends
     138             :    when user calls modify_data for same account, or tranasction ends.
     139             : 
     140             :    On failure, returns NULL, and sets *opt_err if opt_err!=NULL.
     141             :    Reasons for error include
     142             :    - account not found
     143             :    - internal database or user error (out of memory, attempting to view
     144             :      record which has an active modify_data handle, etc.)
     145             : 
     146             :    It is always wrong to cast return value to a non-const pointer.
     147             :    Instead, use fd_funk_get_acc_meta_mutable to acquire a mutable handle.
     148             : 
     149             :    if txn_out is supplied (non-null), the txn the key was found in
     150             :    is returned. If *txn_out == NULL, the key was found in the root
     151             :    context.
     152             : 
     153             :    IMPORTANT: fd_funk_get_acc_meta_readonly is only safe if it
     154             :    is guaranteed there are no other modifying accesses to the account. */
     155             : 
     156             : fd_account_meta_t const *
     157             : fd_funk_get_acc_meta_readonly( fd_funk_t const *      funk,
     158             :                                fd_funk_txn_t const *  txn,
     159             :                                fd_pubkey_t const *    pubkey,
     160             :                                fd_funk_rec_t const ** opt_out_rec,
     161             :                                int *                  opt_err,
     162             :                                fd_funk_txn_t const ** txn_out );
     163             : 
     164             : /* fd_funk_get_acc_meta_mutable requests a writable handle to an account.
     165             :    Follows interface of fd_funk_get_account_meta_readonly with the following
     166             :    changes:
     167             : 
     168             :    - do_create controls behavior if account does not exist.  If set to
     169             :      0, returns error.  If set to 1, creates account with given size
     170             :      and zero-initializes metadata.  Caller must initialize metadata of
     171             :      returned handle in this case.
     172             :    - min_data_sz is the minimum writable data size that the caller will
     173             :      accept.  This parameter will never shrink an existing account.  If
     174             :      do_create, specifies the new account's size.  Otherwise, increases
     175             :      record size if necessary.
     176             :    - When resizing or creating an account, the caller should also always
     177             :      set the account meta's size field.  This is not done automatically.
     178             :    - If caller already has a read-only handle to the requested account,
     179             :      opt_con_rec can be used to skip query by pubkey.
     180             :    - In most cases, account is copied to "dirty cache".
     181             : 
     182             :    On success:
     183             :    - If opt_out_rec!=NULL, sets *opt_out_rec to a pointer to writable
     184             :      funk rec.
     185             :    - If a record was cloned from an ancestor funk txn or created,
     186             :      out_prepare is populated with the prepared record object.
     187             :    - Returns pointer to mutable account metadata and data analogous to
     188             :      fd_funk_get_acc_meta_readonly.
     189             :    - IMPORTANT:  Return value may point to the same memory region as a
     190             :      previous calls to fd_funk_get_acc_meta_readonly or fd_funk_get_acc_meta_mutable do,
     191             :      for the same funk rec (account/txn pair).  fd_funk_acc_mgr APIs only promises
     192             :      that account handles requested for different funk txns will not
     193             :      alias. Generally, for each funk txn, the user should only ever
     194             :      access the latest handle returned by view/modify.
     195             : 
     196             :    IMPORTANT: fd_funk_get_acc_meta_mutable can only be called if
     197             :    it is guaranteed that there are no other modifying accesses to
     198             :    that account. */
     199             : 
     200             : fd_account_meta_t *
     201             : fd_funk_get_acc_meta_mutable( fd_funk_t *             funk,
     202             :                               fd_funk_txn_t *         txn,
     203             :                               fd_pubkey_t const *     pubkey,
     204             :                               int                     do_create,
     205             :                               ulong                   min_data_sz,
     206             :                               fd_funk_rec_t **        opt_out_rec,
     207             :                               fd_funk_rec_prepare_t * out_prepare,
     208             :                               int *                   opt_err );
     209             : 
     210             : /* fd_acc_mgr_strerror converts an fd_acc_mgr error code into a human
     211             :    readable cstr.  The lifetime of the returned pointer is infinite and
     212             :    the call itself is thread safe.  The returned pointer is always to a
     213             :    non-NULL cstr. */
     214             : 
     215             : FD_FN_CONST char const *
     216             : fd_acc_mgr_strerror( int err );
     217             : 
     218             : FD_PROTOTYPES_END
     219             : 
     220             : #endif /* HEADER_fd_src_flamenco_runtime_fd_acc_mgr_h */

Generated by: LCOV version 1.14