@@ -142,6 +142,31 @@ impl ForkProgress {
142142        } 
143143    } 
144144
145+     fn  calculate_alpenglow_ticks ( 
146+         slot :  Slot , 
147+         first_alpenglow_slot :  Slot , 
148+         parent_slot :  Slot , 
149+         ticks_per_slot :  u64 , 
150+     )  -> Option < u64 >  { 
151+         // Slots before alpenglow shouldn't have alpenglow ticks 
152+         if  slot < first_alpenglow_slot { 
153+             return  None ; 
154+         } 
155+ 
156+         let  alpenglow_ticks = if  parent_slot < first_alpenglow_slot && slot >= first_alpenglow_slot
157+         { 
158+             // 1. All slots between the parent and the first alpenglow slot need to 
159+             // have `ticks_per_slot` ticks 
160+             // 2. One extra tick for the actual alpenglow slot 
161+             // 3. There are no ticks for any skipped alpenglow slots 
162+             ( first_alpenglow_slot - parent_slot - 1 )  *  ticks_per_slot + 1 
163+         }  else  { 
164+             1 
165+         } ; 
166+ 
167+         Some ( alpenglow_ticks) 
168+     } 
169+ 
145170    pub  fn  new_from_bank ( 
146171        bank :  & Bank , 
147172        validator_identity :  & Pubkey , 
@@ -170,6 +195,20 @@ impl ForkProgress {
170195            num_dropped_blocks_on_fork, 
171196        ) ; 
172197
198+         if  let  Some ( first_alpenglow_slot)  = bank
199+             . feature_set 
200+             . activated_slot ( & solana_feature_set:: secp256k1_program_enabled:: id ( ) ) 
201+         { 
202+             if  let  Some ( num_expected_ticks)  = Self :: calculate_alpenglow_ticks ( 
203+                 bank. slot ( ) , 
204+                 first_alpenglow_slot, 
205+                 bank. parent_slot ( ) , 
206+                 bank. ticks_per_slot ( ) , 
207+             )  { 
208+                 bank. set_tick_height ( bank. max_tick_height ( )  - num_expected_ticks) ; 
209+             } 
210+         } 
211+ 
173212        if  bank. is_frozen ( )  { 
174213            new_progress. fork_stats . bank_hash  = Some ( bank. hash ( ) ) ; 
175214        } 
@@ -613,4 +652,83 @@ mod test {
613652            . is_leader_slot  = true ; 
614653        assert ! ( !progress_map. get_leader_propagation_slot_must_exist( 10 ) . 0 ) ; 
615654    } 
655+ 
656+     #[ test]  
657+     fn  test_calculate_alpenglow_ticks ( )  { 
658+         let  first_alpenglow_slot = 10 ; 
659+         let  ticks_per_slot = 2 ; 
660+ 
661+         // Slots before alpenglow don't have alpenglow ticks 
662+         let  slot = 9 ; 
663+         let  parent_slot = 8 ; 
664+         assert ! ( ForkProgress :: calculate_alpenglow_ticks( 
665+             slot, 
666+             first_alpenglow_slot, 
667+             parent_slot, 
668+             ticks_per_slot
669+         ) 
670+         . is_none( ) ) ; 
671+ 
672+         // First alpenglow slot should only have 1 tick 
673+         let  slot = first_alpenglow_slot; 
674+         let  parent_slot = first_alpenglow_slot - 1 ; 
675+         assert_eq ! ( 
676+             ForkProgress :: calculate_alpenglow_ticks( 
677+                 slot, 
678+                 first_alpenglow_slot, 
679+                 parent_slot, 
680+                 ticks_per_slot
681+             ) 
682+             . unwrap( ) , 
683+             1 
684+         ) ; 
685+ 
686+         // First alpenglow slot with skipped non-alpenglow slots 
687+         // need to have `ticks_per_slot` ticks per skipped slot and 
688+         // then one additional tick for the first alpenglow slot 
689+         let  slot = first_alpenglow_slot; 
690+         let  num_skipped_slots = 3 ; 
691+         let  parent_slot = first_alpenglow_slot - num_skipped_slots - 1 ; 
692+         assert_eq ! ( 
693+             ForkProgress :: calculate_alpenglow_ticks( 
694+                 slot, 
695+                 first_alpenglow_slot, 
696+                 parent_slot, 
697+                 ticks_per_slot
698+             ) 
699+             . unwrap( ) , 
700+             num_skipped_slots *  ticks_per_slot + 1 
701+         ) ; 
702+ 
703+         // Skipped alpenglow slots don't need any additional ticks 
704+         let  slot = first_alpenglow_slot + 2 ; 
705+         let  parent_slot = first_alpenglow_slot; 
706+         assert_eq ! ( 
707+             ForkProgress :: calculate_alpenglow_ticks( 
708+                 slot, 
709+                 first_alpenglow_slot, 
710+                 parent_slot, 
711+                 ticks_per_slot
712+             ) 
713+             . unwrap( ) , 
714+             1 
715+         ) ; 
716+ 
717+         // Skipped alpenglow slots along skipped non-alpenglow slots 
718+         // need to have `ticks_per_slot` ticks per skipped non-alpenglow 
719+         // slot only and then one additional tick for the alpenglow slot 
720+         let  slot = first_alpenglow_slot + 2 ; 
721+         let  num_skipped_non_alpenglow_slots = 4 ; 
722+         let  parent_slot = first_alpenglow_slot - num_skipped_non_alpenglow_slots - 1 ; 
723+         assert_eq ! ( 
724+             ForkProgress :: calculate_alpenglow_ticks( 
725+                 slot, 
726+                 first_alpenglow_slot, 
727+                 parent_slot, 
728+                 ticks_per_slot
729+             ) 
730+             . unwrap( ) , 
731+             num_skipped_non_alpenglow_slots *  ticks_per_slot + 1 
732+         ) ; 
733+     } 
616734} 
0 commit comments