Skip to content

Commit b34bf5f

Browse files
authored
Merge branch 'develop' into feat/always-send-block-response
2 parents 014e3fd + 20d5137 commit b34bf5f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+745
-553
lines changed

stacks-common/src/types/mod.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cmp::Ordering;
22
use std::fmt;
3+
use std::ops::{Deref, DerefMut, Index, IndexMut};
34

45
#[cfg(feature = "canonical")]
56
pub mod sqlite;
@@ -460,3 +461,83 @@ impl<L: PartialEq + Eq> Ord for StacksEpoch<L> {
460461
self.epoch_id.cmp(&other.epoch_id)
461462
}
462463
}
464+
465+
/// A wrapper for holding a list of Epochs, indexable by StacksEpochId
466+
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq)]
467+
pub struct EpochList<L: Clone>(Vec<StacksEpoch<L>>);
468+
469+
impl<L: Clone> EpochList<L> {
470+
pub fn new(epochs: &[StacksEpoch<L>]) -> EpochList<L> {
471+
EpochList(epochs.to_vec())
472+
}
473+
474+
pub fn get(&self, index: StacksEpochId) -> Option<&StacksEpoch<L>> {
475+
self.0.get(StacksEpoch::find_epoch_by_id(&self.0, index)?)
476+
}
477+
478+
pub fn get_mut(&mut self, index: StacksEpochId) -> Option<&mut StacksEpoch<L>> {
479+
let index = StacksEpoch::find_epoch_by_id(&self.0, index)?;
480+
self.0.get_mut(index)
481+
}
482+
483+
/// Truncates the list after the given epoch id
484+
pub fn truncate_after(&mut self, epoch_id: StacksEpochId) {
485+
if let Some(index) = StacksEpoch::find_epoch_by_id(&self.0, epoch_id) {
486+
self.0.truncate(index + 1);
487+
}
488+
}
489+
490+
/// Determine which epoch, if any, a given burnchain height falls into.
491+
pub fn epoch_id_at_height(&self, height: u64) -> Option<StacksEpochId> {
492+
StacksEpoch::find_epoch(self, height).map(|idx| self.0[idx].epoch_id)
493+
}
494+
495+
/// Determine which epoch, if any, a given burnchain height falls into.
496+
pub fn epoch_at_height(&self, height: u64) -> Option<StacksEpoch<L>> {
497+
StacksEpoch::find_epoch(self, height).map(|idx| self.0[idx].clone())
498+
}
499+
500+
/// Pushes a new `StacksEpoch` to the end of the list
501+
pub fn push(&mut self, epoch: StacksEpoch<L>) {
502+
if let Some(last) = self.0.last() {
503+
assert!(
504+
epoch.start_height == last.end_height && epoch.epoch_id > last.epoch_id,
505+
"Epochs must be pushed in order"
506+
);
507+
}
508+
self.0.push(epoch);
509+
}
510+
511+
pub fn to_vec(&self) -> Vec<StacksEpoch<L>> {
512+
self.0.clone()
513+
}
514+
}
515+
516+
impl<L: Clone> Index<StacksEpochId> for EpochList<L> {
517+
type Output = StacksEpoch<L>;
518+
fn index(&self, index: StacksEpochId) -> &StacksEpoch<L> {
519+
self.get(index)
520+
.expect("Invalid StacksEpochId: could not find corresponding epoch")
521+
}
522+
}
523+
524+
impl<L: Clone> IndexMut<StacksEpochId> for EpochList<L> {
525+
fn index_mut(&mut self, index: StacksEpochId) -> &mut StacksEpoch<L> {
526+
self.get_mut(index)
527+
.expect("Invalid StacksEpochId: could not find corresponding epoch")
528+
}
529+
}
530+
531+
impl<L: Clone> Deref for EpochList<L> {
532+
type Target = [StacksEpoch<L>];
533+
534+
fn deref(&self) -> &Self::Target {
535+
&self.0
536+
}
537+
}
538+
539+
impl<L: Clone> DerefMut for EpochList<L> {
540+
fn deref_mut(&mut self) -> &mut Self::Target {
541+
&mut self.0
542+
}
543+
}

stacks-signer/src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SpawnedSigner
125125
);
126126
let (res_send, res_recv) = channel();
127127
let ev = SignerEventReceiver::new(config.network.is_mainnet());
128-
#[cfg(feature = "monitoring_prom")]
129-
{
130-
crate::monitoring::start_serving_monitoring_metrics(config.clone()).ok();
131-
}
128+
crate::monitoring::start_serving_monitoring_metrics(config.clone()).ok();
132129
let runloop = RunLoop::new(config.clone());
133130
let mut signer: RunLoopSigner<S, T> = libsigner::Signer::new(runloop, ev, res_send);
134131
let running_signer = signer.spawn(endpoint).expect("Failed to spawn signer");

