Skip to content

Commit ebc8fb0

Browse files
Merge pull request #6619 from jacinta-stacks/feat/expand-consensus-test-to-support-pre-nakamoto-epochs
Support abritrary epochs in TestChainstate
2 parents dc555b4 + 8c55ee7 commit ebc8fb0

17 files changed

+2718
-1272
lines changed

stacks-common/src/types/mod.rs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ use crate::address::{
2929
C32_ADDRESS_VERSION_MAINNET_MULTISIG, C32_ADDRESS_VERSION_MAINNET_SINGLESIG,
3030
C32_ADDRESS_VERSION_TESTNET_MULTISIG, C32_ADDRESS_VERSION_TESTNET_SINGLESIG,
3131
};
32-
use crate::consts::MICROSTACKS_PER_STACKS;
32+
use crate::consts::{
33+
MICROSTACKS_PER_STACKS, PEER_VERSION_EPOCH_1_0, PEER_VERSION_EPOCH_2_0,
34+
PEER_VERSION_EPOCH_2_05, PEER_VERSION_EPOCH_2_1, PEER_VERSION_EPOCH_2_2,
35+
PEER_VERSION_EPOCH_2_3, PEER_VERSION_EPOCH_2_4, PEER_VERSION_EPOCH_2_5, PEER_VERSION_EPOCH_3_0,
36+
PEER_VERSION_EPOCH_3_1, PEER_VERSION_EPOCH_3_2, PEER_VERSION_EPOCH_3_3,
37+
};
3338
use crate::types::chainstate::{StacksAddress, StacksPublicKey};
3439
use crate::util::hash::Hash160;
3540
use crate::util::secp256k1::{MessageSignature, Secp256k1PublicKey};
@@ -96,9 +101,23 @@ pub const MINING_COMMITMENT_WINDOW: u8 = 6;
96101
// Only relevant for Nakamoto (epoch 3.x)
97102
pub const MINING_COMMITMENT_FREQUENCY_NAKAMOTO: u8 = 3;
98103

