Line data Source code
1 : #include "fd_epoch.h" 2 : 3 : void * 4 0 : fd_epoch_new( void * shmem, ulong voter_max ) { 5 0 : if( FD_UNLIKELY( !shmem ) ) { 6 0 : FD_LOG_WARNING(( "NULL mem" )); 7 0 : return NULL; 8 0 : } 9 : 10 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_epoch_align() ) ) ) { 11 0 : FD_LOG_WARNING(( "misaligned mem" )); 12 0 : return NULL; 13 0 : } 14 : 15 0 : ulong footprint = fd_epoch_footprint( voter_max ); 16 0 : if( FD_UNLIKELY( !footprint ) ) { 17 0 : FD_LOG_WARNING(( "bad mem" )); 18 0 : return NULL; 19 0 : } 20 : 21 0 : fd_wksp_t * wksp = fd_wksp_containing( shmem ); 22 0 : if( FD_UNLIKELY( !wksp ) ) { 23 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" )); 24 0 : return NULL; 25 0 : } 26 : 27 0 : fd_memset( shmem, 0, footprint ); 28 0 : int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( voter_max ) ) + 2; /* fill ratio <= 0.25 */ 29 : 30 0 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 31 0 : fd_epoch_t * epoch = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_align(), sizeof(fd_epoch_t) ); 32 0 : void * epoch_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_voters_align(), fd_epoch_voters_footprint( lg_slot_cnt ) ); 33 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_epoch_align() ) == (ulong)shmem + footprint ); 34 : 35 0 : epoch->voters_gaddr = fd_wksp_gaddr_fast( wksp, fd_epoch_voters_join( fd_epoch_voters_new( epoch_voters, lg_slot_cnt ) ) ); 36 : 37 0 : epoch->epoch_gaddr = fd_wksp_gaddr_fast( wksp, epoch ); 38 0 : epoch->total_stake = 0UL; 39 0 : epoch->first_slot = FD_SLOT_NULL; 40 0 : epoch->last_slot = FD_SLOT_NULL; 41 : 42 0 : FD_COMPILER_MFENCE(); 43 0 : FD_VOLATILE( epoch->magic ) = FD_EPOCH_MAGIC; 44 0 : FD_COMPILER_MFENCE(); 45 : 46 0 : return shmem; 47 0 : } 48 : 49 : fd_epoch_t * 50 0 : fd_epoch_join( void * shepoch ) { 51 0 : fd_epoch_t * epoch = (fd_epoch_t *)shepoch; 52 : 53 0 : if( FD_UNLIKELY( !epoch ) ) { 54 0 : FD_LOG_WARNING(( "NULL epoch" )); 55 0 : return NULL; 56 0 : } 57 : 58 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)epoch, fd_epoch_align() ) ) ) { 59 0 : FD_LOG_WARNING(( "misaligned epoch" )); 60 0 : return NULL; 61 0 : } 62 : 63 0 : fd_wksp_t * wksp = fd_wksp_containing( epoch ); 64 0 : if( FD_UNLIKELY( !wksp ) ) { 65 0 : FD_LOG_WARNING(( "epoch must be part of a workspace" )); 66 0 : return NULL; 67 0 : } 68 : 69 0 : if( FD_UNLIKELY( epoch->magic!=FD_EPOCH_MAGIC ) ) { 70 0 : FD_LOG_WARNING(( "bad magic" )); 71 0 : return NULL; 72 0 : } 73 : 74 0 : return epoch; 75 0 : } 76 : 77 : void * 78 0 : fd_epoch_leave( fd_epoch_t const * epoch ) { 79 : 80 0 : if( FD_UNLIKELY( !epoch ) ) { 81 0 : FD_LOG_WARNING(( "NULL epoch" )); 82 0 : return NULL; 83 0 : } 84 : 85 0 : return (void *)epoch; 86 0 : } 87 : 88 : void * 89 0 : fd_epoch_delete( void * epoch ) { 90 : 91 0 : if( FD_UNLIKELY( !epoch ) ) { 92 0 : FD_LOG_WARNING(( "NULL epoch" )); 93 0 : return NULL; 94 0 : } 95 : 96 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)epoch, fd_epoch_align() ) ) ) { 97 0 : FD_LOG_WARNING(( "misaligned epoch" )); 98 0 : return NULL; 99 0 : } 100 : 101 0 : return epoch; 102 0 : } 103 : 104 : void 105 : fd_epoch_init( fd_epoch_t * epoch, 106 : ulong eah_start_slot, 107 : ulong eah_stop_slot, 108 0 : fd_vote_accounts_global_t const * vote_accounts ) { 109 : 110 0 : epoch->first_slot = eah_start_slot; 111 0 : epoch->last_slot = eah_stop_slot; 112 : 113 0 : fd_voter_t * epoch_voters = fd_epoch_voters( epoch ); 114 : 115 0 : fd_vote_accounts_pair_global_t_mapnode_t * vote_accounts_pool = fd_vote_accounts_vote_accounts_pool_join( vote_accounts ); 116 0 : fd_vote_accounts_pair_global_t_mapnode_t * vote_accounts_root = fd_vote_accounts_vote_accounts_root_join( vote_accounts ); 117 : 118 0 : for( fd_vote_accounts_pair_global_t_mapnode_t * curr = fd_vote_accounts_pair_global_t_map_minimum( 119 0 : vote_accounts_pool, 120 0 : vote_accounts_root ); 121 0 : curr; 122 0 : curr = fd_vote_accounts_pair_global_t_map_successor( vote_accounts_pool, curr ) ) { 123 : 124 0 : if( FD_UNLIKELY( curr->elem.stake > 0UL ) ) { 125 : 126 0 : #if FD_EPOCH_USE_HANDHOLDING 127 0 : FD_TEST( !fd_epoch_voters_query( epoch_voters, curr->elem.key, NULL ) ); 128 0 : FD_TEST( fd_epoch_voters_key_cnt( epoch_voters ) < fd_epoch_voters_key_max( epoch_voters ) ); 129 0 : #endif 130 : 131 0 : fd_voter_t * voter = fd_epoch_voters_insert( epoch_voters, curr->elem.key ); 132 0 : voter->rec.uc[FD_FUNK_REC_KEY_FOOTPRINT - 1] = FD_FUNK_KEY_TYPE_ACC; 133 : 134 0 : #if FD_EPOCH_USE_HANDHOLDING 135 0 : FD_TEST( 0 == memcmp( &voter->key, &curr->elem.key, sizeof(fd_pubkey_t) ) ); 136 0 : FD_TEST( fd_epoch_voters_query( epoch_voters, voter->key, NULL ) ); 137 0 : #endif 138 : 139 0 : voter->stake = curr->elem.stake; 140 : 141 0 : voter->replay_vote = FD_SLOT_NULL; 142 0 : voter->gossip_vote = FD_SLOT_NULL; 143 0 : voter->rooted_vote = FD_SLOT_NULL; 144 0 : } 145 0 : epoch->total_stake += curr->elem.stake; 146 0 : } 147 0 : } 148 : 149 : void 150 0 : fd_epoch_fini( fd_epoch_t * epoch ) { 151 0 : fd_epoch_voters_clear( fd_epoch_voters( epoch ) ); 152 0 : epoch->total_stake = 0UL; 153 0 : }