Line data Source code
1 : #include "fd_sysvar_epoch_schedule.h" 2 : #include "fd_sysvar.h" 3 : #include "../fd_system_ids.h" 4 : 5 : fd_epoch_schedule_t * 6 : fd_epoch_schedule_derive( fd_epoch_schedule_t * schedule, 7 : ulong epoch_len, 8 : ulong leader_schedule_slot_offset, 9 12267 : int warmup ) { 10 : 11 12267 : if( FD_UNLIKELY( epoch_len < FD_EPOCH_LEN_MIN ) ) { 12 6 : FD_LOG_WARNING(( "epoch_len too small" )); 13 6 : return NULL; 14 6 : } 15 : 16 12261 : *schedule = (fd_epoch_schedule_t) { 17 12261 : .slots_per_epoch = epoch_len, 18 12261 : .leader_schedule_slot_offset = leader_schedule_slot_offset, 19 12261 : .warmup = !!warmup 20 12261 : }; 21 : 22 12261 : if( warmup ) { 23 6081 : ulong ceil_log2_epoch = (ulong)fd_ulong_find_msb( epoch_len-1UL ) + 1UL; 24 : 25 6081 : if( FD_UNLIKELY( ceil_log2_epoch>=64UL ) ) { 26 3 : FD_LOG_WARNING(( "epoch_len too large (ceil_log2_epoch %lu)", ceil_log2_epoch )); 27 3 : return NULL; 28 3 : } 29 : 30 6078 : ulong ceil_log2_len_min = (ulong)fd_ulong_find_msb( FD_EPOCH_LEN_MIN ); 31 : 32 6078 : schedule->first_normal_epoch = fd_ulong_sat_sub( ceil_log2_epoch, ceil_log2_len_min ); 33 6078 : schedule->first_normal_slot = (1UL << ceil_log2_epoch) - FD_EPOCH_LEN_MIN; 34 6078 : } 35 : 36 12258 : return schedule; 37 12261 : } 38 : 39 : void 40 : fd_sysvar_epoch_schedule_write( fd_bank_t * bank, 41 : fd_accdb_t * accdb, 42 : fd_capture_ctx_t * capture_ctx, 43 9 : fd_epoch_schedule_t const * epoch_schedule ) { 44 9 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_epoch_schedule_id, epoch_schedule, sizeof(fd_epoch_schedule_t) ); 45 9 : } 46 : 47 : void 48 : fd_sysvar_epoch_schedule_init( fd_bank_t * bank, 49 : fd_accdb_t * accdb, 50 0 : fd_capture_ctx_t * capture_ctx ) { 51 0 : fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule; 52 0 : fd_sysvar_epoch_schedule_write( bank, accdb, capture_ctx, epoch_schedule ); 53 0 : } 54 : 55 : /* https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/sdk/program/src/epoch_schedule.rs#L105 */ 56 : 57 : ulong 58 : fd_epoch_slot_cnt( fd_epoch_schedule_t const * schedule, 59 252 : ulong epoch ) { 60 252 : if( FD_UNLIKELY( epoch < schedule->first_normal_epoch ) ) { 61 63 : ulong exp = fd_ulong_sat_add( epoch, (ulong)fd_ulong_find_lsb( FD_EPOCH_LEN_MIN ) ); 62 63 : return ( exp<64UL ? 1UL<<exp : ULONG_MAX ); // saturating_pow 63 63 : } 64 : 65 189 : return schedule->slots_per_epoch; 66 252 : } 67 : 68 : /* https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/sdk/program/src/epoch_schedule.rs#L170 */ 69 : 70 : ulong 71 : fd_epoch_slot0( fd_epoch_schedule_t const * schedule, 72 9252 : ulong epoch ) { 73 9252 : if( FD_UNLIKELY( epoch <= schedule->first_normal_epoch ) ) { 74 7809 : ulong power = fd_ulong_if( epoch<64UL, 1UL<<epoch, ULONG_MAX ); 75 7809 : return fd_ulong_sat_mul( power-1UL, FD_EPOCH_LEN_MIN ); 76 7809 : } 77 : 78 1443 : return fd_ulong_sat_add( 79 1443 : fd_ulong_sat_mul( 80 1443 : fd_ulong_sat_sub( 81 1443 : epoch, 82 1443 : schedule->first_normal_epoch), 83 1443 : schedule->slots_per_epoch), 84 1443 : schedule->first_normal_slot); 85 9252 : } 86 : 87 : /* https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/sdk/program/src/epoch_schedule.rs#L140 */ 88 : 89 : ulong 90 : fd_slot_to_epoch( fd_epoch_schedule_t const * schedule, 91 : ulong slot, 92 1355472 : ulong * out_offset_opt ) { 93 1355472 : ulong epoch; 94 1355472 : ulong offset; 95 : 96 1355472 : if( FD_UNLIKELY( slot < schedule->first_normal_slot ) ) { 97 : /* step0 = ceil(log2(FD_EPOCH_LEN_MIN)) 98 : step1 = ceil(log2(FD_EPOCH_LEN_MIN + slot + 1)) 99 : epoch = step1 - step0 - 1 */ 100 : 101 23727 : ulong s0 = FD_EPOCH_LEN_MIN + slot + 1UL; 102 : /* Invariant: s0 > 1UL */ 103 : /* Invariant: s0 > FD_EPOCH_LEN_MIN */ 104 : 105 : /* Find lowest exp where (2^exp) >= s0 106 : (Only valid for s0 > 1UL and FD_EPOCH_LEN_MIN > 1UL) */ 107 23727 : int exp = fd_ulong_find_msb( s0-1UL ) + 1; 108 23727 : int min_exp = fd_ulong_find_msb( FD_EPOCH_LEN_MIN ); 109 23727 : epoch = (ulong)( exp - min_exp - 1 ); 110 23727 : ulong epoch_len = 1UL<<( epoch + (ulong)fd_uint_find_lsb( FD_EPOCH_LEN_MIN ) ); 111 23727 : offset = slot - ( epoch_len - FD_EPOCH_LEN_MIN ); 112 1331745 : } else { 113 1331745 : if( FD_UNLIKELY( schedule->slots_per_epoch == 0UL ) ) { 114 12 : FD_LOG_WARNING(( "zero slots_per_epoch returning first_normal_epoch %lu", schedule->first_normal_epoch )); 115 12 : if( out_offset_opt ) *out_offset_opt = 0UL; 116 12 : return schedule->first_normal_epoch; 117 12 : } 118 1331733 : ulong n_slot = slot - schedule->first_normal_slot; 119 1331733 : ulong n_epoch = n_slot / schedule->slots_per_epoch; 120 1331733 : epoch = schedule->first_normal_epoch + n_epoch; 121 1331733 : offset = n_slot % schedule->slots_per_epoch; 122 1331733 : } 123 : 124 1355460 : ulong dummy_out; 125 1355460 : ulong * out_offset = out_offset_opt ? out_offset_opt : &dummy_out; 126 : 127 1355460 : *out_offset = offset; 128 1355460 : return epoch; 129 1355472 : } 130 : 131 : /* https://docs.rs/solana-epoch-schedule/2.2.1/src/solana_epoch_schedule/lib.rs.html#136-151 */ 132 : 133 : ulong 134 : fd_slot_to_leader_schedule_epoch( fd_epoch_schedule_t const * schedule, 135 4176 : ulong slot ) { 136 : 137 4176 : if( FD_UNLIKELY( slot<schedule->first_normal_slot ) ) { 138 3 : return fd_slot_to_epoch( schedule, slot, NULL ) + 1UL; 139 3 : } 140 : 141 4173 : if( FD_UNLIKELY( schedule->slots_per_epoch == 0UL ) ) { 142 12 : FD_LOG_WARNING(( "zero slots_per_epoch returning first_normal_epoch %lu", schedule->first_normal_epoch )); 143 12 : return schedule->first_normal_epoch; 144 12 : } 145 : 146 4161 : ulong new_slots_since_first_normal_slot = 147 4161 : slot - schedule->first_normal_slot; 148 4161 : ulong new_first_normal_leader_schedule_slot = 149 4161 : new_slots_since_first_normal_slot + schedule->leader_schedule_slot_offset; 150 4161 : ulong new_epochs_since_first_normal_leader_schedule = 151 4161 : new_first_normal_leader_schedule_slot / schedule->slots_per_epoch; 152 : 153 4161 : return schedule->first_normal_epoch + new_epochs_since_first_normal_leader_schedule; 154 4173 : }