Skip to content

Commit e668895

Browse files
committed
Add reorg_attempts_activity_timeout_exceeded test and add config option reorg_attempts_activity_timeout_ms
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 953388b commit e668895

File tree

9 files changed

+248
-4
lines changed

9 files changed

+248
-4
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ jobs:
146146
- tests::signer::v0::single_miner_empty_sortition
147147
- tests::signer::v0::multiple_miners_empty_sortition
148148
- tests::signer::v0::block_proposal_timeout
149-
- tests::signer::v0::rejected_blocks_count_towards_miner_validity
149+
- tests::signer::v0::reorg_attempts_count_towards_miner_validity
150+
- tests::signer::v0::late_reorg_attempts_do_not_count_towards_miner_validity
150151
- tests::signer::v0::allow_reorg_within_first_proposal_burn_block_timing_secs
151152
- tests::nakamoto_integrations::burn_ops_integration_test
152153
- tests::nakamoto_integrations::check_block_heights

stacks-signer/src/chainstate.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ pub struct ProposalEvalConfig {
124124
pub tenure_last_block_proposal_timeout: Duration,
125125
/// How much idle time must pass before allowing a tenure extend
126126
pub tenure_idle_timeout: Duration,
127+
/// Time following a block's global acceptance that a signer will consider an attempt by a miner to reorg the block
128+
/// as valid towards miner activity
129+
pub reorg_attempts_activity_timeout: Duration,
127130
}
128131

129132
impl From<&SignerConfig> for ProposalEvalConfig {
@@ -133,6 +136,7 @@ impl From<&SignerConfig> for ProposalEvalConfig {
133136
block_proposal_timeout: value.block_proposal_timeout,
134137
tenure_last_block_proposal_timeout: value.tenure_last_block_proposal_timeout,
135138
tenure_idle_timeout: value.tenure_idle_timeout,
139+
reorg_attempts_activity_timeout: value.reorg_attempts_activity_timeout,
136140
}
137141
}
138142
}
@@ -547,8 +551,10 @@ impl SortitionsView {
547551
signer_db: &mut SignerDb,
548552
client: &StacksClient,
549553
tenure_last_block_proposal_timeout: Duration,
554+
reorg_attempts_activity_timeout: Duration,
550555
) -> Result<bool, ClientError> {
551556
// 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.
552558
let last_block_info = Self::get_tenure_last_block_info(
553559
&tenure_change.prev_tenure_consensus_hash,
554560
signer_db,
@@ -568,6 +574,22 @@ impl SortitionsView {
568574
"proposed_chain_length" => block.header.chain_length,
569575
"expected_at_least" => info.block.header.chain_length + 1,
570576
);
577+
if info.signed_group.unwrap_or(get_epoch_time_secs())
578+
+ reorg_attempts_activity_timeout.as_secs()
579+
> get_epoch_time_secs()
580+
{
581+
// 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).
582+
// Treat any attempt to reorg a locally accepted block as valid miner activity.
583+
// If the call returns a globally accepted block, check its globally accepted time against a quarter of the block_proposal_timeout
584+
// to give the miner some extra buffer time to wait for its chain tip to advance
585+
// The miner may just be slow, so count this invalid block proposal towards valid miner activity.
586+
if let Err(e) = signer_db.update_last_activity_time(
587+
&tenure_change.tenure_consensus_hash,
588+
get_epoch_time_secs(),
589+
) {
590+
warn!("Failed to update last activity time: {e}");
591+
}
592+
}
571593
return Ok(false);
572594
}
573595
}
@@ -633,6 +655,7 @@ impl SortitionsView {
633655
signer_db,
634656
client,
635657
self.config.tenure_last_block_proposal_timeout,
658+
self.config.reorg_attempts_activity_timeout,
636659
)?;
637660
if !confirms_expected_parent {
638661
return Ok(false);

stacks-signer/src/client/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ pub(crate) mod tests {
415415
block_proposal_validation_timeout: config.block_proposal_validation_timeout,
416416
tenure_idle_timeout: config.tenure_idle_timeout,
417417
block_proposal_max_age_secs: config.block_proposal_max_age_secs,
418+
reorg_attempts_activity_timeout: config.reorg_attempts_activity_timeout,
418419
}
419420
}
420421

stacks-signer/src/config.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ 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 TENURE_IDLE_TIMEOUT_SECS: u64 = 120;
43+
const DEFAULT_REORG_ATTEMPTS_ACTIVITY_TIMEOUT_MS: u64 = 200_000;
4344

4445
#[derive(thiserror::Error, Debug)]
4546
/// An error occurred parsing the provided configuration
@@ -141,6 +142,9 @@ pub struct SignerConfig {
141142
pub tenure_idle_timeout: Duration,
142143
/// The maximum age of a block proposal in seconds that will be processed by the signer
143144
pub block_proposal_max_age_secs: u64,
145+
/// Time following a block's global acceptance that a signer will consider an attempt by a miner to reorg the block
146+
/// as valid towards miner activity
147+
pub reorg_attempts_activity_timeout: Duration,
144148
}
145149

