Skip to content

Commit e8b50f7

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feat/fork-detection-state-machine
2 parents 5a3aa0e + e45867c commit e8b50f7

File tree

7 files changed

+156
-146
lines changed

7 files changed

+156
-146
lines changed

.github/CODEOWNERS

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# These owners will be the default owners for everything in
2+
# the repo. Unless a later match takes precedence,
3+
#
4+
# require both blockchain-team-codeowners and blockchain-team to review all PR's not specifically matched below
5+
* @stacks-network/blockchain-team-codeowners @stacks-network/blockchain-team
6+
7+
8+
# Signer code
9+
# require both blockchain-team-codeowners and blockchain-team-signer to review PR's for the signer folder(s)
10+
libsigner/**/*.rs @stacks-network/blockchain-team-codeowners @stacks-network/blockchain-team-signer
11+
stacks-signer/**/*.rs @stacks-network/blockchain-team-codeowners @stacks-network/blockchain-team-signer
12+
13+
# CI workflows
14+
# require both blockchain-team and blockchain-team-ci teams to review PR's modifying CI workflows
15+
/.github/workflows/ @stacks-network/blockchain-team @stacks-network/blockchain-team-ci
16+
/.github/actions/ @stacks-network/blockchain-team @stacks-network/blockchain-team-ci

CODEOWNERS

Lines changed: 0 additions & 20 deletions
This file was deleted.

stacks-signer/src/v0/signer.rs

