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_txn_account.h" 7 : 8 : #if FD_HAS_AVX 9 : #include "../../util/simd/fd_avx.h" 10 : #endif 11 : 12 : /* FD_ACC_MGR_{SUCCESS,ERR{...}} are account management specific error codes. 13 : To be stored in an int. */ 14 : 15 5604 : #define FD_ACC_MGR_SUCCESS (0) 16 7806 : #define FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT (-1) 17 : 18 0 : #define FD_ACC_NONCE_SZ_MAX (80UL) /* 80 bytes */ 19 : 20 : /* FD_ACC_TOT_SZ_MAX is the size limit of a Solana account in the firedancer 21 : client. This means that it includes the max size of the account (10MiB) 22 : and the associated metadata. */ 23 : 24 0 : #define FD_ACC_TOT_SZ_MAX (FD_RUNTIME_ACC_SZ_MAX + sizeof(fd_account_meta_t)) 25 : 26 0 : #define FD_ACC_NONCE_TOT_SZ_MAX (FD_ACC_NONCE_SZ_MAX + sizeof(fd_account_meta_t)) 27 : 28 : FD_PROTOTYPES_BEGIN 29 : 30 : /* Account Management APIs **************************************************/ 31 : 32 : /* The following account management APIs are helpers for fd_account_meta_t creation, 33 : existence, and retrieval from funk */ 34 : 35 : static inline void 36 3 : fd_account_meta_init( fd_account_meta_t * m ) { 37 3 : fd_memset( m, 0, sizeof(fd_account_meta_t) ); 38 3 : } 39 : 40 : /* fd_account_meta_exists checks if the account in a funk record exists or was 41 : deleted. Handles NULL input safely. Returns 0 if the account was 42 : deleted (zero lamports, empty data, zero owner). Otherwise, returns 43 : 1. */ 44 : 45 : static inline int 46 0 : fd_account_meta_exists( fd_account_meta_t const * m ) { 47 : 48 0 : if( !m ) return 0; 49 : 50 0 : # if FD_HAS_AVX 51 0 : wl_t o = wl_ldu( m->owner ); 52 0 : int has_owner = !_mm256_testz_si256( o, o ); 53 : # else 54 : int has_owner = 0; 55 : for( ulong i=0UL; i<32UL; i++ ) 56 : has_owner |= m->owner[i]; 57 : has_owner = !!has_owner; 58 : # endif 59 : 60 0 : return ((m->lamports > 0UL) | 61 0 : (m->dlen > 0UL) | 62 0 : (has_owner ) ); 63 : 64 0 : } 65 : 66 : /* Account meta helpers */ 67 : static inline void * 68 3 : fd_account_meta_get_data( fd_account_meta_t * m ) { 69 3 : return ((uchar *) m) + sizeof(fd_account_meta_t); 70 3 : } 71 : 72 : static inline void const * 73 0 : fd_account_meta_get_data_const( fd_account_meta_t const * m ) { 74 0 : return ((uchar const *) m) + sizeof(fd_account_meta_t); 75 0 : } 76 : 77 : static inline ulong 78 0 : fd_account_meta_get_record_sz( fd_account_meta_t const * m ) { 79 0 : return sizeof(fd_account_meta_t) + m->dlen; 80 0 : } 81 : 82 : /* Funk key handling **************************************************/ 83 : 84 : /* fd_acc_funk_key returns a fd_funk database key given an account 85 : address. */ 86 : 87 : FD_FN_PURE static inline fd_funk_rec_key_t 88 4701 : fd_funk_acc_key( fd_pubkey_t const * pubkey ) { 89 4701 : fd_funk_rec_key_t key = {0}; 90 4701 : memcpy( key.uc, pubkey, sizeof(fd_pubkey_t) ); 91 4701 : return key; 92 4701 : } 93 : 94 : /* Account Access from Funk APIs *************************************************/ 95 : 96 : /* The following fd_funk_acc_mgr APIs translate between the runtime account DB abstraction 97 : and the actual funk database. 98 : 99 : ### Translation 100 : 101 : Each runtime account is backed by a funk record. However, not all 102 : funk records contain an account. Funk records may temporarily hold 103 : "deleted accounts". 104 : 105 : The memory layout of the account funk record data is 106 : (fd_account_meta_t, padding, account data). */ 107 : 108 : /* fd_funk_get_acc_meta_readonly requests a read-only handle to account data. 109 : funk is the database handle. txn is the database 110 : transaction to query. pubkey is the account key to query. 111 : 112 : On success: 113 : - loads the account data into in-memory cache 114 : - returns a pointer to it in the caller's local address space 115 : - if out_rec!=NULL, sets *out_rec to a pointer to the funk rec. 116 : This handle is suitable as opt_con_rec for fd_funk_get_acc_meta_readonly. 117 : - notably, leaves *opt_err untouched, even if opt_err!=NULL 118 : 119 : First byte of returned pointer is first byte of fd_account_meta_t. 120 : To find data region of account, add sizeof(fd_account_meta_t). 121 : 122 : Lifetime of returned fd_funk_rec_t and account record pointers ends 123 : when user calls modify_data for same account, or tranasction ends. 124 : 125 : On failure, returns NULL, and sets *opt_err if opt_err!=NULL. 126 : Reasons for error include 127 : - account not found 128 : - internal database or user error (out of memory, attempting to view 129 : record which has an active modify_data handle, etc.) 130 : 131 : It is always wrong to cast return value to a non-const pointer. 132 : Instead, use fd_funk_get_acc_meta_mutable to acquire a mutable handle. 133 : 134 : If xid_out is supplied (non-null), sets *xid_out to the xid in which 135 : the found record was created. 136 : 137 : IMPORTANT: fd_funk_get_acc_meta_readonly is only safe if it 138 : is guaranteed there are no other modifying accesses to the account. */ 139 : 140 : fd_account_meta_t const * 141 : fd_funk_get_acc_meta_readonly( fd_funk_t const * funk, 142 : fd_funk_txn_xid_t const * xid, 143 : fd_pubkey_t const * pubkey, 144 : fd_funk_rec_t const ** orec, 145 : int * opt_err, 146 : fd_funk_txn_xid_t * xid_out ); 147 : 148 : /* fd_acc_mgr_strerror converts an fd_acc_mgr error code into a human 149 : readable cstr. The lifetime of the returned pointer is infinite and 150 : the call itself is thread safe. The returned pointer is always to a 151 : non-NULL cstr. */ 152 : 153 : FD_FN_CONST char const * 154 : fd_acc_mgr_strerror( int err ); 155 : 156 : FD_PROTOTYPES_END 157 : 158 : #endif /* HEADER_fd_src_flamenco_runtime_fd_acc_mgr_h */