Skip to content

Commit

Permalink
feat: add tenure_extend_buffer_secs miner config option
Browse files Browse the repository at this point in the history
This allows the miner to specify a buffer (in seconds) that it should
wait after it has reached a time when it thinks 70% of signers should
approve a time-based tenure extend. The goal is to provide a little
buffer for clock skew, since we have seen, live on mainnet, cases where
<70% of signers approve a tenure-extend.

This is item 2 in #5757.
  • Loading branch information
obycode committed Feb 7, 2025
1 parent ea79fdc commit 0a93b50
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
### Added

- Add `vrf_seed` to the `/v3/sortitions` rpc endpoint
- Add miner configuration option `tenure_extend_buffer_secs` to specify the number of seconds of buffer the miner should wait, after reaching the 70% threshold for tenure extension time, before issuing a tenure extension, to allow for clock skew between the miner and signers

### Changed

Expand Down
9 changes: 9 additions & 0 deletions stackslib/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ const DEFAULT_TENURE_TIMEOUT_SECS: u64 = 180;
/// Default percentage of block budget that must be used before attempting a
/// time-based tenure extend
const DEFAULT_TENURE_EXTEND_COST_THRESHOLD: u64 = 50;
/// Default number of seconds to wait after reaching a time when 70% of signers
/// would allow a time-based tenure extend before actually attempting to
/// extend, to allow for clock skew.
const DEFAULT_TENURE_EXTEND_BUFFER_SECS: u64 = 2;

static HELIUM_DEFAULT_CONNECTION_OPTIONS: LazyLock<ConnectionOptions> =
LazyLock::new(|| ConnectionOptions {
Expand Down Expand Up @@ -2169,6 +2173,8 @@ pub struct MinerConfig {
pub tenure_timeout: Duration,
/// Percentage of block budget that must be used before attempting a time-based tenure extend
pub tenure_extend_cost_threshold: u64,
/// Duration defining a buffer period to wait before submitting a time-based tenure extend after reaching the 70% approval time
pub tenure_extend_buffer_secs: u64,
/// Define the timeout to apply while waiting for signers responses, based on the amount of rejections
pub block_rejection_timeout_steps: HashMap<u32, Duration>,
}
Expand Down Expand Up @@ -2210,6 +2216,7 @@ impl Default for MinerConfig {
tenure_extend_poll_secs: Duration::from_secs(DEFAULT_TENURE_EXTEND_POLL_SECS),
tenure_timeout: Duration::from_secs(DEFAULT_TENURE_TIMEOUT_SECS),
tenure_extend_cost_threshold: DEFAULT_TENURE_EXTEND_COST_THRESHOLD,
tenure_extend_buffer_secs: DEFAULT_TENURE_EXTEND_BUFFER_SECS,

block_rejection_timeout_steps: {
let mut rejections_timeouts_default_map = HashMap::<u32, Duration>::new();
Expand Down Expand Up @@ -2616,6 +2623,7 @@ pub struct MinerConfigFile {
pub tenure_extend_poll_secs: Option<u64>,
pub tenure_timeout_secs: Option<u64>,
pub tenure_extend_cost_threshold: Option<u64>,
pub tenure_extend_buffer_secs: Option<u64>,
pub block_rejection_timeout_steps: Option<HashMap<String, u64>>,
}

Expand Down Expand Up @@ -2760,6 +2768,7 @@ impl MinerConfigFile {
tenure_extend_poll_secs: self.tenure_extend_poll_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_extend_poll_secs),
tenure_timeout: self.tenure_timeout_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_timeout),
tenure_extend_cost_threshold: self.tenure_extend_cost_threshold.unwrap_or(miner_default_config.tenure_extend_cost_threshold),
tenure_extend_buffer_secs: self.tenure_extend_buffer_secs.unwrap_or(miner_default_config.tenure_extend_buffer_secs),

block_rejection_timeout_steps: {
if let Some(block_rejection_timeout_items) = self.block_rejection_timeout_steps {
Expand Down
3 changes: 2 additions & 1 deletion testnet/stacks-node/src/nakamoto_node/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,8 @@ impl BlockMinerThread {
});
}

let tenure_extend_timestamp = coordinator.get_tenure_extend_timestamp();
let tenure_extend_timestamp = coordinator.get_tenure_extend_timestamp()
+ self.config.miner.tenure_extend_buffer_secs;
if get_epoch_time_secs() <= tenure_extend_timestamp
&& self.tenure_change_time.elapsed() <= self.config.miner.tenure_timeout
{
Expand Down
52 changes: 52 additions & 0 deletions testnet/stacks-node/src/tests/signer/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13500,3 +13500,55 @@ fn interrupt_miner_on_new_stacks_tip() {
info!("------------------------- Shutdown -------------------------");
signer_test.shutdown();
}

#[test]
#[ignore]
/// This test verifies that a miner will produce a TenureExtend transaction
/// after the signers' idle timeout, plus buffer, is reached.
fn tenure_extend_after_idle_signers_with_buffer() {
if env::var("BITCOIND_TEST") != Ok("1".into()) {
return;
}

tracing_subscriber::registry()
.with(fmt::layer())
.with(EnvFilter::from_default_env())
.init();

info!("------------------------- Test Setup -------------------------");
let num_signers = 5;
let idle_timeout = Duration::from_secs(1);
let buffer_secs = 20;
let mut signer_test: SignerTest<SpawnedSigner> = SignerTest::new_with_config_modifications(
num_signers,
vec![],
|config| {
config.tenure_idle_timeout = idle_timeout;
},
|config| {
config.miner.tenure_extend_cost_threshold = 0;
config.miner.tenure_extend_buffer_secs = buffer_secs;
},
None,
None,
);

signer_test.boot_to_epoch_3();

info!("---- Nakamoto booted, starting test ----");
signer_test.mine_nakamoto_block(Duration::from_secs(30), true);

info!("---- Waiting for a tenure extend ----");

// Now, wait for a block with a tenure extend
wait_for(idle_timeout.as_secs() + buffer_secs / 2, || {
Ok(last_block_contains_tenure_change_tx(
TenureChangeCause::Extended,
))
})
.expect_err(
"Received a tenure extend before idle timeout plus buffer should have been reached",
);

signer_test.shutdown();
}

0 comments on commit 0a93b50

Please sign in to comment.