Skip to content

Commit 3e52aa0

Browse files
committed
fix: correct is_in_next_prepare_phase
1 parent 40b1603 commit 3e52aa0

File tree

1 file changed

+69
-4
lines changed

1 file changed

+69
-4
lines changed

stacks-signer/src/runloop.rs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,11 @@ impl RewardCycleInfo {
9292

9393
/// Check if the provided burnchain block height is in the prepare phase of the next cycle
9494
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;
9697

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
99100
}
100101
}
101102

@@ -267,7 +268,8 @@ impl RunLoop {
267268
let current_reward_cycle = reward_cycle_info.reward_cycle;
268269
self.refresh_signer_config(current_reward_cycle);
269270
// 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+
{
271273
self.refresh_signer_config(current_reward_cycle.saturating_add(1));
272274
}
273275
self.current_reward_cycle_info = Some(reward_cycle_info);
@@ -560,4 +562,67 @@ mod tests {
560562
.wrapping_add(1)
561563
));
562564
}
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+
}
563628
}

0 commit comments

Comments
 (0)