Skip to content

Commit 32db942

Browse files
authored
Merge branch 'develop' into feat/vrf-seed-in-get-sortition-rpc-endpoint
2 parents 8bf7261 + ef96476 commit 32db942

File tree

19 files changed

+738
-98
lines changed

19 files changed

+738
-98
lines changed

.github/workflows/pr-differences-mutants.yml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
name: PR Differences Mutants
22

33
on:
4-
pull_request:
5-
types:
6-
- opened
7-
- reopened
8-
- synchronize
9-
- ready_for_review
10-
paths:
11-
- '**.rs'
4+
# Disabling PR mutants (issue #5806)
5+
# pull_request:
6+
# types:
7+
# - opened
8+
# - reopened
9+
# - synchronize
10+
# - ready_for_review
11+
# paths:
12+
# - '**.rs'
1213
workflow_dispatch:
1314

1415
concurrency:

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1515

1616
### Fixed
1717

18+
- Error responses to /v2/transactions/fees are once again expressed as JSON ([#4145](https://github.com/stacks-network/stacks-core/issues/4145)).
19+
1820
## [3.1.0.0.5]
1921

2022
### Added

stacks-signer/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
77

88
## [Unreleased]
99

10-
### Added
10+
## Added
11+
12+
- Introduced the `reorg_attempts_activity_timeout_ms` configuration option for signers which is used to determine the length of time after the last block of a tenure is confirmed that an incoming miner's attempts to reorg it are considered valid miner activity.
1113

1214
### Changed
1315

16+
- Increase default `block_proposal_timeout_ms` from 10 minutes to 4 hours. Until #5729 is implemented, there is no value in rejecting a late block from a miner, since a late block is better than no block at all.
17+
18+
- Signers no longer view any block proposal by a miner in their DB as indicative of valid miner activity.
19+
1420
## [3.1.0.0.5.0]
1521

1622
### Added

stacks-signer/src/chainstate.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,25 @@ impl SortitionState {
8989
if self.miner_status != SortitionMinerStatus::Valid {
9090
return Ok(false);
9191
}
92-
// if we've already seen a proposed block from this miner. It cannot have timed out.
93-
let has_blocks = signer_db.has_proposed_block_in_tenure(&self.consensus_hash)?;
94-
if has_blocks {
92+
// if we've already signed a block in this tenure, the miner can't have timed out.
93+
let has_block = signer_db.has_signed_block_in_tenure(&self.consensus_hash)?;
94+
if has_block {
9595
return Ok(false);
9696
}
9797
let Some(received_ts) = signer_db.get_burn_block_receive_time(&self.burn_block_hash)?
9898
else {
9999
return Ok(false);
100100
};
101101
let received_time = UNIX_EPOCH + Duration::from_secs(received_ts);
102-
let Ok(elapsed) = std::time::SystemTime::now().duration_since(received_time) else {
102+
let last_activity = signer_db
103+
.get_last_activity_time(&self.consensus_hash)?
104+
.map(|time| UNIX_EPOCH + Duration::from_secs(time))
105+
.unwrap_or(received_time);
106+
107+
let Ok(elapsed) = std::time::SystemTime::now().duration_since(last_activity) else {
103108
return Ok(false);
104109
};
105-
if elapsed > timeout {
106-
return Ok(true);
107-
}
108-
Ok(false)
110+
Ok(elapsed > timeout)
109111
}
110112
}
111113

@@ -122,6 +124,9 @@ pub struct ProposalEvalConfig {
122124
pub tenure_last_block_proposal_timeout: Duration,
123125
/// How much idle time must pass before allowing a tenure extend
124126
pub tenure_idle_timeout: Duration,
127+
/// Time following the last block of the previous tenure's global acceptance that a signer will consider an attempt by
128+
/// the new miner to reorg it as valid towards miner activity
129+
pub reorg_attempts_activity_timeout: Duration,
125130
}
126131

127132
impl From<&SignerConfig> for ProposalEvalConfig {
@@ -131,6 +136,7 @@ impl From<&SignerConfig> for ProposalEvalConfig {
131136
block_proposal_timeout: value.block_proposal_timeout,
132137
tenure_last_block_proposal_timeout: value.tenure_last_block_proposal_timeout,
133138
tenure_idle_timeout: value.tenure_idle_timeout,
139+
reorg_attempts_activity_timeout: value.reorg_attempts_activity_timeout,
134140
}
135141
}
136142
}
@@ -545,8 +551,10 @@ impl SortitionsView {
545551
signer_db: &mut SignerDb,
546552
client: &StacksClient,
547553
tenure_last_block_proposal_timeout: Duration,
554+
reorg_attempts_activity_timeout: Duration,
548555
) -> Result<bool, ClientError> {
549556
// If the tenure change block confirms the expected parent block, it should confirm at least one more block than the last accepted block in the parent tenure.
557+
// NOTE: returns the locally accepted block if it is not timed out, otherwise it will return the last globally accepted block.
550558
let last_block_info = Self::get_tenure_last_block_info(
551559
&tenure_change.prev_tenure_consensus_hash,
552560
signer_db,
@@ -566,6 +574,21 @@ impl SortitionsView {
566574
"proposed_chain_length" => block.header.chain_length,
567575
"expected_at_least" => info.block.header.chain_length + 1,
568576
);
577+
if info.signed_group.map_or(true, |signed_time| {
578+
signed_time + reorg_attempts_activity_timeout.as_secs() > get_epoch_time_secs()
579+
}) {
580+
// Note if there is no signed_group time, this is a locally accepted block (i.e. tenure_last_block_proposal_timeout has not been exceeded).
581+
// Treat any attempt to reorg a locally accepted block as valid miner activity.
582+
// If the call returns a globally accepted block, check its globally accepted time against a quarter of the block_proposal_timeout
583+
// to give the miner some extra buffer time to wait for its chain tip to advance
584+
// The miner may just be slow, so count this invalid block proposal towards valid miner activity.
585+
if let Err(e) = signer_db.update_last_activity_time(
586+
&tenure_change.tenure_consensus_hash,
587+
get_epoch_time_secs(),
588+
) {
589+
warn!("Failed to update last activity time: {e}");
590+
}
591+
}
569592
return Ok(false);
570593
}
571594
}
@@ -631,6 +654,7 @@ impl SortitionsView {
631654
signer_db,
632655
client,
633656
self.config.tenure_last_block_proposal_timeout,
657+
self.config.reorg_attempts_activity_timeout,
634658
)?;
635659
if !confirms_expected_parent {
636660
return Ok(false);

stacks-signer/src/client/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ pub(crate) mod tests {
417417
block_proposal_validation_timeout: config.block_proposal_validation_timeout,
418418
tenure_idle_timeout: config.tenure_idle_timeout,
419419
block_proposal_max_age_secs: config.block_proposal_max_age_secs,
420+
reorg_attempts_activity_timeout: config.reorg_attempts_activity_timeout,
420421
}
421422
}
422423

stacks-signer/src/config.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ 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 = 600_000;
38+
const BLOCK_PROPOSAL_TIMEOUT_MS: u64 = 14_400_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;
4242
const DEFAULT_DRY_RUN: bool = false;
4343
const TENURE_IDLE_TIMEOUT_SECS: u64 = 120;
44+
const DEFAULT_REORG_ATTEMPTS_ACTIVITY_TIMEOUT_MS: u64 = 200_000;
4445

4546
#[derive(thiserror::Error, Debug)]
4647
/// An error occurred parsing the provided configuration
@@ -163,6 +164,9 @@ pub struct SignerConfig {
163164
pub tenure_idle_timeout: Duration,
164165
/// The maximum age of a block proposal in seconds that will be processed by the signer
165166
pub block_proposal_max_age_secs: u64,
167+
/// Time following the last block of the previous tenure's global acceptance that a signer will consider an attempt by
168+
/// the new miner to reorg it as valid towards miner activity
169+
pub reorg_attempts_activity_timeout: Duration,
166170
/// The running mode for the signer (dry-run or normal)
167171
pub signer_mode: SignerConfigMode,
168172
}
@@ -205,6 +209,9 @@ pub struct GlobalConfig {
205209
pub tenure_idle_timeout: Duration,
206210
/// The maximum age of a block proposal that will be processed by the signer
207211
pub block_proposal_max_age_secs: u64,
212+
/// Time following the last block of the previous tenure's global acceptance that a signer will consider an attempt by
213+
/// the new miner to reorg it as valid towards miner activity
214+
pub reorg_attempts_activity_timeout: Duration,
208215
/// Is this signer binary going to be running in dry-run mode?
209216
pub dry_run: bool,
210217
}
@@ -246,6 +253,9 @@ struct RawConfigFile {
246253
pub tenure_idle_timeout_secs: Option<u64>,
247254
/// The maximum age of a block proposal (in secs) that will be processed by the signer.
248255
pub block_proposal_max_age_secs: Option<u64>,
256+
/// Time (in millisecs) following a block's global acceptance that a signer will consider an attempt by a miner
257+
/// to reorg the block as valid towards miner activity
258+
pub reorg_attempts_activity_timeout_ms: Option<u64>,
249259
/// Is this signer binary going to be running in dry-run mode?
250260
pub dry_run: Option<bool>,
251261
}
@@ -349,6 +359,12 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
349359
.block_proposal_max_age_secs
350360
.unwrap_or(DEFAULT_BLOCK_PROPOSAL_MAX_AGE_SECS);
351361

362+
let reorg_attempts_activity_timeout = Duration::from_millis(
363+
raw_data
364+
.reorg_attempts_activity_timeout_ms
365+
.unwrap_or(DEFAULT_REORG_ATTEMPTS_ACTIVITY_TIMEOUT_MS),
366+
);
367+
352368
let dry_run = raw_data.dry_run.unwrap_or(DEFAULT_DRY_RUN);
353369

354370
Ok(Self {
@@ -368,6 +384,7 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
368384
block_proposal_validation_timeout,
369385
tenure_idle_timeout,
370386
block_proposal_max_age_secs,
387+
reorg_attempts_activity_timeout,
371388
dry_run,
372389
})
373390
}

stacks-signer/src/runloop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ impl<Signer: SignerTrait<T>, T: StacksMessageCodec + Clone + Send + Debug> RunLo
315315
block_proposal_validation_timeout: self.config.block_proposal_validation_timeout,
316316
tenure_idle_timeout: self.config.tenure_idle_timeout,
317317
block_proposal_max_age_secs: self.config.block_proposal_max_age_secs,
318+
reorg_attempts_activity_timeout: self.config.reorg_attempts_activity_timeout,
318319
}))
319320
}
320321

0 commit comments

Comments
 (0)