146150
/// The parsed configuration for the signer
@@ -181,6 +185,9 @@ pub struct GlobalConfig {
181185
pub tenure_idle_timeout: Duration,
182186
/// The maximum age of a block proposal that will be processed by the signer
183187
pub block_proposal_max_age_secs: u64,
188+
/// Time following a block's global acceptance that a signer will consider an attempt by a miner to reorg the block
189+
/// as valid towards miner activity
190+
pub reorg_attempts_activity_timeout: Duration,
184191
}
185192

186193
/// Internal struct for loading up the config file
@@ -220,6 +227,9 @@ struct RawConfigFile {
220227
pub tenure_idle_timeout_secs: Option<u64>,
221228
/// The maximum age of a block proposal (in secs) that will be processed by the signer.
222229
pub block_proposal_max_age_secs: Option<u64>,
230+
/// Time (in millisecs) following a block's global acceptance that a signer will consider an attempt by a miner
231+
/// to reorg the block as valid towards miner activity
232+
pub reorg_attempts_activity_timeout_ms: Option<u64>,
223233
}
224234

225235
impl RawConfigFile {
@@ -321,6 +331,12 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
321331
.block_proposal_max_age_secs
322332
.unwrap_or(DEFAULT_BLOCK_PROPOSAL_MAX_AGE_SECS);
323333

334+
let reorg_attempts_activity_timeout = Duration::from_millis(
335+
raw_data
336+
.reorg_attempts_activity_timeout_ms
337+
.unwrap_or(DEFAULT_REORG_ATTEMPTS_ACTIVITY_TIMEOUT_MS),
338+
);
339+
324340
Ok(Self {
325341
node_host: raw_data.node_host,
326342
endpoint,
@@ -338,6 +354,7 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
338354
block_proposal_validation_timeout,
339355
tenure_idle_timeout,
340356
block_proposal_max_age_secs,
357+
reorg_attempts_activity_timeout,
341358
})
342359
}
343360
}

stacks-signer/src/runloop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ impl<Signer: SignerTrait<T>, T: StacksMessageCodec + Clone + Send + Debug> RunLo
291291
block_proposal_validation_timeout: self.config.block_proposal_validation_timeout,
292292
tenure_idle_timeout: self.config.tenure_idle_timeout,
293293
block_proposal_max_age_secs: self.config.block_proposal_max_age_secs,
294+
reorg_attempts_activity_timeout: self.config.reorg_attempts_activity_timeout,
294295
}))
295296
}
296297

stacks-signer/src/tests/chainstate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ fn setup_test_environment(
9191
block_proposal_timeout: Duration::from_secs(5),
9292
tenure_last_block_proposal_timeout: Duration::from_secs(30),
9393
tenure_idle_timeout: Duration::from_secs(300),
94+
reorg_attempts_activity_timeout: Duration::from_secs(3),
9495
},
9596
};
9697

stacks-signer/src/v0/signer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ impl Signer {
613613
&mut self.signer_db,
614614
stacks_client,
615615
self.proposal_config.tenure_last_block_proposal_timeout,
616+
self.proposal_config.reorg_attempts_activity_timeout,
616617
) {
617618
Ok(true) => {}
618619
Ok(false) => {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6468,6 +6468,7 @@ fn signer_chainstate() {
64686468
block_proposal_timeout: Duration::from_secs(100),
64696469
tenure_last_block_proposal_timeout: Duration::from_secs(30),
64706470
tenure_idle_timeout: Duration::from_secs(300),
6471+
reorg_attempts_activity_timeout: Duration::from_secs(30),
64716472
};
64726473
let mut sortitions_view =
64736474
SortitionsView::fetch_view(proposal_conf, &signer_client).unwrap();
@@ -6599,6 +6600,7 @@ fn signer_chainstate() {
65996600
block_proposal_timeout: Duration::from_secs(100),
66006601
tenure_last_block_proposal_timeout: Duration::from_secs(30),
66016602
tenure_idle_timeout: Duration::from_secs(300),
6603+
reorg_attempts_activity_timeout: Duration::from_secs(30),
66026604
};
66036605
let burn_block_height = SortitionDB::get_canonical_burn_chain_tip(sortdb.conn())
66046606
.unwrap()
@@ -6678,6 +6680,7 @@ fn signer_chainstate() {
66786680
block_proposal_timeout: Duration::from_secs(100),
66796681
tenure_last_block_proposal_timeout: Duration::from_secs(30),
66806682
tenure_idle_timeout: Duration::from_secs(300),
6683+
reorg_attempts_activity_timeout: Duration::from_secs(30),
66816684
};
66826685
let mut sortitions_view = SortitionsView::fetch_view(proposal_conf, &signer_client).unwrap();
66836686
assert!(

0 commit comments

Comments
 (0)