Skip to content

Commit 5c1ae90

Browse files
committed
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into feat/signer-subscribe-to-block-events
2 parents 252d4f1 + 2a0217a commit 5c1ae90

File tree

9 files changed

+185
-32
lines changed

9 files changed

+185
-32
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ jobs:
130130
- tests::signer::v0::continue_after_fast_block_no_sortition
131131
- tests::signer::v0::block_validation_response_timeout
132132
- tests::signer::v0::tenure_extend_after_bad_commit
133+
- tests::signer::v0::block_proposal_max_age_rejections
133134
- tests::signer::v0::global_acceptance_depends_on_block_announcement
134135
- tests::nakamoto_integrations::burn_ops_integration_test
135136
- tests::nakamoto_integrations::check_block_heights

stacks-signer/CHANGELOG.md

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

1010
## Added
1111

12+
- Introduced the `block_proposal_max_age_secs` configuration option for signers, enabling them to automatically ignore block proposals that exceed the specified age in seconds.
13+
1214
## Changed
1315
- Signers now listen to new block events from the stacks node to determine whether a block has been successfully appended to the chain tip
1416

stacks-signer/src/chainstate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ impl SortitionsView {
367367
tenure_extend.burn_view_consensus_hash != sortition_consensus_hash;
368368
let extend_timestamp = signer_db.calculate_tenure_extend_timestamp(
369369
self.config.tenure_idle_timeout,
370-
&block,
370+
block,
371371
false,
372372
);
373373
let epoch_time = get_epoch_time_secs();

stacks-signer/src/client/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ pub(crate) mod tests {
414414
tenure_last_block_proposal_timeout: config.tenure_last_block_proposal_timeout,
415415
block_proposal_validation_timeout: config.block_proposal_validation_timeout,
416416
tenure_idle_timeout: config.tenure_idle_timeout,
417+
block_proposal_max_age_secs: config.block_proposal_max_age_secs,
417418
}
418419
}
419420

stacks-signer/src/config.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const BLOCK_PROPOSAL_VALIDATION_TIMEOUT_MS: u64 = 120_000;
3939
const DEFAULT_FIRST_PROPOSAL_BURN_BLOCK_TIMING_SECS: u64 = 60;
4040
const DEFAULT_TENURE_LAST_BLOCK_PROPOSAL_TIMEOUT_SECS: u64 = 30;
4141
const TENURE_IDLE_TIMEOUT_SECS: u64 = 300;
42+
const DEFAULT_BLOCK_PROPOSAL_MAX_AGE_SECS: u64 = 600;
4243

4344
#[derive(thiserror::Error, Debug)]
4445
/// An error occurred parsing the provided configuration
@@ -138,6 +139,8 @@ pub struct SignerConfig {
138139
pub block_proposal_validation_timeout: Duration,
139140
/// How much idle time must pass before allowing a tenure extend
140141
pub tenure_idle_timeout: Duration,
142+
/// The maximum age of a block proposal in seconds that will be processed by the signer
143+
pub block_proposal_max_age_secs: u64,
141144
}
142145

143146
/// The parsed configuration for the signer
@@ -176,6 +179,8 @@ pub struct GlobalConfig {
176179
pub block_proposal_validation_timeout: Duration,
177180
/// How much idle time must pass before allowing a tenure extend
178181
pub tenure_idle_timeout: Duration,
182+
/// The maximum age of a block proposal that will be processed by the signer
183+
pub block_proposal_max_age_secs: u64,
179184
}
180185

181186
/// Internal struct for loading up the config file
@@ -213,6 +218,8 @@ struct RawConfigFile {
213218
pub block_proposal_validation_timeout_ms: Option<u64>,
214219
/// How much idle time (in seconds) must pass before a tenure extend is allowed
215220
pub tenure_idle_timeout_secs: Option<u64>,
221+
/// The maximum age of a block proposal (in secs) that will be processed by the signer.
222+
pub block_proposal_max_age_secs: Option<u64>,
216223
}
217224

218225
impl RawConfigFile {
@@ -310,6 +317,10 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
310317
.unwrap_or(TENURE_IDLE_TIMEOUT_SECS),
311318
);
312319

