@@ -92,10 +92,11 @@ impl RewardCycleInfo {
92
92
93
93
/// Check if the provided burnchain block height is in the prepare phase of the next cycle
94
94
pub fn is_in_next_prepare_phase ( & self , burnchain_block_height : u64 ) -> bool {
95
- let next_reward_cycle = self . reward_cycle . saturating_add ( 1 ) ;
95
+ let effective_height = burnchain_block_height - self . first_burnchain_block_height ;
96
+ let reward_index = effective_height % self . reward_cycle_length ;
96
97
97
- self . is_in_prepare_phase ( burnchain_block_height )
98
- && self . get_reward_cycle ( burnchain_block_height) == next_reward_cycle
98
+ reward_index >= u64 :: from ( self . reward_cycle_length - self . prepare_phase_block_length )
99
+ && self . get_reward_cycle ( burnchain_block_height) == self . reward_cycle
99
100
}
100
101
}
101
102
@@ -267,7 +268,8 @@ impl RunLoop {
267
268
let current_reward_cycle = reward_cycle_info. reward_cycle ;
268
269
self . refresh_signer_config ( current_reward_cycle) ;
269
270
// We should only attempt to initialize the next reward cycle signer if we are in the prepare phase of the next reward cycle
270
- if reward_cycle_info. is_in_prepare_phase ( reward_cycle_info. last_burnchain_block_height ) {
271
+ if reward_cycle_info. is_in_next_prepare_phase ( reward_cycle_info. last_burnchain_block_height )
272
+ {
271
273
self . refresh_signer_config ( current_reward_cycle. saturating_add ( 1 ) ) ;
272
274
}
273
275
self . current_reward_cycle_info = Some ( reward_cycle_info) ;
@@ -560,4 +562,67 @@ mod tests {
560
562
. wrapping_add( 1 )
561
563
) ) ;
562
564
}
565
+
566
+ #[ test]
567
+ fn is_in_next_prepare_phase ( ) {
568
+ let reward_cycle_info = RewardCycleInfo {
569
+ reward_cycle : 5 ,
570
+ reward_cycle_length : 10 ,
571
+ prepare_phase_block_length : 5 ,
572
+ first_burnchain_block_height : 0 ,
573
+ last_burnchain_block_height : 50 ,
574
+ } ;
575
+
576
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 49 ) ) ;
577
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 50 ) ) ;
578
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 51 ) ) ;
579
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 52 ) ) ;
580
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 53 ) ) ;
581
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 54 ) ) ;
582
+ assert ! ( reward_cycle_info. is_in_next_prepare_phase( 55 ) ) ;
583
+ assert ! ( reward_cycle_info. is_in_next_prepare_phase( 56 ) ) ;
584
+ assert ! ( reward_cycle_info. is_in_next_prepare_phase( 57 ) ) ;
585
+ assert ! ( reward_cycle_info. is_in_next_prepare_phase( 58 ) ) ;
586
+ assert ! ( reward_cycle_info. is_in_next_prepare_phase( 59 ) ) ;
587
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 60 ) ) ;
588
+ assert ! ( !reward_cycle_info. is_in_next_prepare_phase( 61 ) ) ;
589
+
590
+ let rand_byte: u8 = std:: cmp:: max ( 1 , thread_rng ( ) . gen ( ) ) ;
591
+ let prepare_phase_block_length = rand_byte as u64 ;
592
+ // Ensure the reward cycle is not close to u64 Max to prevent overflow when adding prepare phase len
593
+ let reward_cycle_length = ( std:: cmp:: max (
594
+ prepare_phase_block_length. wrapping_add ( 1 ) ,
595
+ thread_rng ( ) . next_u32 ( ) as u64 ,
596
+ ) )
597
+ . wrapping_add ( prepare_phase_block_length) ;
598
+ let reward_cycle_phase_block_length =
599
+ reward_cycle_length. wrapping_sub ( prepare_phase_block_length) ;
600
+ let first_burnchain_block_height = std:: cmp:: max ( 1u8 , thread_rng ( ) . gen ( ) ) as u64 ;
601
+ let last_burnchain_block_height = thread_rng ( ) . gen_range (
602
+ first_burnchain_block_height
603
+ ..first_burnchain_block_height
604
+ . wrapping_add ( reward_cycle_length)
605
+ . wrapping_sub ( prepare_phase_block_length) ,
606
+ ) ;
607
+ let blocks_mined = last_burnchain_block_height. wrapping_sub ( first_burnchain_block_height) ;
608
+ let reward_cycle = blocks_mined / reward_cycle_length;
609
+
610
+ let reward_cycle_info = RewardCycleInfo {
611
+ reward_cycle,
612
+ reward_cycle_length,
613
+ prepare_phase_block_length,
614
+ first_burnchain_block_height,
615
+ last_burnchain_block_height,
616
+ } ;
617
+
618
+ for i in 0 ..reward_cycle_length {
619
+ if i < reward_cycle_phase_block_length {
620
+ assert ! ( !reward_cycle_info
621
+ . is_in_next_prepare_phase( first_burnchain_block_height. wrapping_add( i) ) ) ;
622
+ } else {
623
+ assert ! ( reward_cycle_info
624
+ . is_in_next_prepare_phase( first_burnchain_block_height. wrapping_add( i) ) ) ;
625
+ }
626
+ }
627
+ }
563
628
}
0 commit comments