Line data Source code
1 : #include "fd_epoch_stakes.h" 2 : 3 : void * 4 : fd_epoch_stakes_new( void * shmem, 5 9 : ulong slot_max ) { 6 9 : if( FD_UNLIKELY( !shmem ) ) { 7 0 : FD_LOG_WARNING(( "NULL mem" )); 8 0 : return NULL; 9 0 : } 10 9 : fd_wksp_t * wksp = fd_wksp_containing( shmem ); 11 9 : if( FD_UNLIKELY( !wksp ) ) { 12 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" )); 13 0 : return NULL; 14 0 : } 15 9 : ulong footprint = fd_epoch_stakes_footprint( slot_max ); 16 9 : if( FD_UNLIKELY( !footprint ) ) { 17 0 : FD_LOG_WARNING(( "bad slot_max (%lu)", slot_max )); 18 0 : return NULL; 19 0 : } 20 : /* verify aligned to fd_epoch_stakes_align() */ 21 9 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_epoch_stakes_align() ) ) ) { 22 0 : FD_LOG_WARNING(( "misaligned mem" )); 23 0 : return NULL; 24 0 : } 25 : 26 9 : int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( slot_max ) ) + 1; 27 : 28 9 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 29 9 : fd_epoch_stakes_t * epoch_stakes = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_epoch_stakes_t), sizeof(fd_epoch_stakes_t) ); 30 9 : void * voter_stake_map = FD_SCRATCH_ALLOC_APPEND( l, fd_voter_stake_map_align(), fd_voter_stake_map_footprint ( FD_VOTER_MAX * slot_max ) ); 31 9 : void * voter_stake_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_voter_stake_pool_align(), fd_voter_stake_pool_footprint( FD_VOTER_MAX * slot_max ) ); 32 9 : void * epoch_stakes_slot_map = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_stakes_slot_map_align(), fd_epoch_stakes_slot_map_footprint( lg_slot_cnt ) ); 33 9 : void * used_acc_scratch = FD_SCRATCH_ALLOC_APPEND( l, fd_used_acc_scratch_align(), fd_used_acc_scratch_footprint( FD_VOTER_MAX * slot_max ) ); 34 9 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_epoch_stakes_align() ) == (ulong)shmem + footprint ); 35 : 36 9 : epoch_stakes->voter_stake_map = fd_voter_stake_map_join ( fd_voter_stake_map_new ( voter_stake_map, FD_VOTER_MAX * slot_max, 0 ) ); 37 9 : epoch_stakes->voter_stake_pool = fd_voter_stake_pool_join ( fd_voter_stake_pool_new ( voter_stake_pool, FD_VOTER_MAX * slot_max ) ); 38 9 : epoch_stakes->slot_stakes_map = fd_epoch_stakes_slot_map_join( fd_epoch_stakes_slot_map_new( epoch_stakes_slot_map, lg_slot_cnt, 0UL ) ); /* FIXME seed? */ 39 9 : epoch_stakes->used_acc_scratch = fd_used_acc_scratch_join ( fd_used_acc_scratch_new ( used_acc_scratch, FD_VOTER_MAX * slot_max ) ); 40 9 : return shmem; 41 9 : } 42 : 43 : fd_epoch_stakes_t * 44 9 : fd_epoch_stakes_join( void * shepoch_stakes ) { 45 9 : return shepoch_stakes; 46 9 : } 47 : 48 : ulong 49 45 : fd_epoch_stakes_slot_stakes_add( fd_epoch_stakes_t * epoch_stakes, ulong slot, fd_hash_t const * vote_account, ulong stake, ulong prev_voter_idx ) { 50 45 : fd_voter_stake_t * pool = epoch_stakes->voter_stake_pool; 51 45 : if( FD_UNLIKELY( !fd_voter_stake_pool_free( pool ) ) ) FD_LOG_CRIT(( "no free voter stakes in pool" )); 52 45 : fd_voter_stake_t * new_voter_stake = fd_voter_stake_pool_ele_acquire( pool ); 53 45 : new_voter_stake->key = (fd_voter_stake_key_t){ .vote_account = *vote_account, .slot = slot }; 54 45 : new_voter_stake->stake = stake; 55 45 : new_voter_stake->prev = prev_voter_idx; 56 45 : fd_voter_stake_map_ele_insert( epoch_stakes->voter_stake_map, new_voter_stake, pool ); 57 : 58 : /* now update the slot_stakes_map to point to the new head of the linkedlist */ 59 45 : fd_epoch_stakes_slot_t * slot_stakes = fd_epoch_stakes_slot_map_query( epoch_stakes->slot_stakes_map, slot, NULL ); 60 45 : if( FD_UNLIKELY( !slot_stakes ) ) { 61 30 : slot_stakes = fd_epoch_stakes_slot_map_insert( epoch_stakes->slot_stakes_map, slot ); 62 30 : } 63 45 : slot_stakes->voter_stake_idx = fd_voter_stake_pool_idx( pool, new_voter_stake ); 64 45 : return slot_stakes->voter_stake_idx; 65 45 : } 66 : 67 : void 68 0 : fd_epoch_stakes_slot_stakes_remove( fd_epoch_stakes_t * epoch_stakes, fd_epoch_stakes_slot_t * slot ) { 69 : /* walk stakes linkedlist and remove the voter stake at the given index */ 70 0 : ulong voter_idx = slot->voter_stake_idx; 71 0 : while( FD_UNLIKELY( voter_idx != ULONG_MAX ) ) { 72 0 : fd_voter_stake_t * voter_stake = fd_voter_stake_pool_ele( epoch_stakes->voter_stake_pool, voter_idx ); 73 0 : voter_idx = voter_stake->prev; 74 0 : fd_voter_stake_t * remove = fd_voter_stake_map_ele_remove( epoch_stakes->voter_stake_map, &voter_stake->key, NULL, epoch_stakes->voter_stake_pool ); 75 0 : if( FD_UNLIKELY( !remove ) ) FD_LOG_CRIT(( "invariant violation: voter stake does not exist in map" )); 76 0 : fd_voter_stake_pool_ele_release( epoch_stakes->voter_stake_pool, voter_stake ); 77 0 : } 78 0 : fd_epoch_stakes_slot_map_remove( epoch_stakes->slot_stakes_map, slot ); 79 0 : }