Skip to content

Commit ce31f70

Browse files
committed
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into feat/signer-state-machine-rollout
2 parents ed89aa5 + 0a4f5f1 commit ce31f70

File tree

13 files changed

+328
-118
lines changed

13 files changed

+328
-118
lines changed

stacks-signer/src/v0/signer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ impl Signer {
492492
);
493493
#[cfg(any(test, feature = "testing"))]
494494
if self.test_skip_block_broadcast(b) {
495-
return;
495+
continue;
496496
}
497497
self.handle_post_block(stacks_client, b);
498498
}
@@ -501,7 +501,7 @@ impl Signer {
501501
Ok(epoch) => epoch,
502502
Err(e) => {
503503
warn!("{self}: Failed to determine node epoch. Cannot mock sign: {e}");
504-
return;
504+
continue;
505505
}
506506
};
507507
info!("{self}: received a mock block proposal.";

stackslib/src/burnchains/burnchain.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ use crate::core::{
6262
use crate::monitoring::update_burnchain_height;
6363
use crate::util_lib::db::Error as db_error;
6464

65+
#[cfg(any(test, feature = "testing"))]
66+
pub static TEST_DOWNLOAD_ERROR_ON_REORG: std::sync::Mutex<bool> = std::sync::Mutex::new(false);
67+
68+
#[cfg(any(test, feature = "testing"))]
69+
fn fault_inject_downloader_on_reorg(did_reorg: bool) -> bool {
70+
did_reorg && *TEST_DOWNLOAD_ERROR_ON_REORG.lock().unwrap()
71+
}
72+
73+
#[cfg(not(any(test, feature = "testing")))]
74+
fn fault_inject_downloader_on_reorg(_did_reorg: bool) -> bool {
75+
false
76+
}
77+
6578
impl BurnchainStateTransitionOps {
6679
pub fn noop() -> BurnchainStateTransitionOps {
6780
BurnchainStateTransitionOps {
@@ -1502,10 +1515,38 @@ impl Burnchain {
15021515
}
15031516
}
15041517

1505-
let mut start_block = sync_height;
1506-
if db_height < start_block {
1507-
start_block = db_height;
1508-
}
1518+
// check if the db has the parent of sync_height, if not,
1519+
// start at the highest common ancestor
1520+
// if it does, then start at the minimum of db_height and sync_height
1521+
let start_block = if sync_height == 0 {
1522+
0
1523+
} else {
1524+
let Some(sync_header) = indexer.read_burnchain_header(sync_height)? else {
1525+
warn!("Missing burnchain header not read for sync start height";
1526+
"sync_height" => sync_height);
1527+
return Err(burnchain_error::MissingHeaders);
1528+
};
1529+
1530+
let mut cursor = sync_header;
1531+
loop {
1532+
if burnchain_db.has_burnchain_block(&cursor.block_hash)? {
1533+
break cursor.block_height;
1534+
}
1535+
1536+
cursor = indexer
1537+
.read_burnchain_header(cursor.block_height.checked_sub(1).ok_or_else(
1538+
|| {
1539+
error!("Could not find common ancestor, passed bitcoin genesis");
1540+
burnchain_error::MissingHeaders
1541+
},
1542+
)?)?
1543+
.ok_or_else(|| {
1544+
warn!("Missing burnchain header not read for parent of indexed header";
1545+
"indexed_header" => ?cursor);
1546+
burnchain_error::MissingHeaders
1547+
})?;
1548+
}
1549+
};
15091550

15101551
debug!(
15111552
"Sync'ed headers from {} to {}. DB at {}",
@@ -1605,6 +1646,17 @@ impl Burnchain {
16051646
_ => {}
16061647
};
16071648

1649+
if fault_inject_downloader_on_reorg(did_reorg) {
1650+
warn!("Stalling and yielding an error for the reorg";
1651+
"error_ht" => BurnHeaderIPC::height(&ipc_header),
1652+
"sync_ht" => sync_height,
1653+
"start_ht" => start_block,
1654+
"end_ht" => end_block,
1655+
);
1656+
thread::sleep(Duration::from_secs(10));
1657+
return Err(burnchain_error::UnsupportedBurnchain);
1658+
}
1659+
16081660
let download_start = get_epoch_time_ms();
16091661
let ipc_block = downloader.download(&ipc_header)?;
16101662
let download_end = get_epoch_time_ms();

stackslib/src/burnchains/db.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,12 @@ impl BurnchainDB {
11291129
Ok(res.is_some())
11301130
}
11311131

1132+
pub fn has_burnchain_block(&self, block: &BurnchainHeaderHash) -> Result<bool, BurnchainError> {
1133+
let qry = "SELECT 1 FROM burnchain_db_block_headers WHERE block_hash = ?1";
1134+
let res: Option<i64> = query_row(&self.conn, qry, &[block])?;
1135+
Ok(res.is_some())
1136+
}
1137+
11321138
pub fn get_burnchain_header<B: BurnchainHeaderReader>(
11331139
conn: &DBConn,
11341140
indexer: &B,

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,29 +2851,6 @@ impl NakamotoChainState {
28512851
Self::get_block_header_nakamoto(chainstate_conn.sqlite(), &block_id)
28522852
}
28532853

2854-
/// DO NOT USE IN CONSENSUS CODE. Different nodes can have different blocks for the same
2855-
/// tenure.
2856-
///
2857-
/// Get the highest block in a given tenure (identified by its consensus hash).
2858-
/// Ties will be broken by timestamp.
2859-
///
2860-
/// Used to verify that a signer-submitted block proposal builds atop the highest known block
2861-
/// in the given tenure, regardless of which fork it's on.
2862-
pub fn get_highest_known_block_header_in_tenure(
2863-
db: &Connection,
2864-
consensus_hash: &ConsensusHash,
2865-
) -> Result<Option<StacksHeaderInfo>, ChainstateError> {
2866-
// see if we have a nakamoto block in this tenure
2867-
let qry = "SELECT * FROM nakamoto_block_headers WHERE consensus_hash = ?1 ORDER BY block_height DESC, timestamp DESC LIMIT 1";
2868-
let args = params![consensus_hash];
2869-
if let Some(header) = query_row(db, qry, args)? {
2870-
return Ok(Some(header));
2871-
}
2872-
2873-
// see if this is an epoch2 header. If it exists, then there will only be one.
2874-
Ok(StacksChainState::get_stacks_block_header_info_by_consensus_hash(db, consensus_hash)?)
2875-
}
2876-
28772854
/// DO NOT USE IN CONSENSUS CODE. Different nodes can have different blocks for the same
28782855
/// tenure.
28792856
///

stackslib/src/net/relay.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,12 @@ impl Relayer {
24972497
let tx = self.stacker_dbs.tx_begin(config.clone())?;
24982498
for sync_result in sync_results.into_iter() {
24992499
for chunk in sync_result.chunks_to_store.into_iter() {
2500+
if let Some(event_list) = all_events.get_mut(&sync_result.contract_id) {
2501+
event_list.push(chunk.clone());
2502+
} else {
2503+
all_events.insert(sync_result.contract_id.clone(), vec![chunk.clone()]);
2504+
}
2505+
25002506
let md = chunk.get_slot_metadata();
25012507
if let Err(e) = tx.try_replace_chunk(&sc, &md, &chunk.data) {
25022508
if matches!(e, Error::StaleChunk { .. }) {
@@ -2525,11 +2531,6 @@ impl Relayer {
25252531
debug!("Stored chunk"; "stackerdb_contract_id" => %sync_result.contract_id, "slot_id" => md.slot_id, "slot_version" => md.slot_version);
25262532
}
25272533

2528-
if let Some(event_list) = all_events.get_mut(&sync_result.contract_id) {
2529-
event_list.push(chunk.clone());
2530-
} else {
2531-
all_events.insert(sync_result.contract_id.clone(), vec![chunk.clone()]);
2532-
}
25332534
let msg = StacksMessageType::StackerDBPushChunk(StackerDBPushChunkData {
25342535
contract_id: sc.clone(),
25352536
rc_consensus_hash: rc_consensus_hash.clone(),

stackslib/src/net/stackerdb/db.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use stacks_common::util::get_epoch_time_secs;
2525
use stacks_common::util::hash::Sha512Trunc256Sum;
2626
use stacks_common::util::secp256k1::MessageSignature;
2727

28-
use super::StackerDBEventDispatcher;
2928
use crate::net::stackerdb::{StackerDBConfig, StackerDBTx, StackerDBs, STACKERDB_INV_MAX};
3029
use crate::net::{Error as net_error, StackerDBChunkData};
3130
use crate::util_lib::db::{
@@ -396,20 +395,6 @@ impl StackerDBTx<'_> {
396395
Ok(())
397396
}
398397

399-
/// Try to upload a chunk to the StackerDB instance, notifying
400-
/// and subscribed listeners via the `dispatcher`
401-
pub fn put_chunk<ED: StackerDBEventDispatcher>(
402-
self,
403-
contract: &QualifiedContractIdentifier,
404-
chunk: StackerDBChunkData,
405-
dispatcher: &ED,
406-
) -> Result<(), net_error> {
407-
self.try_replace_chunk(contract, &chunk.get_slot_metadata(), &chunk.data)?;
408-
self.commit()?;
409-
dispatcher.new_stackerdb_chunks(contract.clone(), vec![chunk]);
410-
Ok(())
411-
}
412-
413398
/// Add or replace a chunk for a given reward cycle, if it is valid
414399
/// Otherwise, this errors out with Error::StaleChunk
415400
pub fn try_replace_chunk(

testnet/stacks-node/src/nakamoto_node/signer_coordinator.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,9 @@ impl SignerCoordinator {
420420

421421
// Check if a new Stacks block has arrived in the parent tenure
422422
let highest_in_tenure =
423-
NakamotoChainState::get_highest_known_block_header_in_tenure(
424-
&mut chain_state.index_conn(),
423+
NakamotoChainState::find_highest_known_block_header_in_tenure(
424+
&chain_state,
425+
&sortdb,
425426
&parent_tenure_header.consensus_hash,
426427
)?
427428
.ok_or(NakamotoNodeError::UnexpectedChainState)?;
@@ -436,7 +437,10 @@ impl SignerCoordinator {
436437
};
437438
return Ok(stored_block.signer_signature);
438439
} else if highest_stacks_block_id != parent_block_id {
439-
info!("SignCoordinator: Exiting due to new stacks tip");
440+
info!("SignCoordinator: Exiting due to new stacks tip";
441+
"new_block_hash" => %highest_in_tenure.anchored_header.block_hash(),
442+
"new_block_height" => %highest_in_tenure.anchored_header.height(),
443+
);
440444
return Err(NakamotoNodeError::StacksTipChanged);
441445
}
442446

0 commit comments

Comments
 (0)