Line data Source code
1 : #include "fd_exec_epoch_ctx.h" 2 : #include <assert.h> 3 : #include "../sysvar/fd_sysvar_stake_history.h" 4 : 5 : /* TODO remove this */ 6 : #define MAX_LG_SLOT_CNT 10UL 7 : 8 : ulong 9 548337 : fd_exec_epoch_ctx_align( void ) { 10 548337 : return FD_EXEC_EPOCH_CTX_ALIGN; 11 548337 : } 12 : 13 : static ulong 14 : fd_exec_epoch_ctx_footprint_ext( fd_exec_epoch_ctx_layout_t * layout, 15 217572 : ulong vote_acc_max ) { 16 : 17 217572 : if( FD_UNLIKELY( !vote_acc_max ) ) return 0UL; 18 : 19 217572 : fd_memset( layout, 0, sizeof(fd_exec_epoch_ctx_layout_t) ); 20 217572 : layout->vote_acc_max = vote_acc_max; 21 : 22 217572 : ulong stake_votes_sz = fd_vote_accounts_pair_t_map_footprint( vote_acc_max ); if( !stake_votes_sz ) return 0UL; 23 217572 : ulong stake_delegations_sz = fd_delegation_pair_t_map_footprint ( vote_acc_max ); if( !stake_delegations_sz ) return 0UL; 24 217572 : ulong stake_history_treap_sz = fd_stake_history_treap_footprint( FD_SYSVAR_STAKE_HISTORY_CAP ); if( !stake_history_treap_sz ) FD_LOG_CRIT(( "invalid fd_stake_history_treap footprint" )); 25 217572 : ulong stake_history_pool_sz = fd_stake_history_pool_footprint ( FD_SYSVAR_STAKE_HISTORY_CAP ); if( !stake_history_pool_sz ) FD_LOG_CRIT(( "invalid fd_stake_history_pool footprint" )); 26 217572 : ulong next_epoch_stakes_sz = fd_vote_accounts_pair_t_map_footprint( vote_acc_max ); if( !next_epoch_stakes_sz ) return 0UL; 27 217572 : ulong leaders_sz = fd_epoch_leaders_footprint( MAX_PUB_CNT, MAX_SLOTS_CNT ); if( !leaders_sz ) FD_LOG_CRIT(( "invalid fd_epoch_leaders footprint" )); 28 : 29 217572 : FD_SCRATCH_ALLOC_INIT( l, 0 ); 30 217572 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_epoch_ctx_t), sizeof(fd_exec_epoch_ctx_t) ); 31 217572 : layout->stake_votes_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_vote_accounts_pair_t_map_align(), stake_votes_sz ); 32 217572 : layout->stake_delegations_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_delegation_pair_t_map_align(), stake_delegations_sz ); 33 217572 : layout->stake_history_treap_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_stake_history_treap_align(), stake_history_treap_sz ); 34 217572 : layout->stake_history_pool_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_stake_history_pool_align(), stake_history_pool_sz ); 35 217572 : layout->next_epoch_stakes_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_vote_accounts_pair_t_map_align(), next_epoch_stakes_sz ); 36 217572 : layout->leaders_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_leaders_align(), leaders_sz ); 37 : 38 217572 : return layout->footprint = (ulong)FD_SCRATCH_ALLOC_FINI( l, fd_exec_epoch_ctx_align() ); 39 217572 : } 40 : 41 : ulong 42 108786 : fd_exec_epoch_ctx_footprint( ulong vote_acc_max ) { 43 108786 : fd_exec_epoch_ctx_layout_t layout[1]; 44 108786 : return fd_exec_epoch_ctx_footprint_ext( layout, vote_acc_max ); 45 108786 : } 46 : 47 : void * 48 : fd_exec_epoch_ctx_new( void * mem, 49 108786 : ulong vote_acc_max ) { 50 108786 : if( FD_UNLIKELY( !mem ) ) { 51 0 : FD_LOG_WARNING(( "NULL mem" )); 52 0 : return NULL; 53 0 : } 54 : 55 108786 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_EPOCH_CTX_ALIGN ) ) ) { 56 0 : FD_LOG_WARNING(( "misaligned mem" )); 57 0 : return NULL; 58 0 : } 59 : 60 108786 : fd_exec_epoch_ctx_t * self = mem; 61 108786 : fd_memset( self, 0, sizeof(fd_exec_epoch_ctx_t) ); 62 : 63 108786 : if( FD_UNLIKELY( !fd_exec_epoch_ctx_footprint_ext( &self->layout, vote_acc_max ) ) ) { 64 0 : FD_LOG_WARNING(( "invalid vote_acc_max" )); 65 0 : return NULL; 66 0 : } 67 : 68 108786 : fd_exec_epoch_ctx_bank_mem_setup( self ); 69 : 70 108786 : fd_features_disable_all( &self->features ); 71 108786 : self->epoch_bank.cluster_version[0] = FD_DEFAULT_AGAVE_CLUSTER_VERSION_MAJOR; 72 108786 : self->epoch_bank.cluster_version[1] = FD_DEFAULT_AGAVE_CLUSTER_VERSION_MINOR; 73 108786 : self->epoch_bank.cluster_version[2] = FD_DEFAULT_AGAVE_CLUSTER_VERSION_PATCH; 74 108786 : fd_features_enable_cleaned_up( &self->features, self->epoch_bank.cluster_version ); 75 : 76 108786 : FD_COMPILER_MFENCE(); 77 108786 : self->magic = FD_EXEC_EPOCH_CTX_MAGIC; 78 108786 : FD_COMPILER_MFENCE(); 79 : 80 108786 : return mem; 81 108786 : } 82 : 83 : fd_exec_epoch_ctx_t * 84 108786 : fd_exec_epoch_ctx_join( void * mem ) { 85 108786 : if( FD_UNLIKELY( !mem ) ) { 86 0 : FD_LOG_WARNING(( "NULL block" )); 87 0 : return NULL; 88 0 : } 89 : 90 108786 : fd_exec_epoch_ctx_t * ctx = (fd_exec_epoch_ctx_t *) mem; 91 : 92 108786 : if( FD_UNLIKELY( ctx->magic!=FD_EXEC_EPOCH_CTX_MAGIC ) ) { 93 0 : FD_LOG_WARNING(( "bad magic" )); 94 0 : return NULL; 95 0 : } 96 : 97 108786 : return ctx; 98 108786 : } 99 : 100 : static void 101 0 : epoch_ctx_bank_mem_leave( fd_exec_epoch_ctx_t * epoch_ctx ) { 102 0 : void * mem = epoch_ctx; 103 0 : fd_exec_epoch_ctx_layout_t const * layout = &epoch_ctx->layout; 104 : 105 0 : void * stake_votes_mem = (void *)( (ulong)mem + layout->stake_votes_off ); 106 0 : void * stake_delegations_mem = (void *)( (ulong)mem + layout->stake_delegations_off ); 107 0 : void * stake_history_treap_mem = (void *)( (ulong)mem + layout->stake_history_treap_off ); 108 0 : void * stake_history_pool_mem = (void *)( (ulong)mem + layout->stake_history_pool_off ); 109 : 110 0 : fd_vote_accounts_pair_t_map_leave ( stake_votes_mem ); 111 0 : fd_delegation_pair_t_map_leave ( stake_delegations_mem ); 112 0 : fd_stake_history_treap_leave ( stake_history_treap_mem ); 113 0 : (void)fd_stake_history_pool_leave ( stake_history_pool_mem ); 114 0 : } 115 : 116 : void * 117 0 : fd_exec_epoch_ctx_leave( fd_exec_epoch_ctx_t * ctx ) { 118 0 : if( FD_UNLIKELY( !ctx ) ) { 119 0 : FD_LOG_WARNING(( "NULL block" )); 120 0 : return NULL; 121 0 : } 122 : 123 0 : if( FD_UNLIKELY( ctx->magic!=FD_EXEC_EPOCH_CTX_MAGIC ) ) { 124 0 : FD_LOG_WARNING(( "bad magic" )); 125 0 : return NULL; 126 0 : } 127 : 128 0 : epoch_ctx_bank_mem_leave( ctx ); 129 : 130 0 : return (void *) ctx; 131 0 : } 132 : 133 : void * 134 0 : fd_exec_epoch_ctx_delete( void * mem ) { 135 0 : if( FD_UNLIKELY( !mem ) ) { 136 0 : FD_LOG_WARNING(( "NULL mem" )); 137 0 : return NULL; 138 0 : } 139 : 140 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_EPOCH_CTX_ALIGN) ) ) { 141 0 : FD_LOG_WARNING(( "misaligned mem" )); 142 0 : return NULL; 143 0 : } 144 : 145 0 : fd_exec_epoch_ctx_t * hdr = (fd_exec_epoch_ctx_t *)mem; 146 0 : if( FD_UNLIKELY( hdr->magic!=FD_EXEC_EPOCH_CTX_MAGIC ) ) { 147 0 : FD_LOG_WARNING(( "bad magic" )); 148 0 : return NULL; 149 0 : } 150 0 : fd_exec_epoch_ctx_layout_t const * layout = &hdr->layout; 151 : 152 0 : void * next_epoch_stakes_mem = (void *)( (ulong)mem + layout->next_epoch_stakes_off ); 153 0 : void * leaders_mem = (void *)( (ulong)mem + layout->leaders_off ); 154 : 155 0 : fd_vote_accounts_pair_t_map_delete( next_epoch_stakes_mem ); 156 0 : fd_epoch_leaders_delete ( leaders_mem ); 157 : 158 0 : fd_exec_epoch_ctx_epoch_bank_delete( hdr ); 159 : 160 0 : FD_COMPILER_MFENCE(); 161 0 : FD_VOLATILE( hdr->magic ) = 0UL; 162 0 : FD_COMPILER_MFENCE(); 163 : 164 0 : return mem; 165 0 : } 166 : 167 : static void 168 0 : epoch_ctx_bank_mem_delete( fd_exec_epoch_ctx_t * epoch_ctx ) { 169 0 : void * mem = epoch_ctx; 170 0 : fd_exec_epoch_ctx_layout_t const * layout = &epoch_ctx->layout; 171 : 172 0 : void * stake_votes_mem = (void *)( (ulong)mem + layout->stake_votes_off ); 173 0 : void * stake_delegations_mem = (void *)( (ulong)mem + layout->stake_delegations_off ); 174 0 : void * stake_history_treap_mem = (void *)( (ulong)mem + layout->stake_history_treap_off ); 175 0 : void * stake_history_pool_mem = (void *)( (ulong)mem + layout->stake_history_pool_off ); 176 : 177 0 : fd_vote_accounts_pair_t_map_delete( stake_votes_mem ); 178 0 : fd_delegation_pair_t_map_delete ( stake_delegations_mem ); 179 0 : fd_stake_history_treap_delete ( stake_history_treap_mem ); 180 0 : fd_stake_history_pool_delete ( stake_history_pool_mem ); 181 0 : } 182 : 183 : void 184 0 : fd_exec_epoch_ctx_epoch_bank_delete( fd_exec_epoch_ctx_t * epoch_ctx ) { 185 0 : epoch_ctx_bank_mem_delete( epoch_ctx ); 186 0 : memset( &epoch_ctx->epoch_bank, 0UL, FD_EPOCH_BANK_FOOTPRINT); 187 0 : } 188 : 189 : void 190 0 : fd_exec_epoch_ctx_bank_mem_clear( fd_exec_epoch_ctx_t * epoch_ctx ) { 191 0 : fd_epoch_bank_t * const epoch_bank = &epoch_ctx->epoch_bank; 192 0 : { 193 0 : fd_vote_accounts_pair_t_mapnode_t * old_pool = epoch_bank->stakes.vote_accounts.vote_accounts_pool; 194 0 : fd_vote_accounts_pair_t_mapnode_t * old_root = epoch_bank->stakes.vote_accounts.vote_accounts_root; 195 0 : fd_vote_accounts_pair_t_map_release_tree( old_pool, old_root ); 196 0 : epoch_bank->stakes.vote_accounts.vote_accounts_root = NULL; 197 0 : } 198 0 : { 199 0 : fd_delegation_pair_t_mapnode_t * old_pool = epoch_bank->stakes.stake_delegations_pool; 200 0 : fd_delegation_pair_t_mapnode_t * old_root = epoch_bank->stakes.stake_delegations_root; 201 0 : fd_delegation_pair_t_map_release_tree( old_pool, old_root ); 202 0 : epoch_bank->stakes.stake_delegations_root = NULL; 203 0 : } 204 0 : { 205 0 : fd_stake_history_entry_t * old_pool = epoch_bank->stakes.stake_history.pool; 206 0 : fd_stake_history_treap_t * old_treap = epoch_bank->stakes.stake_history.treap; 207 : 208 0 : if ( old_pool && old_treap ) { 209 0 : ulong elem_cnt = 0UL; 210 0 : ulong keys[FD_SYSVAR_STAKE_HISTORY_CAP] = {0}; 211 0 : for( fd_stake_history_treap_fwd_iter_t iter = fd_stake_history_treap_fwd_iter_init( old_treap, old_pool ); 212 0 : !fd_stake_history_treap_fwd_iter_done( iter ); 213 0 : iter = fd_stake_history_treap_fwd_iter_next( iter, old_pool ) ) { 214 0 : fd_stake_history_entry_t const * ele = fd_stake_history_treap_fwd_iter_ele_const( iter, old_pool ); 215 0 : keys[elem_cnt++] = ele->epoch; 216 0 : } 217 0 : for (ulong i=0UL; i<elem_cnt; i++) { 218 0 : fd_stake_history_entry_t * ele = fd_stake_history_treap_ele_query( old_treap, keys[i], old_pool ); 219 0 : old_treap = fd_stake_history_treap_ele_remove( old_treap, ele, old_pool ); 220 0 : fd_stake_history_pool_ele_release( old_pool, ele ); 221 0 : } 222 0 : } 223 0 : } 224 0 : { 225 0 : fd_vote_accounts_pair_t_mapnode_t * old_pool = epoch_bank->next_epoch_stakes.vote_accounts_pool; 226 0 : fd_vote_accounts_pair_t_mapnode_t * old_root = epoch_bank->next_epoch_stakes.vote_accounts_root; 227 0 : fd_vote_accounts_pair_t_map_release_tree( old_pool, old_root ); 228 0 : epoch_bank->next_epoch_stakes.vote_accounts_root = NULL; 229 0 : } 230 0 : } 231 : 232 : fd_epoch_bank_t * 233 108786 : fd_exec_epoch_ctx_bank_mem_setup( fd_exec_epoch_ctx_t * self ) { 234 108786 : fd_exec_epoch_ctx_layout_t * layout = &self->layout; 235 : 236 108786 : void * stake_votes_mem = (void *)( (ulong)self + layout->stake_votes_off ); 237 108786 : void * stake_delegations_mem = (void *)( (ulong)self + layout->stake_delegations_off ); 238 108786 : void * stake_history_treap_mem = (void *)( (ulong)self + layout->stake_history_treap_off ); 239 108786 : void * stake_history_pool_mem = (void *)( (ulong)self + layout->stake_history_pool_off ); 240 108786 : void * next_epoch_stakes_mem = (void *)( (ulong)self + layout->next_epoch_stakes_off ); 241 : //void * leaders_mem = (void *)( (ulong)self + layout->leaders_off ); 242 : 243 108786 : fd_epoch_bank_t * epoch_bank = &self->epoch_bank; 244 108786 : fd_epoch_bank_new( &self->epoch_bank ); 245 : 246 108786 : epoch_bank->stakes.vote_accounts.vote_accounts_pool = 247 108786 : fd_vote_accounts_pair_t_map_join( fd_vote_accounts_pair_t_map_new( stake_votes_mem, layout->vote_acc_max ) ); 248 : 249 108786 : epoch_bank->stakes.stake_delegations_pool = 250 108786 : fd_delegation_pair_t_map_join ( fd_delegation_pair_t_map_new ( stake_delegations_mem, layout->vote_acc_max ) ); 251 : 252 108786 : epoch_bank->stakes.stake_history.treap = 253 108786 : fd_stake_history_treap_join ( fd_stake_history_treap_new ( stake_history_treap_mem, FD_SYSVAR_STAKE_HISTORY_CAP ) ); 254 108786 : epoch_bank->stakes.stake_history.pool = 255 108786 : fd_stake_history_pool_join ( fd_stake_history_pool_new ( stake_history_pool_mem, FD_SYSVAR_STAKE_HISTORY_CAP ) ); 256 : 257 108786 : epoch_bank->next_epoch_stakes.vote_accounts_pool = 258 108786 : fd_vote_accounts_pair_t_map_join( fd_vote_accounts_pair_t_map_new( next_epoch_stakes_mem, layout->vote_acc_max ) ); 259 : 260 : //TODO support separate epoch leaders new and init 261 : //fd_epoch_leaders_new ( leaders_mem, MAX_PUB_CNT, MAX_SLOTS_CNT ); 262 : 263 108786 : return epoch_bank; 264 108786 : } 265 : 266 : void 267 0 : fd_exec_epoch_ctx_from_prev( fd_exec_epoch_ctx_t * self, fd_exec_epoch_ctx_t * prev ) { 268 0 : fd_memcpy( &self->features, &prev->features, sizeof(fd_features_t) ); 269 0 : self->bank_hash_cmp = prev->bank_hash_cmp; 270 : 271 0 : fd_epoch_bank_t * old_epoch_bank = fd_exec_epoch_ctx_epoch_bank( prev ); 272 0 : fd_epoch_bank_t * new_epoch_bank = fd_exec_epoch_ctx_bank_mem_setup( self ); 273 : 274 0 : FD_SCRATCH_SCOPE_BEGIN { 275 : 276 0 : ulong sz = fd_epoch_bank_size( old_epoch_bank ); 277 0 : uchar * buf = fd_scratch_alloc( fd_epoch_bank_align(), sz ); 278 : 279 0 : fd_bincode_encode_ctx_t encode = {.data = buf, .dataend = buf + sz }; 280 0 : fd_epoch_bank_encode( old_epoch_bank, &encode ); 281 : 282 0 : fd_bincode_decode_ctx_t decode = {.data = buf, .dataend = buf + sz, .valloc = fd_null_alloc_virtual() }; 283 0 : fd_epoch_bank_decode( new_epoch_bank, &decode); 284 : 285 0 : sz = fd_ulong_align_up( fd_epoch_leaders_footprint( MAX_PUB_CNT, MAX_SLOTS_CNT ), fd_epoch_leaders_align() ); 286 0 : fd_memcpy( fd_exec_epoch_ctx_leaders( self ), fd_exec_epoch_ctx_leaders( prev ), sz ); 287 0 : } FD_SCRATCH_SCOPE_END; 288 0 : }