Skip to content

Commit b54421d

Browse files
committed
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into feat/signer-track-validation-submission-with-config-timeout
2 parents 60bb664 + 7224b9b commit b54421d

File tree

8 files changed

+845
-177
lines changed

8 files changed

+845
-177
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ jobs:
124124
- tests::signer::v0::continue_after_tenure_extend
125125
- tests::signer::v0::multiple_miners_with_custom_chain_id
126126
- tests::signer::v0::block_commit_delay
127+
- tests::signer::v0::continue_after_fast_block_no_sortition
127128
- tests::signer::v0::block_validation_response_timeout
128129
- tests::nakamoto_integrations::burn_ops_integration_test
129130
- tests::nakamoto_integrations::check_block_heights

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1010
### Changed
1111
- Add index for StacksBlockId to nakamoto block headers table (improves node performance)
1212
- Remove the panic for reporting DB deadlocks (just error and continue waiting)
13+
- Add index to `metadata_table` in Clarity DB on `blockhash`
1314
- Add `block_commit_delay_ms` to the config file to control the time to wait after seeing a new burn block, before submitting a block commit, to allow time for the first Nakamoto block of the new tenure to be mined, allowing this miner to avoid the need to RBF the block commit.
1415

1516
## [3.0.0.0.1]
@@ -18,7 +19,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1819
- Add index for StacksBlockId to nakamoto block headers table (improves node performance)
1920
- Remove the panic for reporting DB deadlocks (just error and continue waiting)
2021
- Various test fixes for CI (5353, 5368, 5372, 5371, 5380, 5378, 5387, 5396, 5390, 5394)
21-
- Various log fixes:
22+
- Various log fixes:
2223
- don't say proceeding to mine blocks if not a miner
2324
- misc. warns downgraded to debugs
2425
- 5391: Update default block proposal timeout to 10 minutes

clarity/src/vm/database/sqlite.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ impl SqliteConnection {
248248
)
249249
.map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?;
250250

251+
conn.execute(
252+
"CREATE INDEX IF NOT EXISTS md_blockhashes ON metadata_table(blockhash)",
253+
NO_PARAMS,
254+
)
255+
.map_err(|x| InterpreterError::SqliteError(IncomparableError { err: x }))?;
256+
251257
Self::check_schema(conn)?;
252258

253259
Ok(())

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ pub enum MinerReason {
109109
/// sortition.
110110
burn_view_consensus_hash: ConsensusHash,
111111
},
112+
/// The miner thread was spawned to initialize a prior empty tenure
113+
EmptyTenure,
112114
}
113115