Lines changed: 51 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -409,13 +409,8 @@ impl Signer {
409409
block_response,
410410
sortition_state,
411411
),
412-
SignerMessage::StateMachineUpdate(update) => {
413-
self.handle_state_machine_update(
414-
signer_public_key,
415-
update,
416-
received_time,
417-
);
418-
}
412+
SignerMessage::StateMachineUpdate(update) => self
413+
.handle_state_machine_update(signer_public_key, update, received_time),
419414
_ => {}
420415
}
421416
}
@@ -676,22 +671,43 @@ impl Signer {
676671

677672
/// The actual `send_block_response` implementation. Declared so that we do
678673
/// not need to duplicate in testing.
679-
fn impl_send_block_response(&mut self, block_response: BlockResponse) {
680-
let res = self
674+
fn impl_send_block_response(
675+
&mut self,
676+
block: Option<&NakamotoBlock>,
677+
block_response: BlockResponse,
678+
) {
679+
info!(
680+
"{self}: Broadcasting a block response to stacks node: {block_response:?}";
681+
);
682+
let accepted = matches!(block_response, BlockResponse::Accepted(..));
683+
match self
681684
.stackerdb
682-
.send_message_with_retry::<SignerMessage>(block_response.clone().into());
683-
match res {
684-
Err(e) => warn!("{self}: Failed to send block rejection to stacker-db: {e:?}"),
685-
Ok(ack) if !ack.accepted => warn!(
686-
"{self}: Block rejection not accepted by stacker-db: {:?}",
687-
ack.reason
688-
),
689-
Ok(_) => debug!("{self}: Block rejection accepted by stacker-db"),
685+
.send_message_with_retry::<SignerMessage>(block_response.into())
686+
{
687+
Ok(ack) => {
688+
if !ack.accepted {
689+
warn!(
690+
"{self}: Block response not accepted by stacker-db: {:?}",
691+
ack.reason
692+
);
693+
}
694+
crate::monitoring::actions::increment_block_responses_sent(accepted);
695+
if let Some(block) = block {
696+
crate::monitoring::actions::record_block_response_latency(block);
697+
}
698+
}
699+
Err(e) => {
700+
warn!("{self}: Failed to send block response to stacker-db: {e:?}",);
701+
}
690702
}
691703
}
692704

693705
#[cfg(any(test, feature = "testing"))]
694-
fn send_block_response(&mut self, block_response: BlockResponse) {
706+
fn send_block_response(
707+
&mut self,
708+
block: Option<&NakamotoBlock>,
709+
block_response: BlockResponse,
710+
) {
695711
const NUM_REPEATS: usize = 1;
696712
let mut count = 0;
697713
let public_keys = TEST_REPEAT_PROPOSAL_RESPONSE.get();
@@ -701,16 +717,20 @@ impl Signer {
701717
count = NUM_REPEATS;
702718
}
703719
while count <= NUM_REPEATS {
704-
self.impl_send_block_response(block_response.clone());
720+
self.impl_send_block_response(block, block_response.clone());
705721

706722
count += 1;
707723
sleep_ms(1000);
708724
}
709725
}
710726

711727
#[cfg(not(any(test, feature = "testing")))]
712-
fn send_block_response(&mut self, block_response: BlockResponse) {
713-
self.impl_send_block_response(block_response)
728+
fn send_block_response(
729+
&mut self,
730+
block: Option<&NakamotoBlock>,
731+
block_response: BlockResponse,
732+
) {
733+
self.impl_send_block_response(block, block_response)
714734
}
715735

716736
/// Handle signer state update message
@@ -840,8 +860,7 @@ impl Signer {
840860

841861
if let Some(block_response) = block_response {
842862
// We know proposal is invalid. Send rejection message, do not do further validation and do not store it.
843-
debug!("{self}: Broadcasting a block response to stacks node: {block_response:?}");
844-
self.send_block_response(block_response);
863+
self.send_block_response(Some(&block_info.block), block_response);
845864
} else {
846865
// Just in case check if the last block validation submission timed out.
847866
self.check_submitted_block_proposal();
@@ -895,19 +914,7 @@ impl Signer {
895914
return;
896915
};
897916

898-
// Submit a proposal response to the .signers contract for miners
899-
debug!("{self}: Broadcasting a block response to stacks node: {block_response:?}");
900-
901-
let accepted = matches!(block_response, BlockResponse::Accepted(..));
902-
if let Err(e) = self
903-
.stackerdb
904-
.send_message_with_retry::<SignerMessage>(block_response.into())
905-
{
906-
warn!("{self}: Failed to send block response to stacker-db: {e:?}");
907-
} else {
908-
crate::monitoring::actions::increment_block_responses_sent(accepted);
909-
crate::monitoring::actions::record_block_response_latency(&block_info.block);
910-
}
917+
self.impl_send_block_response(Some(&block_info.block), block_response);
911918
}
912919

913920
/// Handle block response messages from a signer
@@ -1043,21 +1050,7 @@ impl Signer {
10431050
warn!("{self}: Failed to mark block as locally rejected: {e:?}");
10441051
}
10451052
};
1046-
debug!("{self}: Broadcasting a block response to stacks node: {block_response:?}");
1047-
let res = self
1048-
.stackerdb
1049-
.send_message_with_retry::<SignerMessage>(block_response.into());
1050-
1051-
crate::monitoring::actions::record_block_response_latency(&block_info.block);
1052-
1053-
match res {
1054-
Err(e) => warn!("{self}: Failed to send block rejection to stacker-db: {e:?}"),
1055-
Ok(ack) if !ack.accepted => warn!(
1056-
"{self}: Block rejection not accepted by stacker-db: {:?}",
1057-
ack.reason
1058-
),
1059-
Ok(_) => debug!("{self}: Block rejection accepted by stacker-db"),
1060-
}
1053+
self.impl_send_block_response(Some(&block_info.block), block_response);
10611054
self.signer_db
10621055
.insert_block(&block_info)
10631056
.unwrap_or_else(|e| self.handle_insert_block_error(e));
@@ -1164,30 +1157,12 @@ impl Signer {
11641157
.unwrap_or_else(|e| warn!("{self}: Failed to remove pending block validation: {e:?}"));
11651158

11661159
if let Some(response) = block_response {
1167-
// Submit a proposal response to the .signers contract for miners
1168-
info!(
1169-
"{self}: Broadcasting a block response to stacks node: {response:?}";
1170-
);
1171-
let accepted = matches!(response, BlockResponse::Accepted(..));
1172-
match self
1173-
.stackerdb
1174-
.send_message_with_retry::<SignerMessage>(response.into())
1175-
{
1176-
Ok(_) => {
1177-
crate::monitoring::actions::increment_block_responses_sent(accepted);
1178-
if let Ok(Some(block_info)) = self
1179-
.signer_db
1180-
.block_lookup(&block_validate_response.signer_signature_hash())
1181-
{
1182-
crate::monitoring::actions::record_block_response_latency(
1183-
&block_info.block,
1184-
);
1185-
}
1186-
}
1187-
Err(e) => {
1188-
warn!("{self}: Failed to send block rejection to stacker-db: {e:?}",);
1189-
}
1190-
}
1160+
let block = self
1161+
.signer_db
1162+
.block_lookup(&signer_sig_hash)
1163+
.unwrap_or_default()
1164+
.map(|info| info.block);
1165+
self.impl_send_block_response(block.as_ref(), response);
11911166
};
11921167

11931168
// Check if there is a pending block validation that we need to submit to the node
@@ -1280,21 +1255,7 @@ impl Signer {
12801255
warn!("{self}: Failed to mark block as locally rejected: {e:?}");
12811256
}
12821257
};
1283-
debug!("{self}: Broadcasting a block response to stacks node: {rejection:?}");
1284-
let res = self
1285-
.stackerdb
1286-
.send_message_with_retry::<SignerMessage>(rejection.into());
1287-
1288-
crate::monitoring::actions::record_block_response_latency(&block_info.block);
1289-
1290-
match res {
1291-
Err(e) => warn!("{self}: Failed to send block rejection to stacker-db: {e:?}"),
1292-
Ok(ack) if !ack.accepted => warn!(
1293-
"{self}: Block rejection not accepted by stacker-db: {:?}",
1294-
ack.reason
1295-
),
1296-
Ok(_) => debug!("{self}: Block rejection accepted by stacker-db"),
1297-
}
1258+
self.impl_send_block_response(Some(&block_info.block), rejection);
12981259

12991260
self.signer_db
13001261
.insert_block(&block_info)

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

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,13 +1264,25 @@ impl<'a> SortitionHandleTx<'a> {
12641264
burn_header_hash: &BurnchainHeaderHash,
12651265
chain_tip: &SortitionId,
12661266
) -> Result<Option<BlockSnapshot>, db_error> {
1267+
let Some(sortition_id) = self.get_sortition_id_for_bhh(burn_header_hash, chain_tip)? else {
1268+
return Ok(None);
1269+
};
1270+
1271+
SortitionDB::get_block_snapshot(self.tx(), &sortition_id)
1272+
}
1273+
1274+
fn get_sortition_id_for_bhh(
1275+
&mut self,
1276+
burn_header_hash: &BurnchainHeaderHash,
1277+
chain_tip: &SortitionId,
1278+
) -> Result<Option<SortitionId>, db_error> {
12671279
let sortition_identifier_key = db_keys::sortition_id_for_bhh(burn_header_hash);
12681280
let sortition_id = match self.get_indexed(chain_tip, &sortition_identifier_key)? {
12691281
None => return Ok(None),
12701282
Some(x) => SortitionId::from_hex(&x).expect("FATAL: bad Sortition ID stored in DB"),
12711283
};
12721284

1273-
SortitionDB::get_block_snapshot(self.tx(), &sortition_id)
1285+
Ok(Some(sortition_id))
12741286
}
12751287

12761288
/// Get a leader key at a specific location in the burn chain's fork history, given the
@@ -6528,25 +6540,25 @@ impl SortitionHandleTx<'_> {
65286540
}
65296541

65306542
// must be an ancestor of this tip, or must be this tip
6531-
if let Some(sn) =
6532-
self.get_block_snapshot(&arrival_sn.burn_header_hash, &parent_tip.sortition_id)?
6543+
if let Some(sortition_id) = self
6544+
.get_sortition_id_for_bhh(&arrival_sn.burn_header_hash, &parent_tip.sortition_id)?
65336545
{
6534-
if !sn.pox_valid || sn != arrival_sn {
6546+
if sortition_id != arrival_sn.sortition_id {
65356547
continue;
65366548
}
65376549

65386550
debug!(
65396551
"New Stacks anchored block arrived: block {}/{} ({}) ari={} tip={}",
6540-
&sn.consensus_hash,
6541-
&sn.winning_stacks_block_hash,
6542-
sn.stacks_block_height,
6552+
&arrival_sn.consensus_hash,
6553+
&arrival_sn.winning_stacks_block_hash,
6554+
arrival_sn.stacks_block_height,
65436555
ari,
65446556
&parent_tip.burn_header_hash
65456557
);
65466558
new_block_arrivals.push((
6547-
sn.consensus_hash,
6548-
sn.winning_stacks_block_hash,
6549-
sn.stacks_block_height,
6559+
arrival_sn.consensus_hash,
6560+
arrival_sn.winning_stacks_block_hash,
6561+
arrival_sn.stacks_block_height,
65506562
));
65516563
} else {
65526564
// this block did not arrive on an ancestor block

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

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -294,15 +294,15 @@ impl DBConfig {
294294
});
295295
match epoch_id {
296296
StacksEpochId::Epoch10 => true,
297-
StacksEpochId::Epoch20 => version_u32 >= 1 && version_u32 <= 8,
298-
StacksEpochId::Epoch2_05 => version_u32 >= 2 && version_u32 <= 8,
299-
StacksEpochId::Epoch21 => version_u32 >= 3 && version_u32 <= 8,
300-
StacksEpochId::Epoch22 => version_u32 >= 3 && version_u32 <= 8,
301-
StacksEpochId::Epoch23 => version_u32 >= 3 && version_u32 <= 8,
302-
StacksEpochId::Epoch24 => version_u32 >= 3 && version_u32 <= 8,
303-
StacksEpochId::Epoch25 => version_u32 >= 3 && version_u32 <= 8,
304-
StacksEpochId::Epoch30 => version_u32 >= 3 && version_u32 <= 8,
305-
StacksEpochId::Epoch31 => version_u32 >= 3 && version_u32 <= 8,
297+
StacksEpochId::Epoch20 => version_u32 >= 1 && version_u32 <= 9,
298+
StacksEpochId::Epoch2_05 => version_u32 >= 2 && version_u32 <= 9,
299+
StacksEpochId::Epoch21 => version_u32 >= 3 && version_u32 <= 9,
300+
StacksEpochId::Epoch22 => version_u32 >= 3 && version_u32 <= 9,
301+
StacksEpochId::Epoch23 => version_u32 >= 3 && version_u32 <= 9,
302+
StacksEpochId::Epoch24 => version_u32 >= 3 && version_u32 <= 9,
303+
StacksEpochId::Epoch25 => version_u32 >= 3 && version_u32 <= 9,
304+
StacksEpochId::Epoch30 => version_u32 >= 3 && version_u32 <= 9,
305+
StacksEpochId::Epoch31 => version_u32 >= 3 && version_u32 <= 9,
306306
}
307307
}
308308
}
@@ -654,7 +654,7 @@ impl<'a> DerefMut for ChainstateTx<'a> {
654654
}
655655
}
656656

657-
pub const CHAINSTATE_VERSION: &str = "8";
657+
pub const CHAINSTATE_VERSION: &str = "9";
658658

659659
const CHAINSTATE_INITIAL_SCHEMA: &[&str] = &[
660660
"PRAGMA foreign_keys = ON;",
@@ -853,6 +853,15 @@ const CHAINSTATE_SCHEMA_3: &[&str] = &[
853853
"#,
854854
];
855855

856+
const CHAINSTATE_SCHEMA_4: &[&str] = &[
857+
// schema change is JUST a new index, so just bump db_config.version
858+
// and add the index to `CHAINSTATE_INDEXES` (which gets re-execed
859+
// on every schema change)
860+
r#"
861+
UPDATE db_config SET version = "9";
862+
"#,
863+
];
864+
856865
const CHAINSTATE_INDEXES: &[&str] = &[
857866
"CREATE INDEX IF NOT EXISTS index_block_hash_to_primary_key ON block_headers(index_block_hash,consensus_hash,block_hash);",
858867
"CREATE INDEX IF NOT EXISTS block_headers_hash_index ON block_headers(block_hash,block_height);",
@@ -877,6 +886,7 @@ const CHAINSTATE_INDEXES: &[&str] = &[
877886
"CREATE INDEX IF NOT EXISTS index_block_header_by_affirmation_weight ON block_headers(affirmation_weight);",
878887
"CREATE INDEX IF NOT EXISTS index_block_header_by_height_and_affirmation_weight ON block_headers(block_height,affirmation_weight);",
879888
"CREATE INDEX IF NOT EXISTS index_headers_by_consensus_hash ON block_headers(consensus_hash);",
889+
"CREATE INDEX IF NOT EXISTS processable_block ON staging_blocks(processed, orphaned, attachable);",
880890
];
881891

882892
pub use stacks_common::consts::MINER_REWARD_MATURITY;
@@ -1104,6 +1114,14 @@ impl StacksChainState {
11041114
tx.execute_batch(cmd)?;
11051115
}
11061116
}
1117+
"8" => {
1118+
info!(
1119+
"Migrating chainstate schema from version 8 to 9: add index for staging_blocks"
1120+
);
1121+
for cmd in CHAINSTATE_SCHEMA_4.iter() {
1122+
tx.execute_batch(cmd)?;
1123+
}
1124+
}
11071125
_ => {
11081126
error!(
11091127
"Invalid chain state database: expected version = {}, got {}",

0 commit comments

Comments
 (0)