Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_accdb_fd_accdb_ref_h 2 : #define HEADER_fd_src_flamenco_accdb_fd_accdb_ref_h 3 : 4 : /* fd_accdb_ref.h provides account database handle classes. 5 : 6 : - accdb_ref is an opaque handle to an account database cache entry. 7 : - accdb_ro (extends accdb_ref) represents a read-only handle. 8 : - accdb_rw (extends accdb_ro) represents a read-write handle. 9 : - accdb_spec is an account speculative read guard 10 : 11 : These APIs sit between the database layer (abstracts away backing 12 : stores and DB specifics) and the runtime layer (offer no runtime 13 : protections). */ 14 : 15 : #include "fd_accdb_base.h" 16 : #include "../fd_flamenco_base.h" 17 : #include "../types/fd_types_custom.h" 18 : 19 : /* fd_accdb_ref_t is an opaque account database handle. */ 20 : 21 : struct fd_accdb_ref { 22 : ulong meta_laddr; 23 : ulong user_data; 24 : ulong user_data2; 25 : uchar address[32]; 26 : uint accdb_type; /* FD_ACCDB_TYPE_* */ 27 : uchar ref_type; /* FD_ACCDB_REF_* */ 28 : }; 29 : typedef struct fd_accdb_ref fd_accdb_ref_t; 30 : 31 : /* fd_accdb_ro_t is a readonly account database handle. */ 32 : 33 : union fd_accdb_ro { 34 : fd_accdb_ref_t ref[1]; 35 : struct { 36 : fd_account_meta_t const * meta; 37 : }; 38 : }; 39 : typedef union fd_accdb_ro fd_accdb_ro_t; 40 : 41 : FD_PROTOTYPES_BEGIN 42 : 43 : /* fd_accdb_ro_init_nodb creates a read-only account reference to an 44 : account that is not managed by an account database. This is useful 45 : for local caching (e.g. cross-program invocations). */ 46 : 47 : static inline fd_accdb_ro_t * 48 : fd_accdb_ro_init_nodb( fd_accdb_ro_t * ro, 49 : void const * address, 50 33 : fd_account_meta_t const * meta ) { 51 33 : ro->meta = meta; 52 33 : ro->ref->user_data = 0UL; 53 33 : ro->ref->user_data2 = 0UL; 54 33 : memcpy( ro->ref->address, address, 32UL ); 55 33 : ro->ref->accdb_type = FD_ACCDB_TYPE_NONE; 56 33 : ro->ref->ref_type = FD_ACCDB_REF_RO; 57 33 : return ro; 58 33 : } 59 : 60 : /* fd_accdb_ro_init_nodb_oob creates a read-only account reference to an 61 : account that is not managed by an account database, where the account 62 : data is stored out-of-band (i.e. not contiguous at meta+1). The 63 : data pointer is stored in user_data2 and returned by 64 : fd_accdb_ref_data_const. */ 65 : 66 : static inline fd_accdb_ro_t * 67 : fd_accdb_ro_init_nodb_oob( fd_accdb_ro_t * ro, 68 : void const * address, 69 : fd_account_meta_t const * meta, 70 72 : void const * data ) { 71 72 : ro->meta = meta; 72 72 : ro->ref->user_data = 0UL; 73 72 : ro->ref->user_data2 = (ulong)data; 74 72 : memcpy( ro->ref->address, address, 32UL ); 75 72 : ro->ref->accdb_type = FD_ACCDB_TYPE_NONE; 76 72 : ro->ref->ref_type = FD_ACCDB_REF_RO; 77 72 : return ro; 78 72 : } 79 : 80 : /* fd_accdb_ro_init_empty creates a read-only account reference to a 81 : non-existent account. */ 82 : 83 : extern fd_account_meta_t const fd_accdb_meta_empty; 84 : 85 : static inline fd_accdb_ro_t * 86 : fd_accdb_ro_init_empty( fd_accdb_ro_t * ro, 87 11139 : void const * address ) { 88 11139 : ro->meta = &fd_accdb_meta_empty; 89 11139 : ro->ref->user_data = 0UL; 90 11139 : ro->ref->user_data2 = 0UL; 91 11139 : memcpy( ro->ref->address, address, 32UL ); 92 11139 : ro->ref->accdb_type = FD_ACCDB_TYPE_NONE; 93 11139 : ro->ref->ref_type = FD_ACCDB_REF_RO; 94 11139 : return ro; 95 11139 : } 96 : 97 : static inline void const * 98 1218 : fd_accdb_ref_address( fd_accdb_ro_t const * ro ) { 99 1218 : return ro->ref->address; 100 1218 : } 101 : 102 : static inline void const * 103 3954 : fd_accdb_ref_data_const( fd_accdb_ro_t const * ro ) { 104 3954 : if( FD_UNLIKELY( ro->ref->user_data2 && ro->ref->accdb_type==FD_ACCDB_TYPE_NONE ) ) 105 93 : return (void const *)ro->ref->user_data2; 106 3861 : return (void *)( ro->meta+1 ); 107 3954 : } 108 : 109 : static inline ulong 110 9099 : fd_accdb_ref_data_sz( fd_accdb_ro_t const * ro ) { 111 9099 : return ro->meta->dlen; 112 9099 : } 113 : 114 : static inline ulong 115 25788 : fd_accdb_ref_lamports( fd_accdb_ro_t const * ro ) { 116 25788 : return ro->meta->lamports; 117 25788 : } 118 : 119 : static inline fd_pubkey_t const * 120 192 : fd_accdb_ref_owner( fd_accdb_ro_t const * ro ) { 121 192 : return fd_type_pun_const( ro->meta->owner ); 122 192 : } 123 : 124 : static inline uint 125 0 : fd_accdb_ref_exec_bit( fd_accdb_ro_t const * ro ) { 126 0 : return !!ro->meta->executable; 127 0 : } 128 : 129 : static inline ulong 130 0 : fd_accdb_ref_slot( fd_accdb_ro_t const * ro ) { 131 0 : return ro->meta->slot; 132 0 : } 133 : 134 : // void 135 : // fd_accdb_ref_lthash( fd_accdb_ro_t const * ro, 136 : // void * lthash ); 137 : 138 : FD_PROTOTYPES_END 139 : 140 : /* fd_accdb_rw_t is a writable database handle. Typically, writable 141 : handles are only available for invisible/in-prepartion records. 142 : In rare cases (e.g. when booting up), components may directly write 143 : to globally visible writable records. */ 144 : 145 : union fd_accdb_rw { 146 : fd_accdb_ref_t ref[1]; 147 : fd_accdb_ro_t ro [1]; 148 : struct { 149 : fd_account_meta_t * meta; 150 : }; 151 : }; 152 : typedef union fd_accdb_rw fd_accdb_rw_t; 153 : 154 : FD_PROTOTYPES_BEGIN 155 : 156 : /* fd_accdb_rw_init_nodb creates a writable account reference to an 157 : account that is not managed by an account database. This is useful 158 : for local caching (e.g. cross-program invocations). */ 159 : 160 : static inline fd_accdb_rw_t * 161 : fd_accdb_rw_init_nodb( fd_accdb_rw_t * rw, 162 : void const * address, 163 : fd_account_meta_t const * meta, 164 981 : ulong data_max ) { 165 981 : rw->meta = (fd_account_meta_t *)meta; 166 981 : rw->ref->user_data = data_max; 167 981 : rw->ref->user_data2 = 0UL; 168 981 : memcpy( rw->ref->address, address, 32UL ); 169 981 : rw->ref->accdb_type = FD_ACCDB_TYPE_NONE; 170 981 : return rw; 171 981 : } 172 : 173 : // void 174 : // fd_accdb_ref_clear( fd_accdb_rw_t * rw ); 175 : 176 : static inline void * 177 2628 : fd_accdb_ref_data( fd_accdb_rw_t * rw ) { 178 2628 : if( FD_UNLIKELY( rw->ref->user_data2 && rw->ref->accdb_type==FD_ACCDB_TYPE_NONE ) ) 179 0 : return (void *)rw->ref->user_data2; 180 2628 : return (void *)( rw->meta+1 ); 181 2628 : } 182 : 183 : static inline void 184 : fd_accdb_ref_lamports_set( fd_accdb_rw_t * rw, 185 8598 : ulong lamports ) { 186 8598 : rw->meta->lamports = lamports; 187 8598 : } 188 : 189 : static inline void 190 : fd_accdb_ref_owner_set( fd_accdb_rw_t * rw, 191 2415 : void const * owner ) { 192 2415 : memcpy( rw->meta->owner, owner, 32UL ); 193 2415 : } 194 : 195 : static inline void 196 : fd_accdb_ref_exec_bit_set( fd_accdb_rw_t * rw, 197 1212 : uint exec_bit ) { 198 1212 : rw->meta->executable = !!exec_bit; 199 1212 : } 200 : 201 : static inline void 202 : fd_accdb_ref_slot_set( fd_accdb_rw_t * rw, 203 48 : ulong slot ) { 204 48 : rw->meta->slot = slot; 205 48 : } 206 : 207 : /* Upcast */ 208 : 209 : static inline fd_accdb_ro_t * 210 99 : fd_accdb_ref_ro( fd_accdb_ref_t * ref ) { 211 99 : return fd_type_pun( ref ); 212 99 : } 213 : 214 : static inline fd_accdb_rw_t * 215 0 : fd_accdb_ref_rw( fd_accdb_ref_t * ref ) { 216 0 : FD_TEST( ref->ref_type==FD_ACCDB_REF_RW ); 217 0 : return fd_type_pun( ref ); 218 0 : } 219 : 220 : FD_PROTOTYPES_END 221 : 222 : FD_STATIC_ASSERT( sizeof(fd_accdb_ref_t)==sizeof(fd_accdb_ro_t), layout ); 223 : FD_STATIC_ASSERT( sizeof(fd_accdb_ref_t)==sizeof(fd_accdb_rw_t), layout ); 224 : 225 : #endif /* HEADER_fd_src_flamenco_accdb_fd_accdb_ref_h */