stacks-signer/src/monitoring/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ use ::prometheus::HistogramTimer;
1919
#[cfg(feature = "monitoring_prom")]
2020
use slog::slog_error;
2121
#[cfg(not(feature = "monitoring_prom"))]
22-
use slog::slog_warn;
22+
use slog::slog_info;
2323
#[cfg(feature = "monitoring_prom")]
2424
use stacks_common::error;
2525
#[cfg(not(feature = "monitoring_prom"))]
26-
use stacks_common::warn;
26+
use stacks_common::info;
2727

2828
use crate::config::GlobalConfig;
2929

@@ -143,7 +143,7 @@ pub fn start_serving_monitoring_metrics(config: GlobalConfig) -> Result<(), Stri
143143
#[cfg(not(feature = "monitoring_prom"))]
144144
{
145145
if config.metrics_endpoint.is_some() {
146-
warn!("Not starting monitoring metrics server as the monitoring_prom feature is not enabled");
146+
info!("`metrics_endpoint` is configured for the signer, but the monitoring_prom feature is not enabled. Not starting monitoring metrics server.");
147147
}
148148
}
149149
Ok(())

stacks-signer/src/v0/signer.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use blockstack_lib::chainstate::nakamoto::{NakamotoBlock, NakamotoBlockHeader};
2121
use blockstack_lib::net::api::postblock_proposal::{
2222
BlockValidateOk, BlockValidateReject, BlockValidateResponse,
2323
};
24+
use blockstack_lib::util_lib::db::Error as DBError;
2425
use clarity::types::chainstate::StacksPrivateKey;
2526
use clarity::types::{PrivateKey, StacksEpochId};
2627
use clarity::util::hash::MerkleHashFunc;
@@ -496,7 +497,7 @@ impl Signer {
496497
// Do not store KNOWN invalid blocks as this could DOS the signer. We only store blocks that are valid or unknown.
497498
self.signer_db
498499
.insert_block(&block_info)
499-
.unwrap_or_else(|_| panic!("{self}: Failed to insert block in DB"));
500+
.unwrap_or_else(|e| self.handle_insert_block_error(e));
500501
}
501502
}
502503

@@ -569,7 +570,7 @@ impl Signer {
569570

570571
self.signer_db
571572
.insert_block(&block_info)
572-
.unwrap_or_else(|_| panic!("{self}: Failed to insert block in DB"));
573+
.unwrap_or_else(|e| self.handle_insert_block_error(e));
573574
let accepted = BlockAccepted::new(block_info.signer_signature_hash(), signature);
574575
// have to save the signature _after_ the block info
575576
self.handle_block_signature(stacks_client, &accepted);
@@ -627,7 +628,7 @@ impl Signer {
627628
);
628629
self.signer_db
629630
.insert_block(&block_info)
630-
.unwrap_or_else(|_| panic!("{self}: Failed to insert block in DB"));
631+
.unwrap_or_else(|e| self.handle_insert_block_error(e));
631632
self.handle_block_rejection(&block_rejection);
632633
Some(BlockResponse::Rejected(block_rejection))
633634
}
@@ -740,7 +741,7 @@ impl Signer {
740741
}
741742
self.signer_db
742743
.insert_block(&block_info)
743-
.unwrap_or_else(|_| panic!("{self}: Failed to insert block in DB"));
744+
.unwrap_or_else(|e| self.handle_insert_block_error(e));
744745
}
745746

