Skip to content

Commit 381398d

Browse files
Move asserts about nakamoto boot state to a helper function that can be called elsewhere
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 3ea9d35 commit 381398d

File tree

4 files changed

+72
-32
lines changed

4 files changed

+72
-32
lines changed

stackslib/src/chainstate/tests/consensus.rs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -399,38 +399,6 @@ impl ConsensusChain<'_> {
399399
});
400400
current_height = end_height;
401401
}
402-
// Validate Epoch 2.5 and 3.0 constraints
403-
if let Some(epoch_3_0) = epochs.iter().find(|e| e.epoch_id == StacksEpochId::Epoch30) {
404-
let epoch_2_5 = epochs
405-
.iter()
406-
.find(|e| e.epoch_id == StacksEpochId::Epoch25)
407-
.expect("Epoch 2.5 not found");
408-
let epoch_2_5_start = epoch_2_5.start_height;
409-
let epoch_3_0_start = epoch_3_0.start_height;
410-
let epoch_2_5_end = epoch_2_5.end_height;
411-
412-
let epoch_2_5_reward_cycle = epoch_2_5_start / reward_cycle_length;
413-
let epoch_3_0_reward_cycle = epoch_3_0_start / reward_cycle_length;
414-
let prior_cycle = epoch_3_0_reward_cycle.saturating_sub(1);
415-
let epoch_3_0_prepare_phase =
416-
prior_cycle * reward_cycle_length + (reward_cycle_length - prepare_length);
417-
assert!(
418-
epoch_2_5_start < epoch_3_0_prepare_phase,
419-
"Epoch 2.5 must start before the prepare phase of the cycle prior to Epoch 3.0. (Epoch 2.5 activation height: {epoch_2_5_start}. Epoch 3.0 prepare phase start: {epoch_3_0_prepare_phase})"
420-
);
421-
assert_eq!(
422-
epoch_2_5_end, epoch_3_0.start_height,
423-
"Epoch 2.5 end must equal Epoch 3.0 start (epoch_2_5_end: {epoch_2_5_end}, epoch_3_0_start: {epoch_3_0_start})"
424-
);
425-
assert_ne!(
426-
epoch_2_5_reward_cycle, epoch_3_0_reward_cycle,
427-
"Epoch 2.5 and Epoch 3.0 must not be in the same reward cycle (epoch_2_5_reward_cycle: {epoch_2_5_reward_cycle}, epoch_3_0_reward_cycle: {epoch_3_0_reward_cycle})"
428-
);
429-
assert!(
430-
!is_reward_cycle_boundary(epoch_3_0_start, reward_cycle_length),
431-
"Epoch 3.0 must not start at a reward cycle boundary (epoch_3_0_start: {epoch_3_0_start})"
432-
);
433-
}
434402
// Validate test vector block counts
435403
for (epoch_id, num_blocks) in num_blocks_per_epoch {
436404
let epoch = epochs

stackslib/src/config/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,16 @@ impl Config {
684684
"FATAL: v1 unlock height is at a reward cycle boundary\nburnchain: {burnchain:?}"
685685
);
686686
}
687+
if epochs
688+
.iter()
689+
.any(|epoch| epoch.epoch_id == StacksEpochId::Epoch30)
690+
{
691+
StacksEpoch::assert_valid_epoch_3_0_activation(
692+
epochs,
693+
burnchain.pox_constants.reward_cycle_length as u64,
694+
burnchain.pox_constants.prepare_length as u64,
695+
);
696+
}
687697
}
688698

689699
// TODO: add tests from mutation testing results #4866

stackslib/src/core/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,12 @@ pub trait StacksEpochExtension {
883883
bitcoin_network: BitcoinNetworkType,
884884
configured_epochs: Option<&EpochList>,
885885
) -> EpochList;
886+
/// Assert that the epochs list will satisfy the Epoch 3.0 activation requirements given the reward cycle length and prepare phase length
887+
fn assert_valid_epoch_3_0_activation(
888+
epochs: &[StacksEpoch],
889+
reward_cycle_length: u64,
890+
prepare_length: u64,
891+
);
886892
}
887893