114116
impl std::fmt::Display for MinerReason {
@@ -121,6 +123,7 @@ impl std::fmt::Display for MinerReason {
121123
f,
122124
"Extended: burn_view_consensus_hash = {burn_view_consensus_hash:?}",
123125
),
126+
MinerReason::EmptyTenure => write!(f, "EmptyTenure"),
124127
}
125128
}
126129
}
@@ -921,19 +924,19 @@ impl BlockMinerThread {
921924
let vrf_proof = if self.config.get_node_config(false).mock_mining {
922925
self.keychain.generate_proof(
923926
VRF_MOCK_MINER_KEY,
924-
self.burn_block.sortition_hash.as_bytes(),
927+
self.burn_election_block.sortition_hash.as_bytes(),
925928
)
926929
} else {
927930
self.keychain.generate_proof(
928931
self.registered_key.target_block_height,
929-
self.burn_block.sortition_hash.as_bytes(),
932+
self.burn_election_block.sortition_hash.as_bytes(),
930933
)
931934
};
932935

933936
debug!(
934937
"Generated VRF Proof: {} over {} ({},{}) with key {}",
935938
vrf_proof.to_hex(),
936-
&self.burn_block.sortition_hash,
939+
&self.burn_election_block.sortition_hash,
937940
&self.burn_block.block_height,
938941
&self.burn_block.burn_header_hash,
939942
&self.registered_key.vrf_public_key.to_hex()
@@ -1154,7 +1157,7 @@ impl BlockMinerThread {
11541157
};
11551158

11561159
let (tenure_change_tx, coinbase_tx) = match &self.reason {
1157-
MinerReason::BlockFound => {
1160+
MinerReason::BlockFound | MinerReason::EmptyTenure => {
11581161
let tenure_change_tx =
11591162
self.generate_tenure_change_tx(current_miner_nonce, payload)?;
11601163
let coinbase_tx =

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

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -874,23 +874,14 @@ impl RelayerThread {
874874
SortitionDB::get_canonical_stacks_chain_tip_hash(self.sortdb.conn()).unwrap();
875875
let canonical_stacks_tip =
876876
StacksBlockId::new(&canonical_stacks_tip_ch, &canonical_stacks_tip_bh);
877-
let block_election_snapshot =
878-
SortitionDB::get_block_snapshot_consensus(self.sortdb.conn(), &canonical_stacks_tip_ch)
879-
.map_err(|e| {
880-
error!("Relayer: failed to get block snapshot for canonical tip: {e:?}");
881-
NakamotoNodeError::SnapshotNotFoundForChainTip
882-
})?
883-
.ok_or_else(|| {
884-
error!("Relayer: failed to get block snapshot for canonical tip");
885-
NakamotoNodeError::SnapshotNotFoundForChainTip
886-
})?;
887877

888878
let Some(ref mining_key) = self.config.miner.mining_key else {
889879
return Ok(());
890880
};
891881
let mining_pkh = Hash160::from_node_public_key(&StacksPublicKey::from_private(mining_key));
892882

893-
let last_winner_snapshot = {
883+
// If we won the last sortition, then we should start a new tenure off of it.
884+
let last_block_election_snapshot = {
894885
let ih = self.sortdb.index_handle(&burn_tip.sortition_id);
895886
ih.get_last_snapshot_with_sortition(burn_tip.block_height)
896887
.map_err(|e| {
@@ -899,29 +890,59 @@ impl RelayerThread {
899890
})?
900891
};
901892

902-
let won_last_sortition = last_winner_snapshot.miner_pk_hash == Some(mining_pkh);
893+
let won_last_sortition = last_block_election_snapshot.miner_pk_hash == Some(mining_pkh);
903894
debug!(
904895
"Relayer: Current burn block had no sortition. Checking for tenure continuation.";
905896
"won_last_sortition" => won_last_sortition,
906897
"current_mining_pkh" => %mining_pkh,
907-
"last_winner_snapshot.miner_pk_hash" => ?last_winner_snapshot.miner_pk_hash,
898+
"last_block_election_snapshot.consensus_hash" => %last_block_election_snapshot.consensus_hash,
899+
"last_block_election_snapshot.miner_pk_hash" => ?last_block_election_snapshot.miner_pk_hash,
908900
"canonical_stacks_tip_id" => %canonical_stacks_tip,
909901
"canonical_stacks_tip_ch" => %canonical_stacks_tip_ch,
910-
"block_election_ch" => %block_election_snapshot.consensus_hash,
911902
"burn_view_ch" => %new_burn_view,
912903
);
913904

914905
if !won_last_sortition {
915906
return Ok(());
916907
}
917908

909+
let canonical_block_snapshot =
910+
SortitionDB::get_block_snapshot_consensus(self.sortdb.conn(), &canonical_stacks_tip_ch)
911+
.map_err(|e| {
912+
error!("Relayer: failed to get block snapshot for canonical tip: {e:?}");
913+
NakamotoNodeError::SnapshotNotFoundForChainTip
914+
})?
915+
.ok_or_else(|| {
916+
error!("Relayer: failed to get block snapshot for canonical tip");
917+
NakamotoNodeError::SnapshotNotFoundForChainTip
918+
})?;
919+
920+
let won_canonical_block_snapshot =
921+
canonical_block_snapshot.miner_pk_hash == Some(mining_pkh);
922+
923+
let (parent_tenure_start, block_election_snapshot, reason) =
924+
if !won_canonical_block_snapshot {
925+
debug!("Relayer: Failed to issue a tenure change payload in our last tenure. Issue a new tenure change payload.");
926+
(
927+
StacksBlockId(last_block_election_snapshot.winning_stacks_block_hash.0),
928+
last_block_election_snapshot,
929+
MinerReason::EmptyTenure,
930+
)
931+
} else {
932+
debug!("Relayer: Successfully issued a tenure change payload in its tenure. Issue a continue extend from the chain tip.");
933+
(
934+
canonical_stacks_tip, //For tenure extend, we should be extending off the canonical tip
935+
canonical_block_snapshot,
936+
MinerReason::Extended {
937+
burn_view_consensus_hash: new_burn_view,
938+
},
939+
)
940+
};
918941
match self.start_new_tenure(
919-
canonical_stacks_tip, // For tenure extend, we should be extending off the canonical tip
942+
parent_tenure_start,
920943
block_election_snapshot,
921944
burn_tip,
922-
MinerReason::Extended {
923-
burn_view_consensus_hash: new_burn_view,
924-
},
945+
reason,
925946
) {
926947
Ok(()) => {
927948
debug!("Relayer: successfully started new tenure.");
@@ -994,13 +1015,7 @@ impl RelayerThread {
9941015

9951016
#[cfg(test)]
9961017
fn fault_injection_skip_block_commit(&self) -> bool {
997-
self.globals
998-
.counters
999-
.naka_skip_commit_op
1000-
.0
1001-
.lock()
1002-
.unwrap()
1003-
.unwrap_or(false)
1018+
self.globals.counters.naka_skip_commit_op.get()
10041019
}
10051020

10061021
#[cfg(not(test))]

testnet/stacks-node/src/run_loop/neon.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,19 @@ impl Default for TestFlag {
9393
}
9494
}
9595

96+
#[cfg(test)]
97+
impl TestFlag {
98+
/// Set the test flag to the given value
99+
pub fn set(&self, value: bool) {
100+
*self.0.lock().unwrap() = Some(value);
101+
}
102+
103+
/// Get the test flag value. Defaults to false if the flag is not set.
104+
pub fn get(&self) -> bool {
105+
self.0.lock().unwrap().unwrap_or(false)
106+
}
107+
}
108+
96109
#[derive(Clone, Default)]
97110
pub struct Counters {
98111
pub blocks_processed: RunLoopCounter,
@@ -1022,7 +1035,7 @@ impl RunLoop {
10221035
/// This function will block by looping infinitely.
10231036
/// It will start the burnchain (separate thread), set-up a channel in
10241037
/// charge of coordinating the new blocks coming from the burnchain and
1025-
/// the nodes, taking turns on tenures.
1038+
/// the nodes, taking turns on tenures.
10261039
///
10271040
/// Returns `Option<NeonGlobals>` so that data can be passed to `NakamotoNode`
10281041
pub fn start(

testnet/stacks-node/src/tests/nakamoto_integrations.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4984,7 +4984,7 @@ fn forked_tenure_is_ignored() {
49844984

49854985
// Unpause the broadcast of Tenure B's block, do not submit commits, and do not allow blocks to
49864986
// be processed
4987-
test_skip_commit_op.0.lock().unwrap().replace(true);
4987+
test_skip_commit_op.set(true);
49884988
TEST_BROADCAST_STALL.lock().unwrap().replace(false);
49894989

49904990
// Wait for a stacks block to be broadcasted.
@@ -5037,7 +5037,7 @@ fn forked_tenure_is_ignored() {
50375037
.expect("Mutex poisoned")
50385038
.get_stacks_blocks_processed();
50395039
next_block_and(&mut btc_regtest_controller, 60, || {
5040-
test_skip_commit_op.0.lock().unwrap().replace(false);
5040+
test_skip_commit_op.set(false);
50415041
TEST_BLOCK_ANNOUNCE_STALL.lock().unwrap().replace(false);
50425042
let commits_count = commits_submitted.load(Ordering::SeqCst);
50435043
let blocks_count = mined_blocks.load(Ordering::SeqCst);
@@ -6972,7 +6972,7 @@ fn continue_tenure_extend() {
69726972
.get_stacks_blocks_processed();
69736973

69746974
info!("Pausing commit ops to trigger a tenure extend.");
6975-
test_skip_commit_op.0.lock().unwrap().replace(true);
6975+
test_skip_commit_op.set(true);
69766976

69776977
next_block_and(&mut btc_regtest_controller, 60, || Ok(true)).unwrap();
69786978

@@ -7071,7 +7071,7 @@ fn continue_tenure_extend() {
70717071
}
70727072

70737073
info!("Resuming commit ops to mine regular tenures.");
7074-
test_skip_commit_op.0.lock().unwrap().replace(false);
7074+
test_skip_commit_op.set(false);
70757075

70767076
// Mine 15 more regular nakamoto tenures
70777077
for _i in 0..15 {

0 commit comments

Comments
 (0)