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 2046960 : fd_exec_epoch_ctx_align( void ) { 10 2046960 : return FD_EXEC_EPOCH_CTX_ALIGN; 11 2046960 : } 12 : 13 : static ulong 14 : fd_exec_epoch_ctx_footprint_ext( fd_exec_epoch_ctx_layout_t * layout, 15 815718 : ulong vote_acc_max ) { 16 : 17 815718 : if( FD_UNLIKELY( !vote_acc_max ) ) return 0UL; 18 : 19 815718 : fd_memset( layout, 0, sizeof(fd_exec_epoch_ctx_layout_t) ); 20 815718 : layout->vote_acc_max = vote_acc_max; 21 : 22 815718 : ulong stake_votes_sz = fd_vote_accounts_pair_t_map_footprint( vote_acc_max ); if( !stake_votes_sz ) return 0UL; 23 815718 : ulong stake_delegations_sz = fd_delegation_pair_t_map_footprint ( vote_acc_max ); if( !stake_delegations_sz ) return 0UL; 24 815718 : ulong next_epoch_stakes_sz = fd_vote_accounts_pair_t_map_footprint( vote_acc_max ); if( !next_epoch_stakes_sz ) return 0UL; 25 815718 : ulong leaders_sz = fd_epoch_leaders_footprint( MAX_PUB_CNT, MAX_SLOTS_CNT ); if( !leaders_sz ) FD_LOG_CRIT(( "invalid fd_epoch_leaders footprint" )); 26 : 27 815718 : FD_SCRATCH_ALLOC_INIT( l, 0 ); 28 815718 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_epoch_ctx_t), sizeof(fd_exec_epoch_ctx_t) ); 29 815718 : layout->stake_votes_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_vote_accounts_pair_t_map_align(), stake_votes_sz ); 30 815718 : layout->stake_delegations_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_delegation_pair_t_map_align(), stake_delegations_sz ); 31 815718 : layout->next_epoch_stakes_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_vote_accounts_pair_t_map_align(), next_epoch_stakes_sz ); 32 815718 : layout->leaders_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_leaders_align(), leaders_sz ); 33 : 34 815718 : return layout->footprint = (ulong)FD_SCRATCH_ALLOC_FINI( l, fd_exec_epoch_ctx_align() ); 35 815718 : } 36 : 37 : ulong 38 407859 : fd_exec_epoch_ctx_footprint( ulong vote_acc_max ) { 39 407859 : fd_exec_epoch_ctx_layout_t layout[1]; 40 407859 : return fd_exec_epoch_ctx_footprint_ext( layout, vote_acc_max ); 41 407859 : } 42 : 43 : void * 44 : fd_exec_epoch_ctx_new( void * mem, 45 407859 : ulong vote_acc_max ) { 46 407859 : if( FD_UNLIKELY( !mem ) ) { 47 0 : FD_LOG_WARNING(( "NULL mem" )); 48 0 : return NULL; 49 0 : } 50 : 51 407859 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_EPOCH_CTX_ALIGN ) ) ) { 52 0 : FD_LOG_WARNING(( "misaligned mem" )); 53 0 : return NULL; 54 0 : } 55 : 56 407859 : fd_exec_epoch_ctx_t * self = mem; 57 407859 : fd_memset( self, 0, sizeof(fd_exec_epoch_ctx_t) ); 58 : 59 407859 : if( FD_UNLIKELY( !fd_exec_epoch_ctx_footprint_ext( &self->layout, vote_acc_max ) ) ) { 60 0 : FD_LOG_WARNING(( "invalid vote_acc_max" )); 61 0 : return NULL; 62 0 : } 63 : 64 407859 : fd_exec_epoch_ctx_bank_mem_setup( self ); 65 : 66 407859 : fd_features_disable_all( &self->features ); 67 407859 : self->epoch_bank.cluster_version[0] = FD_DEFAULT_AGAVE_CLUSTER_VERSION_MAJOR; 68 407859 : self->epoch_bank.cluster_version[1] = FD_DEFAULT_AGAVE_CLUSTER_VERSION_MINOR; 69 407859 : self->epoch_bank.cluster_version[2] = FD_DEFAULT_AGAVE_CLUSTER_VERSION_PATCH; 70 407859 : fd_features_enable_cleaned_up( &self->features, self->epoch_bank.cluster_version ); 71 : 72 407859 : FD_COMPILER_MFENCE(); 73 407859 : self->magic = FD_EXEC_EPOCH_CTX_MAGIC; 74 407859 : FD_COMPILER_MFENCE(); 75 : 76 407859 : return mem; 77 407859 : } 78 : 79 : fd_exec_epoch_ctx_t * 80 407859 : fd_exec_epoch_ctx_join( void * mem ) { 81 407859 : if( FD_UNLIKELY( !mem ) ) { 82 0 : FD_LOG_WARNING(( "NULL block" )); 83 0 : return NULL; 84 0 : } 85 : 86 407859 : fd_exec_epoch_ctx_t * ctx = (fd_exec_epoch_ctx_t *) mem; 87 : 88 407859 : if( FD_UNLIKELY( ctx->magic!=FD_EXEC_EPOCH_CTX_MAGIC ) ) { 89 0 : FD_LOG_WARNING(( "bad magic" )); 90 0 : return NULL; 91 0 : } 92 : 93 407859 : return ctx; 94 407859 : } 95 : 96 : static void 97 0 : epoch_ctx_bank_mem_leave( fd_exec_epoch_ctx_t * epoch_ctx ) { 98 0 : void * mem = epoch_ctx; 99 0 : fd_exec_epoch_ctx_layout_t const * layout = &epoch_ctx->layout; 100 : 101 0 : void * stake_votes_mem = (void *)( (ulong)mem + layout->stake_votes_off ); 102 0 : void * stake_delegations_mem = (void *)( (ulong)mem + layout->stake_delegations_off ); 103 : 104 0 : fd_vote_accounts_pair_t_map_leave ( stake_votes_mem ); 105 0 : fd_delegation_pair_t_map_leave ( stake_delegations_mem ); 106 0 : } 107 : 108 : void * 109 0 : fd_exec_epoch_ctx_leave( fd_exec_epoch_ctx_t * ctx ) { 110 0 : if( FD_UNLIKELY( !ctx ) ) { 111 0 : FD_LOG_WARNING(( "NULL block" )); 112 0 : return NULL; 113 0 : } 114 : 115 0 : if( FD_UNLIKELY( ctx->magic!=FD_EXEC_EPOCH_CTX_MAGIC ) ) { 116 0 : FD_LOG_WARNING(( "bad magic" )); 117 0 : return NULL; 118 0 : } 119 : 120 0 : epoch_ctx_bank_mem_leave( ctx ); 121 : 122 0 : return (void *) ctx; 123 0 : } 124 : 125 : void * 126 0 : fd_exec_epoch_ctx_delete( void * mem ) { 127 0 : if( FD_UNLIKELY( !mem ) ) { 128 0 : FD_LOG_WARNING(( "NULL mem" )); 129 0 : return NULL; 130 0 : } 131 : 132 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_EXEC_EPOCH_CTX_ALIGN) ) ) { 133 0 : FD_LOG_WARNING(( "misaligned mem" )); 134 0 : return NULL; 135 0 : } 136 : 137 0 : fd_exec_epoch_ctx_t * hdr = (fd_exec_epoch_ctx_t *)mem; 138 0 : if( FD_UNLIKELY( hdr->magic!=FD_EXEC_EPOCH_CTX_MAGIC ) ) { 139 0 : FD_LOG_WARNING(( "bad magic" )); 140 0 : return NULL; 141 0 : } 142 0 : fd_exec_epoch_ctx_layout_t const * layout = &hdr->layout; 143 : 144 0 : void * next_epoch_stakes_mem = (void *)( (ulong)mem + layout->next_epoch_stakes_off ); 145 0 : void * leaders_mem = (void *)( (ulong)mem + layout->leaders_off ); 146 : 147 0 : fd_vote_accounts_pair_t_map_delete( next_epoch_stakes_mem ); 148 0 : fd_epoch_leaders_delete ( leaders_mem ); 149 : 150 0 : fd_exec_epoch_ctx_epoch_bank_delete( hdr ); 151 : 152 0 : FD_COMPILER_MFENCE(); 153 0 : FD_VOLATILE( hdr->magic ) = 0UL; 154 0 : FD_COMPILER_MFENCE(); 155 : 156 0 : return mem; 157 0 : } 158 : 159 : static void 160 0 : epoch_ctx_bank_mem_delete( fd_exec_epoch_ctx_t * epoch_ctx ) { 161 0 : void * mem = epoch_ctx; 162 0 : fd_exec_epoch_ctx_layout_t const * layout = &epoch_ctx->layout; 163 : 164 0 : void * stake_votes_mem = (void *)( (ulong)mem + layout->stake_votes_off ); 165 0 : void * stake_delegations_mem = (void *)( (ulong)mem + layout->stake_delegations_off ); 166 : 167 0 : fd_vote_accounts_pair_t_map_delete( stake_votes_mem ); 168 0 : fd_delegation_pair_t_map_delete ( stake_delegations_mem ); 169 0 : } 170 : 171 : void 172 0 : fd_exec_epoch_ctx_epoch_bank_delete( fd_exec_epoch_ctx_t * epoch_ctx ) { 173 0 : epoch_ctx_bank_mem_delete( epoch_ctx ); 174 0 : memset( &epoch_ctx->epoch_bank, 0UL, FD_EPOCH_BANK_FOOTPRINT); 175 0 : } 176 : 177 : void 178 0 : fd_exec_epoch_ctx_bank_mem_clear( fd_exec_epoch_ctx_t * epoch_ctx ) { 179 0 : fd_epoch_bank_t * const epoch_bank = &epoch_ctx->epoch_bank; 180 0 : { 181 0 : fd_vote_accounts_pair_t_mapnode_t * old_pool = epoch_bank->stakes.vote_accounts.vote_accounts_pool; 182 0 : fd_vote_accounts_pair_t_mapnode_t * old_root = epoch_bank->stakes.vote_accounts.vote_accounts_root; 183 0 : fd_vote_accounts_pair_t_map_release_tree( old_pool, old_root ); 184 0 : epoch_bank->stakes.vote_accounts.vote_accounts_root = NULL; 185 0 : } 186 0 : { 187 0 : fd_delegation_pair_t_mapnode_t * old_pool = epoch_bank->stakes.stake_delegations_pool; 188 0 : fd_delegation_pair_t_mapnode_t * old_root = epoch_bank->stakes.stake_delegations_root; 189 0 : fd_delegation_pair_t_map_release_tree( old_pool, old_root ); 190 0 : epoch_bank->stakes.stake_delegations_root = NULL; 191 0 : } 192 0 : { 193 0 : fd_vote_accounts_pair_t_mapnode_t * old_pool = epoch_bank->next_epoch_stakes.vote_accounts_pool; 194 0 : fd_vote_accounts_pair_t_mapnode_t * old_root = epoch_bank->next_epoch_stakes.vote_accounts_root; 195 0 : fd_vote_accounts_pair_t_map_release_tree( old_pool, old_root ); 196 0 : epoch_bank->next_epoch_stakes.vote_accounts_root = NULL; 197 0 : } 198 0 : } 199 : 200 : fd_epoch_bank_t * 201 407859 : fd_exec_epoch_ctx_bank_mem_setup( fd_exec_epoch_ctx_t * self ) { 202 407859 : fd_exec_epoch_ctx_layout_t * layout = &self->layout; 203 : 204 407859 : void * stake_votes_mem = (void *)( (ulong)self + layout->stake_votes_off ); 205 407859 : void * stake_delegations_mem = (void *)( (ulong)self + layout->stake_delegations_off ); 206 407859 : void * next_epoch_stakes_mem = (void *)( (ulong)self + layout->next_epoch_stakes_off ); 207 : //void * leaders_mem = (void *)( (ulong)self + layout->leaders_off ); 208 : 209 407859 : fd_epoch_bank_t * epoch_bank = &self->epoch_bank; 210 407859 : fd_epoch_bank_new( &self->epoch_bank ); 211 : 212 407859 : epoch_bank->stakes.vote_accounts.vote_accounts_pool = 213 407859 : fd_vote_accounts_pair_t_map_join( fd_vote_accounts_pair_t_map_new( stake_votes_mem, layout->vote_acc_max ) ); 214 : 215 407859 : epoch_bank->stakes.stake_delegations_pool = 216 407859 : fd_delegation_pair_t_map_join ( fd_delegation_pair_t_map_new ( stake_delegations_mem, layout->vote_acc_max ) ); 217 : 218 407859 : epoch_bank->next_epoch_stakes.vote_accounts_pool = 219 407859 : fd_vote_accounts_pair_t_map_join( fd_vote_accounts_pair_t_map_new( next_epoch_stakes_mem, layout->vote_acc_max ) ); 220 : 221 : //TODO support separate epoch leaders new and init 222 : //fd_epoch_leaders_new ( leaders_mem, MAX_PUB_CNT, MAX_SLOTS_CNT ); 223 : 224 407859 : return epoch_bank; 225 407859 : } 226 : 227 : void 228 0 : fd_exec_epoch_ctx_from_prev( fd_exec_epoch_ctx_t * self, fd_exec_epoch_ctx_t * prev ) { 229 0 : fd_memcpy( &self->features, &prev->features, sizeof(fd_features_t) ); 230 0 : self->bank_hash_cmp = prev->bank_hash_cmp; 231 0 : self->total_epoch_stake = 0UL; 232 : 233 0 : fd_epoch_bank_t * old_epoch_bank = fd_exec_epoch_ctx_epoch_bank( prev ); 234 0 : fd_epoch_bank_t * new_epoch_bank = fd_exec_epoch_ctx_bank_mem_setup( self ); 235 : 236 0 : FD_SCRATCH_SCOPE_BEGIN { 237 : 238 0 : ulong sz = fd_epoch_bank_size( old_epoch_bank ); 239 0 : uchar * buf = fd_scratch_alloc( fd_epoch_bank_align(), sz ); 240 : 241 0 : fd_bincode_encode_ctx_t encode = {.data = buf, .dataend = buf + sz }; 242 0 : fd_epoch_bank_encode( old_epoch_bank, &encode ); 243 : 244 0 : fd_bincode_decode_ctx_t decode = {.data = buf, .dataend = buf + sz, .valloc = fd_null_alloc_virtual() }; 245 0 : fd_epoch_bank_decode( new_epoch_bank, &decode); 246 : 247 0 : sz = fd_ulong_align_up( fd_epoch_leaders_footprint( MAX_PUB_CNT, MAX_SLOTS_CNT ), fd_epoch_leaders_align() ); 248 0 : fd_memcpy( fd_exec_epoch_ctx_leaders( self ), fd_exec_epoch_ctx_leaders( prev ), sz ); 249 0 : } FD_SCRATCH_SCOPE_END; 250 0 : }