diff --git a/stackslib/src/burnchains/bitcoin/indexer.rs b/stackslib/src/burnchains/bitcoin/indexer.rs index 40cabd86d30..901587c9927 100644 --- a/stackslib/src/burnchains/bitcoin/indexer.rs +++ b/stackslib/src/burnchains/bitcoin/indexer.rs @@ -1005,9 +1005,9 @@ impl BurnchainIndexer for BitcoinIndexer { false, )?; let first_block_height = self.get_first_block_height(); - let first_header = spv_client - .read_block_header(first_block_height)? - .expect("BUG: no first block header hash"); + let Ok(Some(first_header)) = spv_client.read_block_header(first_block_height) else { + return Err(burnchain_error::MissingHeaders); + }; let first_block_header_hash = BurnchainHeaderHash::from_bitcoin_hash(&first_header.header.bitcoin_hash()); diff --git a/stackslib/src/burnchains/mod.rs b/stackslib/src/burnchains/mod.rs index 0bc68897cbd..73d9c986f3f 100644 --- a/stackslib/src/burnchains/mod.rs +++ b/stackslib/src/burnchains/mod.rs @@ -472,17 +472,19 @@ impl PoxConstants { #[cfg_attr(test, mutants::skip)] pub fn regtest_default() -> PoxConstants { PoxConstants::new( + 20, 5, 3, - 2, - 3333333333333333, - 1, + 25, + 5, BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT + POX_SUNSET_START, BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT + POX_SUNSET_END, - 1_000_000, - 2_000_000, - 4_000_000, - 3_000_000, + POX_V1_REGTEST_EARLY_UNLOCK_HEIGHT, + POX_V2_REGTEST_EARLY_UNLOCK_HEIGHT, + POX_V3_REGTEST_EARLY_UNLOCK_HEIGHT, + BITCOIN_REGTEST_STACKS_24_BURN_HEIGHT + .try_into() + .expect("Epoch transition height must be <= u32::MAX"), ) } diff --git a/stackslib/src/core/mod.rs b/stackslib/src/core/mod.rs index ade8a825899..d6bb09274e4 100644 --- a/stackslib/src/core/mod.rs +++ b/stackslib/src/core/mod.rs @@ -116,7 +116,17 @@ pub const BITCOIN_TESTNET_STACKS_30_BURN_HEIGHT: u64 = 30_000_000; /// expected affirmation maps (so it only must be accurate to the reward cycle). pub const BITCOIN_TESTNET_STACKS_25_REORGED_HEIGHT: u64 = 2_586_000; -pub const BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT: u64 = 0; +// On regtest networks, we need to matured coinbases for mining Stacks blocks. +// We start at block #100 so we avoid indexing the first 100 non matured +// coinbases. +pub const BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT: u64 = 100; +pub const BITCOIN_REGTEST_STACKS_2_05_BURN_HEIGHT: u64 = 120; +pub const BITCOIN_REGTEST_STACKS_21_BURN_HEIGHT: u64 = 140; +pub const BITCOIN_REGTEST_STACKS_22_BURN_HEIGHT: u64 = 160; +pub const BITCOIN_REGTEST_STACKS_23_BURN_HEIGHT: u64 = 180; +pub const BITCOIN_REGTEST_STACKS_24_BURN_HEIGHT: u64 = 200; +pub const BITCOIN_REGTEST_STACKS_25_BURN_HEIGHT: u64 = 6000; +pub const BITCOIN_REGTEST_STACKS_30_BURN_HEIGHT: u64 = 7001; pub const BITCOIN_REGTEST_FIRST_BLOCK_TIMESTAMP: u32 = 0; pub const BITCOIN_REGTEST_FIRST_BLOCK_HASH: &str = "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"; @@ -158,16 +168,22 @@ pub const POX_V1_MAINNET_EARLY_UNLOCK_HEIGHT: u32 = (BITCOIN_MAINNET_STACKS_21_BURN_HEIGHT as u32) + 1; pub const POX_V1_TESTNET_EARLY_UNLOCK_HEIGHT: u32 = (BITCOIN_TESTNET_STACKS_21_BURN_HEIGHT as u32) + 1; +pub const POX_V1_REGTEST_EARLY_UNLOCK_HEIGHT: u32 = + (BITCOIN_REGTEST_STACKS_21_BURN_HEIGHT as u32) + 1; pub const POX_V2_MAINNET_EARLY_UNLOCK_HEIGHT: u32 = (BITCOIN_MAINNET_STACKS_22_BURN_HEIGHT as u32) + 1; pub const POX_V2_TESTNET_EARLY_UNLOCK_HEIGHT: u32 = (BITCOIN_TESTNET_STACKS_22_BURN_HEIGHT as u32) + 1; +pub const POX_V2_REGTEST_EARLY_UNLOCK_HEIGHT: u32 = + (BITCOIN_REGTEST_STACKS_22_BURN_HEIGHT as u32) + 1; pub const POX_V3_MAINNET_EARLY_UNLOCK_HEIGHT: u32 = (BITCOIN_MAINNET_STACKS_25_BURN_HEIGHT as u32) + 1; pub const POX_V3_TESTNET_EARLY_UNLOCK_HEIGHT: u32 = (BITCOIN_TESTNET_STACKS_25_BURN_HEIGHT as u32) + 1; +pub const POX_V3_REGTEST_EARLY_UNLOCK_HEIGHT: u32 = + (BITCOIN_REGTEST_STACKS_24_BURN_HEIGHT as u32) + 1; // The threshold of weighted votes on a block to approve it in Nakamoto. // This is out of 10, so 7 means "70%". @@ -383,56 +399,56 @@ lazy_static! { }, StacksEpoch { epoch_id: StacksEpochId::Epoch20, - start_height: 0, - end_height: 1000, + start_height: BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_2_05_BURN_HEIGHT, block_limit: HELIUM_BLOCK_LIMIT_20.clone(), network_epoch: PEER_VERSION_EPOCH_2_0 }, StacksEpoch { epoch_id: StacksEpochId::Epoch2_05, - start_height: 1000, - end_height: 2000, + start_height: BITCOIN_REGTEST_STACKS_2_05_BURN_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_21_BURN_HEIGHT, block_limit: HELIUM_BLOCK_LIMIT_20.clone(), network_epoch: PEER_VERSION_EPOCH_2_05 }, StacksEpoch { epoch_id: StacksEpochId::Epoch21, - start_height: 2000, - end_height: 3000, + start_height: BITCOIN_REGTEST_STACKS_21_BURN_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_22_BURN_HEIGHT, block_limit: HELIUM_BLOCK_LIMIT_20.clone(), network_epoch: PEER_VERSION_EPOCH_2_1 }, StacksEpoch { epoch_id: StacksEpochId::Epoch22, - start_height: 3000, - end_height: 4000, + start_height: BITCOIN_REGTEST_STACKS_22_BURN_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_23_BURN_HEIGHT, block_limit: HELIUM_BLOCK_LIMIT_20.clone(), network_epoch: PEER_VERSION_EPOCH_2_2 }, StacksEpoch { epoch_id: StacksEpochId::Epoch23, - start_height: 4000, - end_height: 5000, + start_height: BITCOIN_REGTEST_STACKS_23_BURN_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_24_BURN_HEIGHT, block_limit: HELIUM_BLOCK_LIMIT_20.clone(), network_epoch: PEER_VERSION_EPOCH_2_3 }, StacksEpoch { epoch_id: StacksEpochId::Epoch24, - start_height: 5000, - end_height: 6000, + start_height: BITCOIN_REGTEST_STACKS_24_BURN_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_25_BURN_HEIGHT, block_limit: HELIUM_BLOCK_LIMIT_20.clone(), network_epoch: PEER_VERSION_EPOCH_2_4 }, StacksEpoch { epoch_id: StacksEpochId::Epoch25, - start_height: 6000, - end_height: 7001, + start_height: BITCOIN_REGTEST_STACKS_25_BURN_HEIGHT, + end_height: BITCOIN_REGTEST_STACKS_30_BURN_HEIGHT, block_limit: BLOCK_LIMIT_MAINNET_21.clone(), network_epoch: PEER_VERSION_EPOCH_2_5 }, StacksEpoch { epoch_id: StacksEpochId::Epoch30, - start_height: 7001, + start_height: BITCOIN_REGTEST_STACKS_30_BURN_HEIGHT, end_height: STACKS_EPOCH_MAX, block_limit: BLOCK_LIMIT_MAINNET_21.clone(), network_epoch: PEER_VERSION_EPOCH_3_0 diff --git a/testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs b/testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs index 145e73a3897..0405f8b137c 100644 --- a/testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs +++ b/testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs @@ -587,12 +587,12 @@ impl BitcoinRegtestController { burnchain_error::BurnchainPeerBroken => { // remote burnchain peer broke, and produced a shorter blockchain fork. // just keep trying - sleep_ms(5000); + sleep_ms(1000); continue; } _ => { // delay and try again - sleep_ms(5000); + sleep_ms(1000); continue; } } diff --git a/testnet/stacks-node/src/config.rs b/testnet/stacks-node/src/config.rs index d1b115d9cf5..c6c74a9c4e9 100644 --- a/testnet/stacks-node/src/config.rs +++ b/testnet/stacks-node/src/config.rs @@ -19,6 +19,7 @@ use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs}; use std::path::PathBuf; use std::str::FromStr; use std::sync::{Arc, Mutex}; +use std::thread::sleep; use std::time::Duration; use std::{cmp, fs, thread}; @@ -1127,7 +1128,6 @@ impl Config { .collect(); let endpoint = format!("{}", observer.endpoint); - observers.insert(EventObserverConfig { endpoint, events_keys, @@ -1709,18 +1709,21 @@ impl BurnchainConfigFile { // Using std::net::LookupHost would be preferable, but it's // unfortunately unstable at this point. // https://doc.rust-lang.org/1.6.0/std/net/struct.LookupHost.html - let mut sock_addrs = format!("{}:1", &peer_host) - .to_socket_addrs() - .map_err(|e| format!("Invalid burnchain.peer_host: {}", &e))?; - let sock_addr = match sock_addrs.next() { - Some(addr) => addr, - None => { + let mut attempts = 0; + let mut addrs_iter = loop { + if let Ok(addrs_iter) = format!("{peer_host}:1").to_socket_addrs() { + break addrs_iter; + } + attempts += 1; + if attempts == 15 { return Err(format!( "No IP address could be queried for '{}'", &peer_host )); } + sleep(std::time::Duration::from_secs(5)); }; + let sock_addr = addrs_iter.next().expect("Failed to resolve IP address"); format!("{}", sock_addr.ip()) } None => default_burnchain_config.peer_host,