Skip to content

Commit 24b2d84

Browse files
committed
fix: remove deadlock condition between p2p and relayer threads that could arise when they both try to read the reward set. In short -- don't use a StacksDBTx<'a> to read chainstate when a StacksDBConn<'a> will do. Patch the relevant files to make it so the offending code can take a StacksDBIndexed trait impl instead of a transaction.
1 parent 06efc09 commit 24b2d84

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

stackslib/src/chainstate/nakamoto/coordinator/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ impl<'a, T: BlockEventDispatcher> OnChainRewardSetProvider<'a, T> {
188188
debug_log: bool,
189189
) -> Result<RewardSet, Error> {
190190
let Some(reward_set_block) = NakamotoChainState::get_header_by_coinbase_height(
191-
&mut chainstate.index_tx_begin(),
191+
&mut chainstate.index_conn(),
192192
block_id,
193193
coinbase_height_of_calculation,
194194
)?

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ pub trait StacksDBIndexed {
300300
fn get(&mut self, tip: &StacksBlockId, key: &str) -> Result<Option<String>, DBError>;
301301
fn sqlite(&self) -> &Connection;
302302

303+
/// Get the ancestor block hash given a height
304+
fn get_ancestor_block_id(
305+
&mut self,
306+
coinbase_height: u64,
307+
tip_index_hash: &StacksBlockId,
308+
) -> Result<Option<StacksBlockId>, DBError>;
309+
303310
/// Get the block ID for a specific coinbase height in the fork identified by `tip`
304311
fn get_nakamoto_block_id_at_coinbase_height(
305312
&mut self,
@@ -452,6 +459,14 @@ impl StacksDBIndexed for StacksDBConn<'_> {
452459
fn sqlite(&self) -> &Connection {
453460
self.conn()
454461
}
462+
463+
fn get_ancestor_block_id(
464+
&mut self,
465+
coinbase_height: u64,
466+
tip_index_hash: &StacksBlockId,
467+
) -> Result<Option<StacksBlockId>, DBError> {
468+
self.get_ancestor_block_hash(coinbase_height, tip_index_hash)
469+
}
455470
}
456471

457472
impl StacksDBIndexed for StacksDBTx<'_> {
@@ -462,6 +477,14 @@ impl StacksDBIndexed for StacksDBTx<'_> {
462477
fn sqlite(&self) -> &Connection {
463478
self.tx().deref()
464479
}
480+
481+
fn get_ancestor_block_id(
482+
&mut self,
483+
coinbase_height: u64,
484+
tip_index_hash: &StacksBlockId,
485+
) -> Result<Option<StacksBlockId>, DBError> {
486+
self.get_ancestor_block_hash(coinbase_height, tip_index_hash)
487+
}
465488
}
466489

467490
impl<'a> ChainstateTx<'a> {
@@ -2406,22 +2429,22 @@ impl NakamotoChainState {
24062429
/// Return a Nakamoto StacksHeaderInfo at a given coinbase height in the fork identified by `tip_index_hash`.
24072430
/// * For Stacks 2.x, this is the Stacks block's header
24082431
/// * For Stacks 3.x (Nakamoto), this is the first block in the miner's tenure.
2409-
pub fn get_header_by_coinbase_height(
2410-
tx: &mut StacksDBTx,
2432+
pub fn get_header_by_coinbase_height<SDBI: StacksDBIndexed>(
2433+
conn: &mut SDBI,
24112434
tip_index_hash: &StacksBlockId,
24122435
coinbase_height: u64,
24132436
) -> Result<Option<StacksHeaderInfo>, ChainstateError> {
24142437
// nakamoto block?
24152438
if let Some(block_id) =
2416-
tx.get_nakamoto_block_id_at_coinbase_height(tip_index_hash, coinbase_height)?
2439+
conn.get_nakamoto_block_id_at_coinbase_height(tip_index_hash, coinbase_height)?
24172440
{
2418-
return Self::get_block_header_nakamoto(tx.sqlite(), &block_id);
2441+
return Self::get_block_header_nakamoto(conn.sqlite(), &block_id);
24192442
}
24202443

24212444
// epcoh2 block?
2422-
let Some(ancestor_at_height) = tx
2423-
.get_ancestor_block_hash(coinbase_height, tip_index_hash)?
2424-
.map(|ancestor| Self::get_block_header(tx.tx(), &ancestor))
2445+
let Some(ancestor_at_height) = conn
2446+
.get_ancestor_block_id(coinbase_height, tip_index_hash)?
2447+
.map(|ancestor| Self::get_block_header(conn.sqlite(), &ancestor))
24252448
.transpose()?
24262449
.flatten()
24272450
else {

stackslib/src/chainstate/nakamoto/tenure.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ impl NakamotoChainState {
372372

373373
let matured_coinbase_height = coinbase_height - MINER_REWARD_MATURITY;
374374
let matured_tenure_block_header = Self::get_header_by_coinbase_height(
375-
chainstate_tx,
375+
chainstate_tx.deref_mut(),
376376
&tip_index_hash,
377377
matured_coinbase_height,
378378
)?
@@ -964,7 +964,7 @@ impl NakamotoChainState {
964964

965965
let total_coinbase = coinbase_at_block.saturating_add(accumulated_rewards);
966966
let parent_tenure_start_header: StacksHeaderInfo = Self::get_header_by_coinbase_height(
967-
chainstate_tx,
967+
chainstate_tx.deref_mut(),
968968
&block.header.parent_block_id,
969969
parent_coinbase_height,
970970
)?

0 commit comments

Comments
 (0)