99-
#[repr(u32)]
100-
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Copy, Serialize, Deserialize)]
101-
pub enum StacksEpochId {
104+
macro_rules! define_stacks_epochs {
105+
($($variant:ident = $value:expr),* $(,)?) => {
106+
#[repr(u32)]
107+
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
108+
pub enum StacksEpochId {
109+
$($variant = $value),*
110+
}
111+
112+
impl StacksEpochId {
113+
pub const ALL: &'static [StacksEpochId] = &[
114+
$(StacksEpochId::$variant),*
115+
];
116+
}
117+
};
118+
}
119+
120+
define_stacks_epochs! {
102121
Epoch10 = 0x01000,
103122
Epoch20 = 0x02000,
104123
Epoch2_05 = 0x02005,
@@ -113,6 +132,26 @@ pub enum StacksEpochId {
113132
Epoch33 = 0x03003,
114133
}
115134

135+
impl StacksEpochId {
136+
/// Return the network epoch associated with the StacksEpochId
137+
pub fn network_epoch(epoch: StacksEpochId) -> u8 {
138+
match epoch {
139+
StacksEpochId::Epoch10 => PEER_VERSION_EPOCH_1_0,
140+
StacksEpochId::Epoch20 => PEER_VERSION_EPOCH_2_0,
141+
StacksEpochId::Epoch2_05 => PEER_VERSION_EPOCH_2_05,
142+
StacksEpochId::Epoch21 => PEER_VERSION_EPOCH_2_1,
143+
StacksEpochId::Epoch22 => PEER_VERSION_EPOCH_2_2,
144+
StacksEpochId::Epoch23 => PEER_VERSION_EPOCH_2_3,
145+
StacksEpochId::Epoch24 => PEER_VERSION_EPOCH_2_4,
146+
StacksEpochId::Epoch25 => PEER_VERSION_EPOCH_2_5,
147+
StacksEpochId::Epoch30 => PEER_VERSION_EPOCH_3_0,
148+
StacksEpochId::Epoch31 => PEER_VERSION_EPOCH_3_1,
149+
StacksEpochId::Epoch32 => PEER_VERSION_EPOCH_3_2,
150+
StacksEpochId::Epoch33 => PEER_VERSION_EPOCH_3_3,
151+
}
152+
}
153+
}
154+
116155
#[derive(Debug)]
117156
pub enum MempoolCollectionBehavior {
118157
ByStacksHeight,
@@ -448,13 +487,6 @@ impl StacksEpochId {
448487
StacksEpochId::Epoch33
449488
}
450489

451-
pub const ALL_GTE_30: &'static [StacksEpochId] = &[
452-
StacksEpochId::Epoch30,
453-
StacksEpochId::Epoch31,
454-
StacksEpochId::Epoch32,
455-
StacksEpochId::Epoch33,
456-
];
457-
458490
/// In this epoch, how should the mempool perform garbage collection?
459491
pub fn mempool_garbage_behavior(&self) -> MempoolCollectionBehavior {
460492
match self {

stacks-node/src/burnchains/bitcoin_regtest_controller.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3567,6 +3567,7 @@ mod tests {
35673567

35683568
let mut config = utils::create_miner_config();
35693569
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3570+
config.burnchain.pox_reward_length = Some(11);
35703571

35713572
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
35723573
btcd_controller
@@ -3626,6 +3627,7 @@ mod tests {
36263627

36273628
let mut config = utils::create_miner_config();
36283629
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3630+
config.burnchain.pox_reward_length = Some(11);
36293631

36303632
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
36313633
btcd_controller
@@ -3675,6 +3677,7 @@ mod tests {
36753677

36763678
let mut config = utils::create_miner_config();
36773679
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3680+
config.burnchain.pox_reward_length = Some(11);
36783681

36793682
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
36803683
btcd_controller
@@ -3726,6 +3729,7 @@ mod tests {
37263729

37273730
let mut config = utils::create_miner_config();
37283731
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3732+
config.burnchain.pox_reward_length = Some(11);
37293733

37303734
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
37313735
btcd_controller
@@ -3809,6 +3813,7 @@ mod tests {
38093813

38103814
let mut config = utils::create_miner_config();
38113815
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3816+
config.burnchain.pox_reward_length = Some(11);
38123817

38133818
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
38143819
btcd_controller
@@ -3882,6 +3887,7 @@ mod tests {
38823887

38833888
let mut config = utils::create_miner_config();
38843889
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3890+
config.burnchain.pox_reward_length = Some(11);
38853891

38863892
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
38873893
btcd_controller
@@ -3927,6 +3933,7 @@ mod tests {
39273933

39283934
let mut config = utils::create_miner_config();
39293935
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
3936+
config.burnchain.pox_reward_length = Some(11);
39303937

39313938
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
39323939
btcd_controller
@@ -4063,6 +4070,7 @@ mod tests {
40634070

40644071
let mut config = utils::create_miner_config();
40654072
config.burnchain.local_mining_public_key = Some(miner_pubkey.to_hex());
4073+
config.burnchain.pox_reward_length = Some(11);
40664074

40674075
let mut btcd_controller = BitcoinCoreController::from_stx_config(&config);
40684076
btcd_controller

stacks-node/src/tests/epoch_205.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use stacks::core::test_util::{
1818
};
1919
use stacks::core::{
2020
self, EpochList, StacksEpoch, StacksEpochId, PEER_VERSION_EPOCH_1_0, PEER_VERSION_EPOCH_2_0,
21-
PEER_VERSION_EPOCH_2_05, PEER_VERSION_EPOCH_2_1,
21+
PEER_VERSION_EPOCH_2_05, PEER_VERSION_EPOCH_2_1, STACKS_EPOCH_MAX,
2222
};
2323
use stacks_common::codec::StacksMessageCodec;
2424
use stacks_common::types::chainstate::{BlockHeaderHash, BurnchainHeaderHash, VRFSeed};
@@ -53,6 +53,8 @@ fn test_exact_block_costs() {
5353
let mut epochs = EpochList::new(&*core::STACKS_EPOCHS_REGTEST);
5454
epochs[StacksEpochId::Epoch20].end_height = epoch_205_transition_height;
5555
epochs[StacksEpochId::Epoch2_05].start_height = epoch_205_transition_height;
56+
epochs[StacksEpochId::Epoch2_05].end_height = STACKS_EPOCH_MAX;
57+
epochs.truncate_after(StacksEpochId::Epoch2_05);
5658

5759
conf.burnchain.epochs = Some(epochs);
5860
conf.node.mine_microblocks = true;
@@ -299,6 +301,8 @@ fn test_dynamic_db_method_costs() {
299301
let mut epochs = EpochList::new(&*core::STACKS_EPOCHS_REGTEST);
300302
epochs[StacksEpochId::Epoch20].end_height = epoch_205_transition_height;
301303
epochs[StacksEpochId::Epoch2_05].start_height = epoch_205_transition_height;
304+
epochs[StacksEpochId::Epoch2_05].end_height = STACKS_EPOCH_MAX;
305+
epochs.truncate_after(StacksEpochId::Epoch2_05);
302306

303307
conf.burnchain.epochs = Some(epochs);
304308

@@ -501,6 +505,8 @@ fn transition_empty_blocks() {
501505
let mut epochs = EpochList::new(&*core::STACKS_EPOCHS_REGTEST);
502506
epochs[StacksEpochId::Epoch20].end_height = epoch_2_05;
503507
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
508+
epochs[StacksEpochId::Epoch2_05].end_height = STACKS_EPOCH_MAX;
509+
epochs.truncate_after(StacksEpochId::Epoch2_05);
504510

505511
conf.burnchain.epochs = Some(epochs);
506512

stacks-node/src/tests/epoch_21.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use stacks::chainstate::stacks::StacksBlockHeader;
2626
use stacks::clarity_cli::vm_execute as execute;
2727
use stacks::config::{Config, InitialBalance};
2828
use stacks::core::test_util::make_contract_call;
29-
use stacks::core::{self, EpochList, BURNCHAIN_TX_SEARCH_WINDOW};
29+
use stacks::core::{self, EpochList, BURNCHAIN_TX_SEARCH_WINDOW, STACKS_EPOCH_MAX};
3030
use stacks::util_lib::boot::boot_code_id;
3131
use stacks_common::types::chainstate::{
3232
BlockHeaderHash, BurnchainHeaderHash, StacksAddress, StacksBlockId, VRFSeed,
@@ -79,6 +79,8 @@ fn advance_to_2_1(
7979
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
8080
epochs[StacksEpochId::Epoch2_05].end_height = epoch_2_1;
8181
epochs[StacksEpochId::Epoch21].start_height = epoch_2_1;
82+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
83+
epochs.truncate_after(StacksEpochId::Epoch21);
8284

8385
conf.burnchain.epochs = Some(epochs);
8486

@@ -580,6 +582,8 @@ fn transition_fixes_bitcoin_rigidity() {
580582
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
581583
epochs[StacksEpochId::Epoch2_05].end_height = epoch_2_1;
582584
epochs[StacksEpochId::Epoch21].start_height = epoch_2_1;
585+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
586+
epochs.truncate_after(StacksEpochId::Epoch21);
583587

584588
conf.burnchain.epochs = Some(epochs);
585589

@@ -1476,6 +1480,8 @@ fn transition_removes_pox_sunset() {
14761480
epochs[StacksEpochId::Epoch2_05].start_height = 1;
14771481
epochs[StacksEpochId::Epoch2_05].end_height = epoch_21;
14781482
epochs[StacksEpochId::Epoch21].start_height = epoch_21;
1483+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
1484+
epochs.truncate_after(StacksEpochId::Epoch21);
14791485

14801486
conf.burnchain.epochs = Some(epochs);
14811487

@@ -1731,6 +1737,8 @@ fn transition_empty_blocks() {
17311737
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
17321738
epochs[StacksEpochId::Epoch2_05].end_height = epoch_2_1;
17331739
epochs[StacksEpochId::Epoch21].start_height = epoch_2_1;
1740+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
1741+
epochs.truncate_after(StacksEpochId::Epoch21);
17341742

17351743
conf.node.mine_microblocks = false;
17361744
conf.burnchain.max_rbf = 1000000;
@@ -2006,6 +2014,8 @@ fn test_sortition_divergence_pre_21() {
20062014
epochs[StacksEpochId::Epoch2_05].start_height = 101;
20072015
epochs[StacksEpochId::Epoch2_05].end_height = 241;
20082016
epochs[StacksEpochId::Epoch21].start_height = 241;
2017+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
2018+
epochs.truncate_after(StacksEpochId::Epoch21);
20092019
conf_template.burnchain.epochs = Some(epochs);
20102020

20112021
let privks: Vec<_> = (0..5).map(|_| StacksPrivateKey::random()).collect();
@@ -2438,6 +2448,8 @@ fn trait_invocation_cross_epoch() {
24382448
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
24392449
epochs[StacksEpochId::Epoch2_05].end_height = epoch_2_1;
24402450
epochs[StacksEpochId::Epoch21].start_height = epoch_2_1;
2451+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
2452+
epochs.truncate_after(StacksEpochId::Epoch21);
24412453
conf.burnchain.epochs = Some(epochs);
24422454

24432455
let mut burnchain_config = Burnchain::regtest(&conf.get_burn_db_path());
@@ -2703,6 +2715,8 @@ fn test_v1_unlock_height_with_current_stackers() {
27032715
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
27042716
epochs[StacksEpochId::Epoch2_05].end_height = epoch_2_1;
27052717
epochs[StacksEpochId::Epoch21].start_height = epoch_2_1;
2718+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
2719+
epochs.truncate_after(StacksEpochId::Epoch21);
27062720
conf.burnchain.epochs = Some(epochs);
27072721

27082722
let mut burnchain_config = Burnchain::regtest(&conf.get_burn_db_path());
@@ -2956,6 +2970,8 @@ fn test_v1_unlock_height_with_delay_and_current_stackers() {
29562970
epochs[StacksEpochId::Epoch2_05].start_height = epoch_2_05;
29572971
epochs[StacksEpochId::Epoch2_05].end_height = epoch_2_1;
29582972
epochs[StacksEpochId::Epoch21].start_height = epoch_2_1;
2973+
epochs[StacksEpochId::Epoch21].end_height = STACKS_EPOCH_MAX;
2974+
epochs.truncate_after(StacksEpochId::Epoch21);
29592975
conf.burnchain.epochs = Some(epochs);
29602976

29612977
let mut burnchain_config = Burnchain::regtest(&conf.get_burn_db_path());

stackslib/src/chainstate/coordinator/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,16 @@ impl<
17321732
Ok(None)
17331733
}
17341734

1735+
/// A helper function for exposing the private process_new_pox_anchor_test function
1736+
#[cfg(test)]
1737+
pub fn process_new_pox_anchor_test(
1738+
&mut self,
1739+
block_id: BlockHeaderHash,
1740+
already_processed_burn_blocks: &mut HashSet<BurnchainHeaderHash>,
1741+
) -> Result<Option<BlockHeaderHash>, Error> {
1742+
self.process_new_pox_anchor(block_id, already_processed_burn_blocks)
1743+
}
1744+
17351745
/// Process a new PoX anchor block, possibly resulting in the PoX history being unwound and
17361746
/// replayed through a different sequence of consensus hashes. If the new anchor block causes
17371747
/// the node to reach a prepare-phase that elects a network-affirmed anchor block that we don't

stackslib/src/chainstate/nakamoto/coordinator/mod.rs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -363,36 +363,21 @@ pub fn load_nakamoto_reward_set<U: RewardSetProvider>(
363363
provider: &U,
364364
) -> Result<Option<(RewardCycleInfo, StacksHeaderInfo)>, Error> {
365365
let cycle_start_height = burnchain.nakamoto_first_block_of_cycle(reward_cycle);
366-
367-
let epoch_at_height = SortitionDB::get_stacks_epoch(sort_db.conn(), cycle_start_height)?
368-
.unwrap_or_else(|| {
369-
panic!(
370-
"FATAL: no epoch defined for burn height {}",
371-
cycle_start_height
372-
)
373-
});
374-
375-
// Find the first Stacks block in this reward cycle's preceding prepare phase.
376-
// This block will have invoked `.signers.stackerdb-set-signer-slots()` with the reward set.
377-
// Note that we may not have processed it yet. But, if we do find it, then it's
378-
// unique (and since Nakamoto Stacks blocks are processed in order, the anchor block
379-
// cannot change later).
380-
let first_epoch30_reward_cycle = burnchain
381-
.block_height_to_reward_cycle(epoch_at_height.start_height)
382-
.expect("FATAL: no reward cycle for epoch 3.0 start height");
383-
384-
if !epoch_at_height
385-
.epoch_id
386-
.uses_nakamoto_reward_set(reward_cycle, first_epoch30_reward_cycle)
387-
{
366+
let prepare_phase_start_height =
367+
cycle_start_height.saturating_sub(u64::from(burnchain.pox_constants.prepare_length));
368+
let epoch_at_height =
369+
SortitionDB::get_stacks_epoch(sort_db.conn(), prepare_phase_start_height)?.unwrap_or_else(
370+
|| panic!("FATAL: no epoch defined for burn height {prepare_phase_start_height}"),
371+
);
372+
if epoch_at_height.epoch_id < StacksEpochId::Epoch30 {
388373
// in epoch 2.5, and in the first reward cycle of epoch 3.0, the reward set can *only* be found in the sortition DB.
389374
// The nakamoto chain-processing rules aren't active yet, so we can't look for the reward
390375
// cycle info in the nakamoto chain state.
391376
let Some(prepare_end_sortition_id) =
392377
get_ancestor_sort_id(&sort_db.index_conn(), cycle_start_height, sortition_tip)?
393378
else {
394379
// reward cycle is too far in the future
395-
warn!("Requested reward cycle start ancestor sortition ID for cycle {} prepare-end height {}, but tip is {}", reward_cycle, cycle_start_height, sortition_tip);
380+
warn!("Requested reward cycle start ancestor sortition ID for cycle {reward_cycle} prepare-end height {cycle_start_height}, but tip is {sortition_tip}");
396381
return Ok(None);
397382
};
398383

stackslib/src/chainstate/nakamoto/coordinator/tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ fn block_descendant() {
942942
pox_constants.v2_unlock_height = 21;
943943
pox_constants.pox_3_activation_height = 26;
944944
pox_constants.v3_unlock_height = 27;
945-
pox_constants.pox_4_activation_height = 28;
945+
pox_constants.pox_4_activation_height = 33;
946946

947947
let mut boot_plan = NakamotoBootPlan::new(function_name!())
948948
.with_test_stackers(test_stackers)
@@ -1031,7 +1031,7 @@ fn block_info_tests(use_primary_testnet: bool) {
10311031
pox_constants.v2_unlock_height = 21;
10321032
pox_constants.pox_3_activation_height = 26;
10331033
pox_constants.v3_unlock_height = 27;
1034-
pox_constants.pox_4_activation_height = 28;
1034+
pox_constants.pox_4_activation_height = 33;
10351035

10361036
let chain_id = if use_primary_testnet {
10371037
CHAIN_ID_TESTNET
@@ -1466,7 +1466,7 @@ fn pox_treatment() {
14661466
pox_constants.v2_unlock_height = 21;
14671467
pox_constants.pox_3_activation_height = 26;
14681468
pox_constants.v3_unlock_height = 27;
1469-
pox_constants.pox_4_activation_height = 28;
1469+
pox_constants.pox_4_activation_height = 33;
14701470

14711471
let mut boot_plan = NakamotoBootPlan::new(function_name!())
14721472
.with_test_stackers(test_stackers.clone())
@@ -1719,7 +1719,7 @@ fn transactions_indexing() {
17191719
pox_constants.v2_unlock_height = 21;
17201720
pox_constants.pox_3_activation_height = 26;
17211721
pox_constants.v3_unlock_height = 27;
1722-
pox_constants.pox_4_activation_height = 28;
1722+
pox_constants.pox_4_activation_height = 33;
17231723

17241724
let mut boot_plan = NakamotoBootPlan::new(function_name!())
17251725
.with_test_stackers(test_stackers.clone())
@@ -1784,7 +1784,7 @@ fn transactions_not_indexing() {
17841784
pox_constants.v2_unlock_height = 21;
17851785
pox_constants.pox_3_activation_height = 26;
17861786
pox_constants.v3_unlock_height = 27;
1787-
pox_constants.pox_4_activation_height = 28;
1787+
pox_constants.pox_4_activation_height = 33;
17881788

17891789
let mut boot_plan = NakamotoBootPlan::new(function_name!())
17901790
.with_test_stackers(test_stackers.clone())
@@ -3897,7 +3897,7 @@ fn process_next_nakamoto_block_deadlock() {
38973897
pox_constants.v2_unlock_height = 21;
38983898
pox_constants.pox_3_activation_height = 26;
38993899
pox_constants.v3_unlock_height = 27;
3900-
pox_constants.pox_4_activation_height = 28;
3900+
pox_constants.pox_4_activation_height = 33;
39013901

39023902
let mut boot_plan = NakamotoBootPlan::new(function_name!())
39033903
.with_test_stackers(test_stackers)

0 commit comments

Comments
 (0)