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