746747
/// Compute the signing weight, given a list of signatures
@@ -1096,7 +1097,7 @@ impl Signer {
10961097
// in case this is the first time we saw this block. Safe to do since this is testing case only.
10971098
self.signer_db
10981099
.insert_block(block_info)
1099-
.unwrap_or_else(|_| panic!("{self}: Failed to insert block in DB"));
1100+
.unwrap_or_else(|e| self.handle_insert_block_error(e));
11001101
Some(BlockResponse::rejected(
11011102
block_proposal.block.header.signer_signature_hash(),
11021103
RejectCode::TestingDirective,
@@ -1120,4 +1121,10 @@ impl Signer {
11201121
warn!("{self}: Failed to send mock signature to stacker-db: {e:?}",);
11211122
}
11221123
}
1124+
1125+
/// Helper for logging insert_block error
1126+
fn handle_insert_block_error(&self, e: DBError) {
1127+
error!("{self}: Failed to insert block into signer-db: {e:?}");
1128+
panic!("{self} Failed to write block to signerdb: {e}");
1129+
}
11231130
}

stackslib/src/burnchains/bitcoin/indexer.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::burnchains::{
4545
Burnchain, BurnchainBlockHeader, Error as burnchain_error, MagicBytes, BLOCKSTACK_MAGIC_MAINNET,
4646
};
4747
use crate::core::{
48-
StacksEpoch, StacksEpochExtension, STACKS_EPOCHS_MAINNET, STACKS_EPOCHS_REGTEST,
48+
EpochList, StacksEpoch, StacksEpochExtension, STACKS_EPOCHS_MAINNET, STACKS_EPOCHS_REGTEST,
4949
STACKS_EPOCHS_TESTNET,
5050
};
5151
use crate::util_lib::db::Error as DBError;
@@ -91,11 +91,11 @@ impl TryFrom<u32> for BitcoinNetworkType {
9191
/// Get the default epochs definitions for the given BitcoinNetworkType.
9292
/// Should *not* be used except by the BitcoinIndexer when no epochs vector
9393
/// was specified.
94-
pub fn get_bitcoin_stacks_epochs(network_id: BitcoinNetworkType) -> Vec<StacksEpoch> {
94+
pub fn get_bitcoin_stacks_epochs(network_id: BitcoinNetworkType) -> EpochList {
9595
match network_id {
96-
BitcoinNetworkType::Mainnet => STACKS_EPOCHS_MAINNET.to_vec(),
97-
BitcoinNetworkType::Testnet => STACKS_EPOCHS_TESTNET.to_vec(),
98-
BitcoinNetworkType::Regtest => STACKS_EPOCHS_REGTEST.to_vec(),
96+
BitcoinNetworkType::Mainnet => (*STACKS_EPOCHS_MAINNET).clone(),
97+
BitcoinNetworkType::Testnet => (*STACKS_EPOCHS_TESTNET).clone(),
98+
BitcoinNetworkType::Regtest => (*STACKS_EPOCHS_REGTEST).clone(),
9999
}
100100
}
101101

@@ -112,7 +112,7 @@ pub struct BitcoinIndexerConfig {
112112
pub spv_headers_path: String,
113113
pub first_block: u64,
114114
pub magic_bytes: MagicBytes,
115-
pub epochs: Option<Vec<StacksEpoch>>,
115+
pub epochs: Option<EpochList>,
116116
}
117117

118118
#[derive(Debug)]
@@ -1041,7 +1041,7 @@ impl BurnchainIndexer for BitcoinIndexer {
10411041
/// 2) Use hard-coded static values, otherwise.
10421042
///
10431043
/// It is an error (panic) to set custom epochs if running on `Mainnet`.
1044-
fn get_stacks_epochs(&self) -> Vec<StacksEpoch> {
1044+
fn get_stacks_epochs(&self) -> EpochList {
10451045
StacksEpoch::get_epochs(self.runtime.network_id, self.config.epochs.as_ref())
10461046
}
10471047

stackslib/src/burnchains/burnchain.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use stacks_common::util::hash::to_hex;
2929
use stacks_common::util::vrf::VRFPublicKey;
3030
use stacks_common::util::{get_epoch_time_ms, get_epoch_time_secs, log, sleep_ms};
3131

32+
use super::EpochList;
3233
use crate::burnchains::affirmation::update_pox_affirmation_maps;
3334
use crate::burnchains::bitcoin::address::{
3435
to_c32_version_byte, BitcoinAddress, LegacyBitcoinAddressType,
@@ -722,7 +723,7 @@ impl Burnchain {
722723
readwrite: bool,
723724
first_block_header_hash: BurnchainHeaderHash,
724725
first_block_header_timestamp: u64,
725-
epochs: Vec<StacksEpoch>,
726+
epochs: EpochList,
726727
) -> Result<(SortitionDB, BurnchainDB), burnchain_error> {
727728
Burnchain::setup_chainstate_dirs(&self.working_dir)?;
728729

stackslib/src/burnchains/indexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub trait BurnchainIndexer {
6262
fn get_first_block_height(&self) -> u64;
6363
fn get_first_block_header_hash(&self) -> Result<BurnchainHeaderHash, burnchain_error>;
6464
fn get_first_block_header_timestamp(&self) -> Result<u64, burnchain_error>;
65-
fn get_stacks_epochs(&self) -> Vec<StacksEpoch>;
65+
fn get_stacks_epochs(&self) -> EpochList;
6666

6767
fn get_headers_path(&self) -> String;
6868
fn get_headers_height(&self) -> Result<u64, burnchain_error>;

stackslib/src/chainstate/burn/db/sortdb.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,9 +2969,9 @@ impl SortitionDB {
29692969
db_tx: &Transaction,
29702970
epochs: &[StacksEpoch],
29712971
) -> Result<(), db_error> {
2972-
let epochs = StacksEpoch::validate_epochs(epochs);
2972+
let epochs: &[StacksEpoch] = &StacksEpoch::validate_epochs(epochs);
29732973
let existing_epochs = Self::get_stacks_epochs(db_tx)?;
2974-
if existing_epochs == epochs {
2974+
if &existing_epochs == epochs {
29752975
return Ok(());
29762976
}
29772977

@@ -3482,9 +3482,10 @@ impl SortitionDB {
34823482
tx.commit()?;
34833483
} else if version == expected_version {
34843484
// this transaction is almost never needed
3485-
let validated_epochs = StacksEpoch::validate_epochs(epochs);
3485+
let validated_epochs: &[StacksEpoch] =
3486+
&StacksEpoch::validate_epochs(epochs);
34863487
let existing_epochs = Self::get_stacks_epochs(self.conn())?;
3487-
if existing_epochs == validated_epochs {
3488+
if &existing_epochs == validated_epochs {
34883489
return Ok(());
34893490
}
34903491

@@ -6636,7 +6637,7 @@ pub mod tests {
66366637
pub fn connect_test_with_epochs(
66376638
first_block_height: u64,
66386639
first_burn_hash: &BurnchainHeaderHash,
6639-
epochs: Vec<StacksEpoch>,
6640+
epochs: EpochList,
66406641
) -> Result<SortitionDB, db_error> {
66416642
let mut rng = rand::thread_rng();
66426643
let mut buf = [0u8; 32];
@@ -10930,10 +10931,9 @@ pub mod tests {
1093010931

1093110932
fs::create_dir_all(path_root).unwrap();
1093210933

10933-
let mut bad_epochs = STACKS_EPOCHS_MAINNET.to_vec();
10934-
let idx = bad_epochs.len() - 2;
10935-
bad_epochs[idx].end_height += 1;
10936-
bad_epochs[idx + 1].start_height += 1;
10934+
let mut bad_epochs = (*STACKS_EPOCHS_MAINNET).clone();
10935+
bad_epochs[StacksEpochId::Epoch25].end_height += 1;
10936+
bad_epochs[StacksEpochId::Epoch30].start_height += 1;
1093710937

1093810938
let sortdb = SortitionDB::connect(
1093910939
&format!("{}/sortdb.sqlite", &path_root),
@@ -10948,14 +10948,14 @@ pub mod tests {
1094810948
.unwrap();
1094910949

1095010950
let db_epochs = SortitionDB::get_stacks_epochs(sortdb.conn()).unwrap();
10951-
assert_eq!(db_epochs, bad_epochs);
10951+
assert_eq!(db_epochs, bad_epochs.to_vec());
1095210952

1095310953
let fixed_sortdb = SortitionDB::connect(
1095410954
&format!("{}/sortdb.sqlite", &path_root),
1095510955
0,
1095610956
&BurnchainHeaderHash([0x00; 32]),
1095710957
0,
10958-
&STACKS_EPOCHS_MAINNET.to_vec(),
10958+
&STACKS_EPOCHS_MAINNET,
1095910959
PoxConstants::mainnet_default(),
1096010960
None,
1096110961
true,

stackslib/src/chainstate/coordinator/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ pub fn setup_states_with_epochs(
290290
pox_consts: Option<PoxConstants>,
291291
initial_balances: Option<Vec<(PrincipalData, u64)>>,
292292
stacks_epoch_id: StacksEpochId,
293-
epochs_opt: Option<Vec<StacksEpoch>>,
293+
epochs_opt: Option<EpochList>,
294294
) {
295295
let mut burn_block = None;
296296
let mut others = vec![];

stackslib/src/chainstate/stacks/boot/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,7 @@ pub mod test {
16401640
pub fn instantiate_pox_peer_with_epoch<'a>(
16411641
burnchain: &Burnchain,
16421642
test_name: &str,
1643-
epochs: Option<Vec<StacksEpoch>>,
1643+
epochs: Option<EpochList>,
16441644
observer: Option<&'a TestEventObserver>,
16451645
) -> (TestPeer<'a>, Vec<StacksPrivateKey>) {
16461646
let mut peer_config = TestPeerConfig::new(test_name, 0, 0);

0 commit comments

Comments
 (0)