320+
let block_proposal_max_age_secs = raw_data
321+
.block_proposal_max_age_secs
322+
.unwrap_or(DEFAULT_BLOCK_PROPOSAL_MAX_AGE_SECS);
323+
313324
Ok(Self {
314325
node_host: raw_data.node_host,
315326
endpoint,
@@ -326,6 +337,7 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
326337
tenure_last_block_proposal_timeout,
327338
block_proposal_validation_timeout,
328339
tenure_idle_timeout,
340+
block_proposal_max_age_secs,
329341
})
330342
}
331343
}

stacks-signer/src/runloop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ impl<Signer: SignerTrait<T>, T: StacksMessageCodec + Clone + Send + Debug> RunLo
286286
tenure_last_block_proposal_timeout: self.config.tenure_last_block_proposal_timeout,
287287
block_proposal_validation_timeout: self.config.block_proposal_validation_timeout,
288288
tenure_idle_timeout: self.config.tenure_idle_timeout,
289+
block_proposal_max_age_secs: self.config.block_proposal_max_age_secs,
289290
}))
290291
}
291292

stacks-signer/src/v0/signer.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ pub struct Signer {
9696
pub block_proposal_validation_timeout: Duration,
9797
/// The current submitted block proposal and its submission time
9898
pub submitted_block_proposal: Option<(BlockProposal, Instant)>,
99+
/// Maximum age of a block proposal in seconds before it is dropped without processing
100+
pub block_proposal_max_age_secs: u64,
99101
}
100102

101103
impl std::fmt::Display for Signer {
@@ -315,6 +317,7 @@ impl From<SignerConfig> for Signer {
315317
proposal_config,
316318
submitted_block_proposal: None,
317319
block_proposal_validation_timeout: signer_config.block_proposal_validation_timeout,
320+
block_proposal_max_age_secs: signer_config.block_proposal_max_age_secs,
318321
}
319322
}
320323
}
@@ -375,6 +378,24 @@ impl Signer {
375378
return;
376379
}
377380

381+
if block_proposal
382+
.block
383+
.header
384+
.timestamp
385+
.saturating_add(self.block_proposal_max_age_secs)
386+
< get_epoch_time_secs()
387+
{
388+
// Block is too old. Drop it with a warning. Don't even bother broadcasting to the node.
389+
warn!("{self}: Received a block proposal that is more than {} secs old. Ignoring...", self.block_proposal_max_age_secs;
390+
"signer_sighash" => %block_proposal.block.header.signer_signature_hash(),
391+
"block_id" => %block_proposal.block.block_id(),
392+
"block_height" => block_proposal.block.header.chain_length,
393+
"burn_height" => block_proposal.burn_height,
394+
"timestamp" => block_proposal.block.header.timestamp,
395+
);
396+
return;
397+
}
398+
378399
// TODO: should add a check to ignore an old burn block height if we know its outdated. Would require us to store the burn block height we last saw on the side.
379400
// the signer needs to be able to determine whether or not the block they're about to sign would conflict with an already-signed Stacks block
380401
let signer_signature_hash = block_proposal.block.header.signer_signature_hash();

testnet/stacks-node/src/tests/signer/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,8 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
311311
}
312312

313313
/// Mine a BTC block and wait for a new Stacks block to be mined
314-
fn mine_nakamoto_block(&mut self, timeout: Duration) {
314+
/// Note: do not use nakamoto blocks mined heuristic if running a test with multiple miners
315+
fn mine_nakamoto_block(&mut self, timeout: Duration, use_nakamoto_blocks_mined: bool) {
315316
let commits_submitted = self.running_nodes.commits_submitted.clone();
316317
let mined_block_time = Instant::now();
317318
let mined_before = self.running_nodes.nakamoto_blocks_mined.get();
@@ -328,7 +329,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
328329
let info_after = self.get_peer_info();
329330
let blocks_mined = self.running_nodes.nakamoto_blocks_mined.get();
330331
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height
331-
&& blocks_mined > mined_before)
332+
&& (!use_nakamoto_blocks_mined || blocks_mined > mined_before))
332333
})
333334
.unwrap();
334335
let mined_block_elapsed_time = mined_block_time.elapsed();

0 commit comments

Comments
 (0)