LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_acc_mgr.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 22 32 68.8 %
Date: 2025-07-01 05:00:49 Functions: 7 452 1.5 %

          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          93 : #define FD_ACC_MGR_SUCCESS             (0)
      18          12 : #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          27 : fd_account_meta_init( fd_account_meta_t * m ) {
      46          27 :   fd_memset( m, 0, sizeof(fd_account_meta_t) );
      47          27 :   m->magic = FD_ACCOUNT_META_MAGIC;
      48          27 :   m->hlen  = sizeof(fd_account_meta_t);
      49          27 : }
      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          33 : fd_account_meta_exists( fd_account_meta_t const * m ) {
      58             : 
      59          33 :   if( !m ) return 0;
      60             : 
      61          33 : # if FD_HAS_AVX
      62          33 :   wl_t o = wl_ldu( m->info.owner );
      63          33 :   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          33 :   return ( ( m->info.lamports > 0 ) |
      72          33 :            ( m->dlen          > 0 ) |
      73          33 :            ( has_owner            ) );
      74             : 
      75          33 : }
      76             : 
      77             : /* Funk key handling **************************************************/
      78             : 
      79             : /* fd_acc_funk_key returns a fd_funk database key given an account
      80             :    address. */
      81             : 
      82             : FD_FN_PURE static inline fd_funk_rec_key_t
      83         123 : fd_funk_acc_key( fd_pubkey_t const * pubkey ) {
      84         123 :   fd_funk_rec_key_t key = {0};
      85         123 :   memcpy( key.uc, pubkey, sizeof(fd_pubkey_t) );
      86         123 :   key.uc[ FD_FUNK_REC_KEY_FOOTPRINT - 1 ] = FD_FUNK_KEY_TYPE_ACC;
      87         123 :   return key;
      88         123 : }
      89             : 
      90             : /* fd_funk_key_is_acc returns 1 if given fd_funk key is an account
      91             :    and 0 otherwise. */
      92             : 
      93             : FD_FN_PURE static inline int
      94           0 : fd_funk_key_is_acc( fd_funk_rec_key_t const * id ) {
      95           0 :   return id->uc[ FD_FUNK_REC_KEY_FOOTPRINT - 1 ] == FD_FUNK_KEY_TYPE_ACC;
      96           0 : }
      97             : 
      98             : /* Account Access from Funk APIs *************************************************/
      99             : 
     100             : /* The following fd_funk_acc_mgr APIs translate between the runtime account DB abstraction
     101             :    and the actual funk database.
     102             : 
     103             :    ### Translation
     104             : 
     105             :    Each runtime account is backed by a funk record.  However, not all
     106             :    funk records contain an account.  Funk records may temporarily hold
     107             :    "deleted accounts".
     108             : 
     109             :    The memory layout of the account funk record data is
     110             :    (fd_account_meta_t, padding, account data). */
     111             : 
     112             : /* fd_funk_get_acc_meta_readonly requests a read-only handle to account data.
     113             :    funk is the database handle.  txn is the database
     114             :    transaction to query.  pubkey is the account key to query.
     115             : 
     116             :    On success:
     117             :    - loads the account data into in-memory cache
     118             :    - returns a pointer to it in the caller's local address space
     119             :    - if out_rec!=NULL, sets *out_rec to a pointer to the funk rec.
     120             :      This handle is suitable as opt_con_rec for fd_funk_get_acc_meta_readonly.
     121             :    - notably, leaves *opt_err untouched, even if opt_err!=NULL
     122             : 
     123             :    First byte of returned pointer is first byte of fd_account_meta_t.
     124             :    To find data region of account, add (fd_account_meta_t)->hlen.
     125             : 
     126             :    Lifetime of returned fd_funk_rec_t and account record pointers ends
     127             :    when user calls modify_data for same account, or tranasction ends.
     128             : 
     129             :    On failure, returns NULL, and sets *opt_err if opt_err!=NULL.
     130             :    Reasons for error include
     131             :    - account not found
     132             :    - internal database or user error (out of memory, attempting to view
     133             :      record which has an active modify_data handle, etc.)
     134             : 
     135             :    It is always wrong to cast return value to a non-const pointer.
     136             :    Instead, use fd_funk_get_acc_meta_mutable to acquire a mutable handle.
     137             : 
     138             :    if txn_out is supplied (non-null), the txn the key was found in
     139             :    is returned. If *txn_out == NULL, the key was found in the root
     140             :    context.
     141             : 
     142             :    IMPORTANT: fd_funk_get_acc_meta_readonly is only safe if it
     143             :    is guaranteed there are no other modifying accesses to the account. */
     144             : 
     145             : fd_account_meta_t const *
     146             : fd_funk_get_acc_meta_readonly( fd_funk_t const *      funk,
     147             :                                fd_funk_txn_t const *  txn,
     148             :                                fd_pubkey_t const *    pubkey,
     149             :                                fd_funk_rec_t const ** opt_out_rec,
     150             :                                int *                  opt_err,
     151             :                                fd_funk_txn_t const ** txn_out );
     152             : 
     153             : /* fd_funk_get_acc_meta_mutable requests a writable handle to an account.
     154             :    Follows interface of fd_funk_get_account_meta_readonly with the following
     155             :    changes:
     156             : 
     157             :    - do_create controls behavior if account does not exist.  If set to
     158             :      0, returns error.  If set to 1, creates account with given size
     159             :      and zero-initializes metadata.  Caller must initialize metadata of
     160             :      returned handle in this case.
     161             :    - min_data_sz is the minimum writable data size that the caller will
     162             :      accept.  This parameter will never shrink an existing account.  If
     163             :      do_create, specifies the new account's size.  Otherwise, increases
     164             :      record size if necessary.
     165             :    - When resizing or creating an account, the caller should also always
     166             :      set the account meta's size field.  This is not done automatically.
     167             :    - If caller already has a read-only handle to the requested account,
     168             :      opt_con_rec can be used to skip query by pubkey.
     169             :    - In most cases, account is copied to "dirty cache".
     170             : 
     171             :    On success:
     172             :    - If opt_out_rec!=NULL, sets *opt_out_rec to a pointer to writable
     173             :      funk rec.
     174             :    - If a record was cloned from an ancestor funk txn or created,
     175             :      out_prepare is populated with the prepared record object.
     176             :    - Returns pointer to mutable account metadata and data analogous to
     177             :      fd_funk_get_acc_meta_readonly.
     178             :    - IMPORTANT:  Return value may point to the same memory region as a
     179             :      previous calls to fd_funk_get_acc_meta_readonly or fd_funk_get_acc_meta_mutable do,
     180             :      for the same funk rec (account/txn pair).  fd_funk_acc_mgr APIs only promises
     181             :      that account handles requested for different funk txns will not
     182             :      alias. Generally, for each funk txn, the user should only ever
     183             :      access the latest handle returned by view/modify.
     184             : 
     185             :    IMPORTANT: fd_funk_get_acc_meta_mutable can only be called if
     186             :    it is guaranteed that there are no other modifying accesses to
     187             :    that account. */
     188             : 
     189             : fd_account_meta_t *
     190             : fd_funk_get_acc_meta_mutable( fd_funk_t *             funk,
     191             :                               fd_funk_txn_t *         txn,
     192             :                               fd_pubkey_t const *     pubkey,
     193             :                               int                     do_create,
     194             :                               ulong                   min_data_sz,
     195             :                               fd_funk_rec_t **        opt_out_rec,
     196             :                               fd_funk_rec_prepare_t * out_prepare,
     197             :                               int *                   opt_err );
     198             : 
     199             : /* fd_acc_mgr_strerror converts an fd_acc_mgr error code into a human
     200             :    readable cstr.  The lifetime of the returned pointer is infinite and
     201             :    the call itself is thread safe.  The returned pointer is always to a
     202             :    non-NULL cstr. */
     203             : 
     204             : FD_FN_CONST char const *
     205             : fd_acc_mgr_strerror( int err );
     206             : 
     207             : FD_PROTOTYPES_END
     208             : 
     209             : #endif /* HEADER_fd_src_flamenco_runtime_fd_acc_mgr_h */

Generated by: LCOV version 1.14