Skip to content

Commit 0d850da

Browse files
authored
Merge pull request #4893 from stacks-network/fix/miner-ignores-noncanonical-2.5.0.0.4
Fix: never consider Stacks chain tips that are not on the canonical burn chain #4886
2 parents cfffe55 + 2d7f8ed commit 0d850da

File tree

1 file changed

+73
-48
lines changed

1 file changed

+73
-48
lines changed

testnet/stacks-node/src/neon_node.rs

Lines changed: 73 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier};
153153
use stacks::burnchains::bitcoin::address::{BitcoinAddress, LegacyBitcoinAddressType};
154154
use stacks::burnchains::db::BurnchainHeaderReader;
155155
use stacks::burnchains::{Burnchain, BurnchainSigner, PoxConstants, Txid};
156-
use stacks::chainstate::burn::db::sortdb::SortitionDB;
156+
use stacks::chainstate::burn::db::sortdb::{SortitionDB, SortitionHandleConn};
157157
use stacks::chainstate::burn::operations::leader_block_commit::{
158158
RewardSetInfo, BURN_BLOCK_MINED_AT_MODULUS,
159159
};
@@ -1144,6 +1144,50 @@ impl BlockMinerThread {
11441144
ret
11451145
}
11461146

1147+
/// Is a given Stacks staging block on the canonical burnchain fork?
1148+
pub(crate) fn is_on_canonical_burnchain_fork(
1149+
candidate: &StagingBlock,
1150+
sortdb_tip_handle: &SortitionHandleConn,
1151+
) -> bool {
1152+
let candidate_ch = &candidate.consensus_hash;
1153+
let candidate_burn_ht = match SortitionDB::get_block_snapshot_consensus(
1154+
sortdb_tip_handle.conn(),
1155+
candidate_ch,
1156+
) {
1157+
Ok(Some(x)) => x.block_height,
1158+
Ok(None) => {
1159+
warn!("Tried to evaluate potential chain tip with an unknown consensus hash";
1160+
"consensus_hash" => %candidate_ch,
1161+
"stacks_block_hash" => %candidate.anchored_block_hash);
1162+
return false;
1163+
}
1164+
Err(e) => {
1165+
warn!("Error while trying to evaluate potential chain tip with an unknown consensus hash";
1166+
"consensus_hash" => %candidate_ch,
1167+
"stacks_block_hash" => %candidate.anchored_block_hash,
1168+
"err" => ?e);
1169+
return false;
1170+
}
1171+
};
1172+
let tip_ch = match sortdb_tip_handle.get_consensus_at(candidate_burn_ht) {
1173+
Ok(Some(x)) => x,
1174+
Ok(None) => {
1175+
warn!("Tried to evaluate potential chain tip with a consensus hash ahead of canonical tip";
1176+
"consensus_hash" => %candidate_ch,
1177+
"stacks_block_hash" => %candidate.anchored_block_hash);
1178+
return false;
1179+
}
1180+
Err(e) => {
1181+
warn!("Error while trying to evaluate potential chain tip with an unknown consensus hash";
1182+
"consensus_hash" => %candidate_ch,
1183+
"stacks_block_hash" => %candidate.anchored_block_hash,
1184+
"err" => ?e);
1185+
return false;
1186+
}
1187+
};
1188+
&tip_ch == candidate_ch
1189+
}
1190+
11471191
/// Load all candidate tips upon which to build. This is all Stacks blocks whose heights are
11481192
/// less than or equal to at `at_stacks_height` (or the canonical chain tip height, if not given),
11491193
/// but greater than or equal to this end height minus `max_depth`.
@@ -1173,61 +1217,42 @@ impl BlockMinerThread {
11731217

11741218
let stacks_tips: Vec<_> = stacks_tips
11751219
.into_iter()
1176-
.filter(|candidate| {
1177-
let candidate_ch = &candidate.consensus_hash;
1178-
let candidate_burn_ht = match SortitionDB::get_block_snapshot_consensus(
1179-
sortdb_tip_handle.conn(),
1180-
candidate_ch
1181-
) {
1182-
Ok(Some(x)) => x.block_height,
1183-
Ok(None) => {
1184-
warn!("Tried to evaluate potential chain tip with an unknown consensus hash";
1185-
"consensus_hash" => %candidate_ch,
1186-
"stacks_block_hash" => %candidate.anchored_block_hash);
1187-
return false;
1188-
},
1189-
Err(e) => {
1190-
warn!("Error while trying to evaluate potential chain tip with an unknown consensus hash";
1191-
"consensus_hash" => %candidate_ch,
1192-
"stacks_block_hash" => %candidate.anchored_block_hash,
1193-
"err" => ?e);
1194-
return false;
1195-
},
1196-
};
1197-
let tip_ch = match sortdb_tip_handle.get_consensus_at(candidate_burn_ht) {
1198-
Ok(Some(x)) => x,
1199-
Ok(None) => {
1200-
warn!("Tried to evaluate potential chain tip with a consensus hash ahead of canonical tip";
1201-
"consensus_hash" => %candidate_ch,
1202-
"stacks_block_hash" => %candidate.anchored_block_hash);
1203-
return false;
1204-
},
1205-
Err(e) => {
1206-
warn!("Error while trying to evaluate potential chain tip with an unknown consensus hash";
1207-
"consensus_hash" => %candidate_ch,
1208-
"stacks_block_hash" => %candidate.anchored_block_hash,
1209-
"err" => ?e);
1210-
return false;
1211-
},
1212-
};
1213-
if &tip_ch != candidate_ch {
1214-
false
1215-
} else {
1216-
true
1217-
}
1218-
})
1220+
.filter(|candidate| Self::is_on_canonical_burnchain_fork(candidate, &sortdb_tip_handle))
12191221
.collect();
12201222

1223+
if stacks_tips.len() == 0 {
1224+
return vec![];
1225+
}
1226+
12211227
let mut considered = HashSet::new();
12221228
let mut candidates = vec![];
12231229
let end_height = stacks_tips[0].height;
12241230

1225-
for cur_height in end_height.saturating_sub(max_depth)..=end_height {
1226-
let stacks_tips = chain_state
1231+
// process these tips
1232+
for tip in stacks_tips.into_iter() {
1233+
let index_block_hash =
1234+
StacksBlockId::new(&tip.consensus_hash, &tip.anchored_block_hash);
1235+
let burn_height = burn_db
1236+
.get_consensus_hash_height(&tip.consensus_hash)
1237+
.expect("FATAL: could not query burnchain block height")
1238+
.expect("FATAL: no burnchain block height for Stacks tip");
1239+
let candidate = TipCandidate::new(tip, burn_height);
1240+
candidates.push(candidate);
1241+
considered.insert(index_block_hash);
1242+
}
1243+
1244+
// process earlier tips, back to max_depth
1245+
for cur_height in end_height.saturating_sub(max_depth)..end_height {
1246+
let stacks_tips: Vec<_> = chain_state
12271247
.get_stacks_chain_tips_at_height(cur_height)
1228-
.expect("FATAL: could not query chain tips at height");
1248+
.expect("FATAL: could not query chain tips at height")
1249+
.into_iter()
1250+
.filter(|candidate| {
1251+
Self::is_on_canonical_burnchain_fork(candidate, &sortdb_tip_handle)
1252+
})
1253+
.collect();
12291254

1230-
for tip in stacks_tips {
1255+
for tip in stacks_tips.into_iter() {
12311256
let index_block_hash =
12321257
StacksBlockId::new(&tip.consensus_hash, &tip.anchored_block_hash);
12331258

0 commit comments

Comments
 (0)