Skip to content

Commit 7762d88

Browse files
authored
Merge pull request #6585 from jferrant/chore/limit-staging-blocks-db-access
Make access to Nakamoto staging blocks restricted to one single pub fn
2 parents dfc17c4 + 61c819a commit 7762d88

File tree

7 files changed

+163
-174
lines changed

7 files changed

+163
-174
lines changed

stacks-node/src/nakamoto_node/miner.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,18 +1029,13 @@ impl BlockMinerThread {
10291029
let burn_view_ch =
10301030
NakamotoChainState::get_block_burn_view(sort_db, block, &parent_block_info)?;
10311031
let mut sortition_handle = sort_db.index_handle_at_ch(&burn_view_ch)?;
1032-
let chainstate_config = chain_state.config();
1033-
let (headers_conn, staging_tx) = chain_state.headers_conn_and_staging_tx_begin()?;
10341032
let accepted = NakamotoChainState::accept_block(
1035-
&chainstate_config,
1033+
chain_state,
10361034
block,
10371035
&mut sortition_handle,
1038-
&staging_tx,
1039-
headers_conn,
10401036
reward_set,
10411037
NakamotoBlockObtainMethod::Mined,
10421038
)?;
1043-
staging_tx.commit()?;
10441039

10451040
if !accepted {
10461041
// this can happen if the p2p network and relayer manage to receive this block prior to

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 5 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,76 +2391,6 @@ impl NakamotoChainState {
23912391
Ok(())
23922392
}
23932393

2394-
/// Insert a Nakamoto block into the staging blocks DB.
2395-
/// We only store a block in the following cases:
2396-
///
2397-
/// * No block with this block's sighash exists in the DB
2398-
/// * A block with this block's sighash exists, AND
2399-
/// * this block represents more signing power
2400-
///
2401-
/// If neither of the above is true, then this is a no-op.
2402-
pub(crate) fn store_block_if_better(
2403-
staging_db_tx: &NakamotoStagingBlocksTx,
2404-
block: &NakamotoBlock,
2405-
burn_attachable: bool,
2406-
signing_weight: u32,
2407-
obtain_method: NakamotoBlockObtainMethod,
2408-
) -> Result<bool, ChainstateError> {
2409-
let block_id = block.block_id();
2410-
let block_hash = block.header.block_hash();
2411-
2412-
// case 1 -- no block with this sighash exists.
2413-
if staging_db_tx.try_store_block_with_new_signer_sighash(
2414-
block,
2415-
burn_attachable,
2416-
signing_weight,
2417-
obtain_method,
2418-
)? {
2419-
debug!("Stored block with new sighash";
2420-
"block_id" => %block_id,
2421-
"block_hash" => %block_hash);
2422-
return Ok(true);
2423-
}
2424-
2425-
// case 2 -- the block exists. Consider replacing it, but only if its
2426-
// signing weight is higher.
2427-
let (existing_block_id, _processed, orphaned, existing_signing_weight) = staging_db_tx.conn().get_block_processed_and_signed_weight(&block.header.consensus_hash, &block_hash)?
2428-
.ok_or_else(|| {
2429-
// this should be unreachable -- there's no record of this block
2430-
error!("Could not store block {} ({}) with block hash {} -- no record of its processed status or signing weight!", &block_id, &block.header.consensus_hash, &block_hash);
2431-
ChainstateError::NoSuchBlockError
2432-
})?;
2433-
2434-
if orphaned {
2435-
// nothing to do
2436-
debug!("Will not store alternative copy of block {} ({}) with block hash {}, since a block with the same block hash was orphaned", &block_id, &block.header.consensus_hash, &block_hash);
2437-
return Ok(false);
2438-
}
2439-
2440-
let ret = if existing_signing_weight < signing_weight {
2441-
staging_db_tx.replace_block(block, signing_weight, obtain_method)?;
2442-
debug!("Replaced block";
2443-
"existing_block_id" => %existing_block_id,
2444-
"block_id" => %block_id,
2445-
"block_hash" => %block_hash,
2446-
"existing_signing_weight" => existing_signing_weight,
2447-
"signing_weight" => signing_weight);
2448-
true
2449-
} else {
2450-
if existing_signing_weight > signing_weight {
2451-
debug!("Will not store alternative copy of block {} ({}) with block hash {}, since it has less signing power", &block_id, &block.header.consensus_hash, &block_hash);
2452-
} else {
2453-
debug!(
2454-
"Will not store duplicate copy of block {} ({}) with block hash {}",
2455-
&block_id, &block.header.consensus_hash, &block_hash
2456-
);
2457-
}
2458-
false
2459-
};
2460-
2461-
return Ok(ret);
2462-
}
2463-
24642394
/// Accept a Nakamoto block into the staging blocks DB.
24652395
/// Fails if:
24662396
/// * the public key cannot be recovered from the miner's signature
@@ -2470,17 +2400,17 @@ impl NakamotoChainState {
24702400
/// * we already have the block
24712401
/// Returns true if we stored the block; false if not.
24722402
pub fn accept_block(
2473-
config: &ChainstateConfig,
2403+
chainstate: &mut StacksChainState,
24742404
block: &NakamotoBlock,
24752405
db_handle: &mut SortitionHandleConn,
2476-
staging_db_tx: &NakamotoStagingBlocksTx,
2477-
headers_conn: &Connection,
24782406
reward_set: &RewardSet,
24792407
obtain_method: NakamotoBlockObtainMethod,
24802408
) -> Result<bool, ChainstateError> {
24812409
let block_id = block.block_id();
24822410
test_debug!("Consider Nakamoto block {block_id}");
2411+
let config = chainstate.config();
24832412
// do nothing if we already have this block
2413+
let (headers_conn, staging_db_tx) = chainstate.headers_conn_and_staging_tx_begin()?;
24842414
if Self::get_block_header(headers_conn, &block_id)?.is_some() {
24852415
debug!("Already have block {block_id}");
24862416
return Ok(false);
@@ -2555,13 +2485,13 @@ impl NakamotoChainState {
25552485
// same sortition history as `db_handle` (and thus it must be burn_attachable)
25562486
let burn_attachable = true;
25572487

2558-
let ret = Self::store_block_if_better(
2559-
staging_db_tx,
2488+
let ret = staging_db_tx.store_block_if_better(
25602489
block,
25612490
burn_attachable,
25622491
signing_weight,
25632492
obtain_method,
25642493
)?;
2494+
staging_db_tx.commit()?;
25652495
if ret {
25662496
test_debug!("Stored Nakamoto block {block_id}");
25672497
} else {

stackslib/src/chainstate/nakamoto/shadow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ impl NakamotoStagingBlocksTx<'_> {
865865
// shadow blocks cannot be replaced
866866
let signing_weight = u32::MAX;
867867

868-
self.store_block(
868+
self.store_block_if_better(
869869
shadow_block,
870870
burn_attachable,
871871
signing_weight,

stackslib/src/chainstate/nakamoto/staging_blocks.rs

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,81 @@ impl NakamotoStagingBlocksTx<'_> {
590590
Ok(())
591591
}
592592

593+
/// Insert a Nakamoto block into the staging blocks DB.
594+
/// We only store a block in the following cases:
595+
///
596+
/// * No block with this block's sighash exists in the DB
597+
/// * A block with this block's sighash exists, AND
598+
/// * this block represents more signing power
599+
///
600+
/// If neither of the above is true, then this is a no-op.
601+
/// NOTE: This is intentionally the only public access into
602+
/// storing additional blocks inside the staging blocks DB
603+
pub fn store_block_if_better(
604+
&self,
605+
block: &NakamotoBlock,
606+
burn_attachable: bool,
607+
signing_weight: u32,
608+
obtain_method: NakamotoBlockObtainMethod,
609+
) -> Result<bool, ChainstateError> {
610+
let block_id = block.block_id();
611+
let block_hash = block.header.block_hash();
612+
let consensus_hash = block.header.consensus_hash.clone();
613+
614+
// case 1 -- no block with this sighash exists.
615+
if self.try_store_block_with_new_signer_sighash(
616+
block,
617+
burn_attachable,
618+
signing_weight,
619+
obtain_method,
620+
)? {
621+
debug!("Stored block with new sighash";
622+
"block_id" => %block_id,
623+
"block_hash" => %block_hash);
624+
return Ok(true);
625+
}
626+
627+
// case 2 -- the block exists. Consider replacing it, but only if its
628+
// signing weight is higher.
629+
let (existing_block_id, _processed, orphaned, existing_signing_weight) = self.conn().get_block_processed_and_signed_weight(&consensus_hash, &block_hash)?
630+
.ok_or_else(|| {
631+
// this should be unreachable -- there's no record of this block
632+
error!("Could not store block {block_id} ({consensus_hash}) with block hash {block_hash} -- no record of its processed status or signing weight!");
633+
ChainstateError::NoSuchBlockError
634+
})?;
635+
636+
if orphaned {
637+
// nothing to do
638+
debug!("Will not store alternative copy of block {block_id} ({consensus_hash}) with block hash {block_hash}, since a block with the same block hash was orphaned");
639+
return Ok(false);
640+
}
641+
642+
let ret = if existing_signing_weight < signing_weight {
643+
self.replace_block(block, signing_weight, obtain_method)?;
644+
debug!("Replaced block";
645+
"existing_block_id" => %existing_block_id,
646+
"block_id" => %block_id,
647+
"block_hash" => %block_hash,
648+
"existing_signing_weight" => existing_signing_weight,
649+
"signing_weight" => signing_weight);
650+
true
651+
} else {
652+
if existing_signing_weight > signing_weight {
653+
debug!("Will not store alternative copy of block {block_id} ({consensus_hash}) with block hash {block_hash}, since it has less signing power");
654+
} else {
655+
debug!(
656+
"Will not store duplicate copy of block {block_id} ({consensus_hash}) with block hash {block_hash}"
657+
);
658+
}
659+
false
660+
};
661+
662+
Ok(ret)
663+
}
664+
593665
/// Store a block into the staging DB.
594-
pub(crate) fn store_block(
666+
/// NOTE: This should not be made public
667+
fn store_block(
595668
&self,
596669
block: &NakamotoBlock,
597670
burn_attachable: bool,
@@ -665,7 +738,7 @@ impl NakamotoStagingBlocksTx<'_> {
665738

666739
/// Do we have a block with the given signer sighash?
667740
/// NOTE: the block hash and sighash are the same for Nakamoto blocks
668-
pub(crate) fn has_nakamoto_block_with_block_hash(
741+
fn has_nakamoto_block_with_block_hash(
669742
&self,
670743
consensus_hash: &ConsensusHash,
671744
block_hash: &BlockHeaderHash,
@@ -681,7 +754,8 @@ impl NakamotoStagingBlocksTx<'_> {
681754
/// NOTE: the block hash and sighash are the same for Nakamoto blocks, so this is equivalent to
682755
/// storing a new block.
683756
/// Return true if stored; false if not.
684-
pub(crate) fn try_store_block_with_new_signer_sighash(
757+
/// NOTE: This should not be made public
758+
fn try_store_block_with_new_signer_sighash(
685759
&self,
686760
block: &NakamotoBlock,
687761
burn_attachable: bool,
@@ -698,7 +772,8 @@ impl NakamotoStagingBlocksTx<'_> {
698772

699773
/// Replace an already-stored block with a newer copy with more signing
700774
/// power. Arguments will not be validated; the caller must do this.
701-
pub(crate) fn replace_block(
775+
/// NOTE: This should not be made public
776+
fn replace_block(
702777
&self,
703778
block: &NakamotoBlock,
704779
signing_weight: u32,

0 commit comments

Comments
 (0)