Skip to content

Commit a0ab14b

Browse files
authored
Merge pull request #5805 from stacks-network/feat/miner-continues-tenure-if-tenure-empty
Issue tenure extend if incoming miner fails to mine
2 parents efb5681 + 18ada14 commit a0ab14b

File tree

8 files changed

+3299
-407
lines changed

8 files changed

+3299
-407
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
2828
### Added
2929

3030
- Add miner configuration option `tenure_extend_cost_threshold` to specify the percentage of the tenure budget that must be spent before a time-based tenure extend is attempted
31+
- Add miner configuration option `tenure_extend_wait_timeout_ms` to specify the time to wait before trying to continue a tenure because the next miner did not produce blocks
3132

3233
### Changed
3334

3435
- Miner will include other transactions in blocks with tenure extend transactions (#5760)
3536
- Add `block_rejection_timeout_steps` to miner configuration for defining rejections-based timeouts while waiting for signers response (#5705)
3637
- Miner will not issue a tenure extend until at least half of the block budget has been spent (#5757)
38+
- Miner will issue a tenure extend if the incoming miner has failed to produce a block (#5729)
3739

3840
### Fixed
3941

stacks-signer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
2727
`StackerDB` messages, it logs `INFO` messages. Other interactions with the `stacks-node`
2828
behave normally (e.g., submitting validation requests, submitting finished blocks). A
2929
dry run signer will error out if the supplied key is actually a registered signer.
30+
- Reduce default value of `block_proposal_timeout_ms` to 120_000
3031

3132
## [3.1.0.0.4.0]
3233

stacks-signer/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use stacks_common::util::hash::Hash160;
3535
use crate::client::SignerSlotID;
3636

3737
const EVENT_TIMEOUT_MS: u64 = 5000;
38-
const BLOCK_PROPOSAL_TIMEOUT_MS: u64 = 14_400_000;
38+
const BLOCK_PROPOSAL_TIMEOUT_MS: u64 = 120_000;
3939
const BLOCK_PROPOSAL_VALIDATION_TIMEOUT_MS: u64 = 120_000;
4040
const DEFAULT_FIRST_PROPOSAL_BURN_BLOCK_TIMING_SECS: u64 = 60;
4141
const DEFAULT_TENURE_LAST_BLOCK_PROPOSAL_TIMEOUT_SECS: u64 = 30;

stackslib/src/config/mod.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ const DEFAULT_TENURE_COST_LIMIT_PER_BLOCK_PERCENTAGE: u8 = 25;
114114
/// see if we need to extend the ongoing tenure (e.g. because the current
115115
/// sortition is empty or invalid).
116116
const DEFAULT_TENURE_EXTEND_POLL_SECS: u64 = 1;
117+
/// Default number of millis to wait before trying to continue a tenure because the next miner did not produce blocks
118+
const DEFAULT_TENURE_EXTEND_WAIT_MS: u64 = 120_000;
117119
/// Default duration to wait before attempting to issue a tenure extend.
118120
/// This should be greater than the signers' timeout. This is used for issuing
119121
/// fallback tenure extends
@@ -2162,9 +2164,11 @@ pub struct MinerConfig {
21622164
pub block_commit_delay: Duration,
21632165
/// The percentage of the remaining tenure cost limit to consume each block.
21642166
pub tenure_cost_limit_per_block_percentage: Option<u8>,
2165-
/// The number of seconds to wait in-between polling the sortition DB to see if we need to
2167+
/// Duration to wait in-between polling the sortition DB to see if we need to
21662168
/// extend the ongoing tenure (e.g. because the current sortition is empty or invalid).
2167-
pub tenure_extend_poll_secs: Duration,
2169+
pub tenure_extend_poll_timeout: Duration,
2170+
/// Duration to wait before trying to continue a tenure because the next miner did not produce blocks
2171+
pub tenure_extend_wait_timeout: Duration,
21682172
/// Duration to wait before attempting to issue a tenure extend
21692173
pub tenure_timeout: Duration,
21702174
/// Percentage of block budget that must be used before attempting a time-based tenure extend
@@ -2207,7 +2211,8 @@ impl Default for MinerConfig {
22072211
tenure_cost_limit_per_block_percentage: Some(
22082212
DEFAULT_TENURE_COST_LIMIT_PER_BLOCK_PERCENTAGE,
22092213
),
2210-
tenure_extend_poll_secs: Duration::from_secs(DEFAULT_TENURE_EXTEND_POLL_SECS),
2214+
tenure_extend_poll_timeout: Duration::from_secs(DEFAULT_TENURE_EXTEND_POLL_SECS),
2215+
tenure_extend_wait_timeout: Duration::from_millis(DEFAULT_TENURE_EXTEND_WAIT_MS),
22112216
tenure_timeout: Duration::from_secs(DEFAULT_TENURE_TIMEOUT_SECS),
22122217
tenure_extend_cost_threshold: DEFAULT_TENURE_EXTEND_COST_THRESHOLD,
22132218

@@ -2614,6 +2619,7 @@ pub struct MinerConfigFile {
26142619
pub block_commit_delay_ms: Option<u64>,
26152620
pub tenure_cost_limit_per_block_percentage: Option<u8>,
26162621
pub tenure_extend_poll_secs: Option<u64>,
2622+
pub tenure_extend_wait_timeout_ms: Option<u64>,
26172623
pub tenure_timeout_secs: Option<u64>,
26182624
pub tenure_extend_cost_threshold: Option<u64>,
26192625
pub block_rejection_timeout_steps: Option<HashMap<String, u64>>,
@@ -2757,7 +2763,8 @@ impl MinerConfigFile {
27572763
subsequent_rejection_pause_ms: self.subsequent_rejection_pause_ms.unwrap_or(miner_default_config.subsequent_rejection_pause_ms),
27582764
block_commit_delay: self.block_commit_delay_ms.map(Duration::from_millis).unwrap_or(miner_default_config.block_commit_delay),
27592765
tenure_cost_limit_per_block_percentage,
2760-
tenure_extend_poll_secs: self.tenure_extend_poll_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_extend_poll_secs),
2766+
tenure_extend_poll_timeout: self.tenure_extend_poll_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_extend_poll_timeout),
2767+
tenure_extend_wait_timeout: self.tenure_extend_wait_timeout_ms.map(Duration::from_millis).unwrap_or(miner_default_config.tenure_extend_wait_timeout),
27612768
tenure_timeout: self.tenure_timeout_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_timeout),
27622769
tenure_extend_cost_threshold: self.tenure_extend_cost_threshold.unwrap_or(miner_default_config.tenure_extend_cost_threshold),
27632770

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

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ use stacks::net::stackerdb::StackerDBs;
4747
use stacks::net::{NakamotoBlocksData, StacksMessageType};
4848
use stacks::util::get_epoch_time_secs;
4949
use stacks::util::secp256k1::MessageSignature;
50+
#[cfg(test)]
51+
use stacks::util::secp256k1::Secp256k1PublicKey;
5052
use stacks_common::types::chainstate::{StacksAddress, StacksBlockId};
53+
#[cfg(test)]
54+
use stacks_common::types::PublicKey;
5155
use stacks_common::types::{PrivateKey, StacksEpochId};
5256
#[cfg(test)]
5357
use stacks_common::util::tests::TestFlag;
@@ -64,8 +68,8 @@ use crate::run_loop::RegisteredKey;
6468
/// Test flag to stall the miner thread
6569
pub static TEST_MINE_STALL: LazyLock<TestFlag<bool>> = LazyLock::new(TestFlag::default);
6670
#[cfg(test)]
67-
/// Test flag to stall block proposal broadcasting
68-
pub static TEST_BROADCAST_PROPOSAL_STALL: LazyLock<TestFlag<bool>> =
71+
/// Test flag to stall block proposal broadcasting for the specified miner keys
72+
pub static TEST_BROADCAST_PROPOSAL_STALL: LazyLock<TestFlag<Vec<Secp256k1PublicKey>>> =
6973
LazyLock::new(TestFlag::default);
7074
#[cfg(test)]
7175
// Test flag to stall the miner from announcing a block while this flag is true
@@ -262,21 +266,32 @@ impl BlockMinerThread {
262266

263267
#[cfg(test)]
264268
fn fault_injection_block_proposal_stall(new_block: &NakamotoBlock) {
265-
if TEST_BROADCAST_PROPOSAL_STALL.get() {
266-
// Do an extra check just so we don't log EVERY time.
269+
if TEST_BROADCAST_PROPOSAL_STALL.get().iter().any(|key| {
270+
key.verify(
271+
new_block.header.miner_signature_hash().as_bytes(),
272+
&new_block.header.miner_signature,
273+
)
274+
.unwrap_or_default()
275+
}) {
267276
warn!("Fault injection: Block proposal broadcast is stalled due to testing directive.";
268-
"stacks_block_id" => %new_block.block_id(),
269-
"stacks_block_hash" => %new_block.header.block_hash(),
270-
"height" => new_block.header.chain_length,
271-
"consensus_hash" => %new_block.header.consensus_hash
277+
"stacks_block_id" => %new_block.block_id(),
278+
"stacks_block_hash" => %new_block.header.block_hash(),
279+
"height" => new_block.header.chain_length,
280+
"consensus_hash" => %new_block.header.consensus_hash
272281
);
273-
while TEST_BROADCAST_PROPOSAL_STALL.get() {
282+
while TEST_BROADCAST_PROPOSAL_STALL.get().iter().any(|key| {
283+
key.verify(
284+
new_block.header.miner_signature_hash().as_bytes(),
285+
&new_block.header.miner_signature,
286+
)
287+
.unwrap_or_default()
288+
}) {
274289
std::thread::sleep(std::time::Duration::from_millis(10));
275290
}
276291
info!("Fault injection: Block proposal broadcast is no longer stalled due to testing directive.";
277-
"block_id" => %new_block.block_id(),
278-
"height" => new_block.header.chain_length,
279-
"consensus_hash" => %new_block.header.consensus_hash
292+
"block_id" => %new_block.block_id(),
293+
"height" => new_block.header.chain_length,
294+
"consensus_hash" => %new_block.header.consensus_hash
280295
);
281296
}
282297
}

0 commit comments

Comments
 (0)