888894
impl StacksEpochExtension for StacksEpoch {
@@ -2347,6 +2353,48 @@ impl StacksEpochExtension for StacksEpoch {
23472353
}
23482354

23492355
assert_eq!(epoch_end_height, STACKS_EPOCH_MAX);
2356+
23502357
EpochList::new(&epochs)
23512358
}
2359+
2360+
fn assert_valid_epoch_3_0_activation(
2361+
epochs: &[StacksEpoch],
2362+
reward_cycle_length: u64,
2363+
prepare_length: u64,
2364+
) {
2365+
// Validate Epoch 2.5 and 3.0 constraints
2366+
let epoch_3_0 = epochs
2367+
.iter()
2368+
.find(|e| e.epoch_id == StacksEpochId::Epoch30)
2369+
.expect("Cannot activate Epoch 3.0 without specifying its activation height");
2370+
let epoch_2_5 = epochs
2371+
.iter()
2372+
.find(|e| e.epoch_id == StacksEpochId::Epoch25)
2373+
.expect("Epoch 2.5 not found");
2374+
let epoch_2_5_start = epoch_2_5.start_height;
2375+
let epoch_3_0_start = epoch_3_0.start_height;
2376+
let epoch_2_5_end = epoch_2_5.end_height;
2377+
2378+
let epoch_2_5_reward_cycle = epoch_2_5_start / reward_cycle_length;
2379+
let epoch_3_0_reward_cycle = epoch_3_0_start / reward_cycle_length;
2380+
let prior_cycle = epoch_3_0_reward_cycle.saturating_sub(1);
2381+
let epoch_3_0_prepare_phase =
2382+
prior_cycle * reward_cycle_length + (reward_cycle_length - prepare_length);
2383+
assert!(
2384+
epoch_2_5_start < epoch_3_0_prepare_phase,
2385+
"Epoch 2.5 must start before the prepare phase of the cycle prior to Epoch 3.0. (Epoch 2.5 activation height: {epoch_2_5_start}. Epoch 3.0 prepare phase start: {epoch_3_0_prepare_phase})"
2386+
);
2387+
assert_eq!(
2388+
epoch_2_5_end, epoch_3_0.start_height,
2389+
"Epoch 2.5 end must equal Epoch 3.0 start (epoch_2_5_end: {epoch_2_5_end}, epoch_3_0_start: {epoch_3_0_start})"
2390+
);
2391+
assert_ne!(
2392+
epoch_2_5_reward_cycle, epoch_3_0_reward_cycle,
2393+
"Epoch 2.5 and Epoch 3.0 must not be in the same reward cycle (epoch_2_5_reward_cycle: {epoch_2_5_reward_cycle}, epoch_3_0_reward_cycle: {epoch_3_0_reward_cycle})"
2394+
);
2395+
assert!(
2396+
epoch_3_0_start % reward_cycle_length > 1,
2397+
"Epoch 3.0 must not start at a reward cycle boundary (epoch_3_0_start: {epoch_3_0_start})"
2398+
);
2399+
}
23522400
}

stackslib/src/net/tests/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,13 @@ impl NakamotoBootPlan {
437437
if let Some(current_block) = current_block {
438438
chainstate_config.current_block = current_block;
439439
}
440+
if let Some(epochs) = self.epochs.as_ref() {
441+
StacksEpoch::assert_valid_epoch_3_0_activation(
442+
epochs,
443+
self.pox_constants.reward_cycle_length as u64,
444+
self.pox_constants.prepare_length as u64,
445+
);
446+
}
440447
let mut chain = TestChainstate::new_with_observer(chainstate_config, observer);
441448
chain.mine_malleablized_blocks = self.malleablized_blocks;
442449
chain
@@ -449,6 +456,13 @@ impl NakamotoBootPlan {
449456
self,
450457
observer: Option<&TestEventObserver>,
451458
) -> (TestPeer<'_>, Vec<TestPeer<'_>>) {
459+
if let Some(epochs) = self.epochs.as_ref() {
460+
StacksEpoch::assert_valid_epoch_3_0_activation(
461+
epochs,
462+
self.pox_constants.reward_cycle_length as u64,
463+
self.pox_constants.prepare_length as u64,
464+
);
465+
}
452466
let mut peer_config = TestPeerConfig::new(&self.test_name, 0, 0);
453467
peer_config.chain_config = self.build_nakamoto_chainstate_config();
454468
peer_config.private_key = self.private_key.clone();

0 commit comments

Comments
 (0)