Skip to content

Commit 8641730

Browse files
authored
Merge branch 'develop' into long-block-proposal-timeout
2 parents fa6a6b7 + 1408ef9 commit 8641730

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1379
-1525
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ jobs:
8383
- tests::neon_integrations::start_stop_bitcoind
8484
- tests::should_succeed_handling_malformed_and_valid_txs
8585
- tests::nakamoto_integrations::simple_neon_integration
86-
- tests::nakamoto_integrations::flash_blocks_on_epoch_3
86+
# Disable this flaky test. We don't need continue testing Epoch 2 -> 3 transition
87+
# - tests::nakamoto_integrations::flash_blocks_on_epoch_3_FLAKY
8788
- tests::nakamoto_integrations::mine_multiple_per_tenure_integration
8889
- tests::nakamoto_integrations::block_proposal_api_endpoint
8990
- tests::nakamoto_integrations::miner_writes_proposed_block_to_stackerdb
@@ -134,6 +135,7 @@ jobs:
134135
- tests::signer::v0::block_commit_delay
135136
- tests::signer::v0::continue_after_fast_block_no_sortition
136137
- tests::signer::v0::block_validation_response_timeout
138+
- tests::signer::v0::block_validation_check_rejection_timeout_heuristic
137139
- tests::signer::v0::block_validation_pending_table
138140
- tests::signer::v0::new_tenure_while_validating_previous_scenario
139141
- tests::signer::v0::tenure_extend_after_bad_commit

CHANGELOG.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
88
## [Unreleased]
99

1010
### Added
11-
- Add `dry_run` configuration option to `stacks-signer` config toml. Dry run mode will
12-
run the signer binary as if it were a registered signer. Instead of broadcasting
13-
`StackerDB` messages, it logs `INFO` messages. Other interactions with the `stacks-node`
14-
behave normally (e.g., submitting validation requests, submitting finished blocks). A
15-
dry run signer will error out if the supplied key is actually a registered signer.
11+
12+
### Changed
13+
14+
### Fixed
15+
16+
## [3.1.0.0.5]
17+
18+
### Added
19+
20+
- 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
1621

1722
### Changed
1823

1924
- Miner will include other transactions in blocks with tenure extend transactions (#5760)
25+
- Add `block_rejection_timeout_steps` to miner configuration for defining rejections-based timeouts while waiting for signers response (#5705)
26+
- Miner will not issue a tenure extend until at least half of the block budget has been spent (#5757)
2027

2128
### Fixed
2229

stacks-signer/CHANGELOG.md

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,56 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1111

1212
- 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.
1313

14+
## [3.1.0.0.5.0]
15+
16+
### Added
17+
18+
- Add `dry_run` configuration option to `stacks-signer` config toml. Dry run mode will
19+
run the signer binary as if it were a registered signer. Instead of broadcasting
20+
`StackerDB` messages, it logs `INFO` messages. Other interactions with the `stacks-node`
21+
behave normally (e.g., submitting validation requests, submitting finished blocks). A
22+
dry run signer will error out if the supplied key is actually a registered signer.
23+
1424
## [3.1.0.0.4.0]
1525

16-
## Added
26+
### Added
1727

1828
- When a new block proposal is received while the signer is waiting for an existing proposal to be validated, the signer will wait until the existing block is done validating before submitting the new one for validating. ([#5453](https://github.com/stacks-network/stacks-core/pull/5453))
1929
- Introduced two new prometheus metrics:
2030
- `stacks_signer_block_validation_latencies_histogram`: the validation_time_ms reported by the node when validating a block proposal
2131
- `stacks_signer_block_response_latencies_histogram`: the "end-to-end" time it takes for the signer to issue a block response
2232

23-
## Changed
33+
### Changed
2434

2535
## [3.1.0.0.3.0]
2636

27-
## Added
37+
### Added
2838

2939
- 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.
3040

31-
## Changed
41+
### Changed
3242
- Improvements to the stale signer cleanup logic: deletes the prior signer if it has no remaining unprocessed blocks in its database
3343
- Signers now listen to new block events from the stacks node to determine whether a block has been successfully appended to the chain tip
3444

35-
# [3.1.0.0.2.1]
45+
## [3.1.0.0.2.1]
3646

37-
## Added
47+
### Added
3848

39-
## Changed
49+
### Changed
4050

4151
- Prevent old reward cycle signers from processing block validation response messages that do not apply to blocks from their cycle.
4252

43-
# [3.1.0.0.2.1]
53+
## [3.1.0.0.2.1]
4454

45-
## Added
55+
### Added
4656

47-
## Changed
57+
### Changed
4858

4959
- Prevent old reward cycle signers from processing block validation response messages that do not apply to blocks from their cycle.
5060

5161
## [3.1.0.0.2.0]
5262

53-
## Added
63+
### Added
5464

5565
- **SIP-029 consensus rules, activating in epoch 3.1 at block 875,000** (see [SIP-029](https://github.com/will-corcoran/sips/blob/feat/sip-029-halving-alignment/sips/sip-029/sip-029-halving-alignment.md) for details)
5666

stackslib/src/burnchains/bitcoin/indexer.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -265,40 +265,31 @@ impl BitcoinIndexer {
265265
Ok(s) => {
266266
// Disable Nagle algorithm
267267
s.set_nodelay(true).map_err(|_e| {
268-
test_debug!("Failed to set TCP_NODELAY: {:?}", &_e);
268+
test_debug!("Failed to set TCP_NODELAY: {_e:?}");
269269
btc_error::ConnectionError
270270
})?;
271271

272272
// set timeout
273273
s.set_read_timeout(Some(Duration::from_secs(self.runtime.timeout)))
274274
.map_err(|_e| {
275-
test_debug!("Failed to set TCP read timeout: {:?}", &_e);
275+
test_debug!("Failed to set TCP read timeout: {_e:?}");
276276
btc_error::ConnectionError
277277
})?;
278278

279279
s.set_write_timeout(Some(Duration::from_secs(self.runtime.timeout)))
280280
.map_err(|_e| {
281-
test_debug!("Failed to set TCP write timeout: {:?}", &_e);
281+
test_debug!("Failed to set TCP write timeout: {_e:?}");
282282
btc_error::ConnectionError
283283
})?;
284284

285-
match self.runtime.sock.take() {
286-
Some(s) => {
287-
let _ = s.shutdown(Shutdown::Both);
288-
}
289-
None => {}
285+
if let Some(s_old) = self.runtime.sock.replace(s) {
286+
let _ = s_old.shutdown(Shutdown::Both);
290287
}
291-
292-
self.runtime.sock = Some(s);
293288
Ok(())
294289
}
295290
Err(_e) => {
296-
let s = self.runtime.sock.take();
297-
match s {
298-
Some(s) => {
299-
let _ = s.shutdown(Shutdown::Both);
300-
}
301-
None => {}
291+
if let Some(s) = self.runtime.sock.take() {
292+
let _ = s.shutdown(Shutdown::Both);
302293
}
303294
Err(btc_error::ConnectionError)
304295
}
@@ -926,11 +917,8 @@ impl BitcoinIndexer {
926917

927918
impl Drop for BitcoinIndexer {
928919
fn drop(&mut self) {
929-
match self.runtime.sock {
930-
Some(ref mut s) => {
931-
let _ = s.shutdown(Shutdown::Both);
932-
}
933-
None => {}
920+
if let Some(ref mut s) = self.runtime.sock {
921+
let _ = s.shutdown(Shutdown::Both);
934922
}
935923
}
936924
}

stackslib/src/burnchains/db.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1193,9 +1193,10 @@ impl BurnchainDB {
11931193
let ops: Vec<BlockstackOperationType> =
11941194
query_rows(&self.conn, qry, args).expect("FATAL: burnchain DB query error");
11951195
for op in ops {
1196-
if let Some(_) = indexer
1196+
if indexer
11971197
.find_burnchain_header_height(&op.burn_header_hash())
11981198
.expect("FATAL: burnchain DB query error")
1199+
.is_some()
11991200
{
12001201
// this is the op on the canonical fork
12011202
return Some(op);

stackslib/src/burnchains/tests/mod.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -577,13 +577,10 @@ impl TestBurnchainBlock {
577577
pub fn patch_from_chain_tip(&mut self, parent_snapshot: &BlockSnapshot) {
578578
assert_eq!(parent_snapshot.block_height + 1, self.block_height);
579579

580-
for i in 0..self.txs.len() {
581-
match self.txs[i] {
582-
BlockstackOperationType::LeaderKeyRegister(ref mut data) => {
583-
assert_eq!(data.block_height, self.block_height);
584-
data.consensus_hash = parent_snapshot.consensus_hash.clone();
585-
}
586-
_ => {}
580+
for tx in self.txs.iter_mut() {
581+
if let BlockstackOperationType::LeaderKeyRegister(ref mut data) = tx {
582+
assert_eq!(data.block_height, self.block_height);
583+
data.consensus_hash = parent_snapshot.consensus_hash.clone();
587584
}
588585
}
589586
}

stackslib/src/chainstate/nakamoto/miner.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,21 @@ pub struct MinerTenureInfo<'a> {
150150
pub tenure_block_commit_opt: Option<LeaderBlockCommitOp>,
151151
}
152152

153+
/// Structure returned from `NakamotoBlockBuilder::build_nakamoto_block` with
154+
/// information about the block that was built.
155+
pub struct BlockMetadata {
156+
/// The block that was built
157+
pub block: NakamotoBlock,
158+
/// The execution cost consumed so far by the current tenure
159+
pub tenure_consumed: ExecutionCost,
160+
/// The cost budget for the current tenure
161+
pub tenure_budget: ExecutionCost,
162+
/// The size of the blocks in the current tenure in bytes
163+
pub tenure_size: u64,
164+
/// The events emitted by the transactions included in this block
165+
pub tx_events: Vec<TransactionEvent>,
166+
}
167+
153168
impl NakamotoBlockBuilder {
154169
/// Make a block builder from genesis (testing only)
155170
pub fn new_first_block(
@@ -526,7 +541,7 @@ impl NakamotoBlockBuilder {
526541
settings: BlockBuilderSettings,
527542
event_observer: Option<&dyn MemPoolEventDispatcher>,
528543
signer_bitvec_len: u16,
529-
) -> Result<(NakamotoBlock, ExecutionCost, u64, Vec<TransactionEvent>), Error> {
544+
) -> Result<BlockMetadata, Error> {
530545
let (tip_consensus_hash, tip_block_hash, tip_height) = (
531546
parent_stacks_header.consensus_hash.clone(),
532547
parent_stacks_header.anchored_header.block_hash(),
@@ -556,7 +571,7 @@ impl NakamotoBlockBuilder {
556571
builder.load_tenure_info(&mut chainstate, burn_dbconn, tenure_info.cause())?;
557572
let mut tenure_tx = builder.tenure_begin(burn_dbconn, &mut miner_tenure_info)?;
558573

559-
let block_limit = tenure_tx
574+
let tenure_budget = tenure_tx
560575
.block_limit()
561576
.expect("Failed to obtain block limit from miner's block connection");
562577

@@ -570,7 +585,7 @@ impl NakamotoBlockBuilder {
570585
(1..=100).contains(&percentage),
571586
"BUG: tenure_cost_limit_per_block_percentage: {percentage}%. Must be between between 1 and 100"
572587
);
573-
let mut remaining_limit = block_limit.clone();
588+
let mut remaining_limit = tenure_budget.clone();
574589
let cost_so_far = tenure_tx.cost_so_far();
575590
if remaining_limit.sub(&cost_so_far).is_ok() && remaining_limit.divide(100).is_ok() {
576591
remaining_limit.multiply(percentage.into()).expect(
@@ -581,7 +596,7 @@ impl NakamotoBlockBuilder {
581596
"Setting soft limit for clarity cost to {percentage}% of remaining block limit";
582597
"remaining_limit" => %remaining_limit,
583598
"cost_so_far" => %cost_so_far,
584-
"block_limit" => %block_limit,
599+
"block_limit" => %tenure_budget,
585600
);
586601
soft_limit = Some(remaining_limit);
587602
};
@@ -630,13 +645,13 @@ impl NakamotoBlockBuilder {
630645

631646
// save the block so we can build microblocks off of it
632647
let block = builder.mine_nakamoto_block(&mut tenure_tx);
633-
let size = builder.bytes_so_far;
634-
let consumed = builder.tenure_finish(tenure_tx)?;
648+
let tenure_size = builder.bytes_so_far;
649+
let tenure_consumed = builder.tenure_finish(tenure_tx)?;
635650

636651
let ts_end = get_epoch_time_ms();
637652

638653
set_last_mined_block_transaction_count(block.txs.len() as u64);
639-
set_last_mined_execution_cost_observed(&consumed, &block_limit);
654+
set_last_mined_execution_cost_observed(&tenure_consumed, &tenure_budget);
640655

641656
info!(
642657
"Miner: mined Nakamoto block";
@@ -645,14 +660,20 @@ impl NakamotoBlockBuilder {
645660
"height" => block.header.chain_length,
646661
"tx_count" => block.txs.len(),
647662
"parent_block_id" => %block.header.parent_block_id,
648-
"block_size" => size,
649-
"execution_consumed" => %consumed,
650-
"percent_full" => block_limit.proportion_largest_dimension(&consumed),
663+
"block_size" => tenure_size,
664+
"execution_consumed" => %tenure_consumed,
665+
"percent_full" => tenure_budget.proportion_largest_dimension(&tenure_consumed),
651666
"assembly_time_ms" => ts_end.saturating_sub(ts_start),
652667
"consensus_hash" => %block.header.consensus_hash
653668
);
654669

655-
Ok((block, consumed, size, tx_events))
670+
Ok(BlockMetadata {
671+
block,
672+
tenure_consumed,
673+
tenure_budget,
674+
tenure_size,
675+
tx_events,
676+
})
656677
}
657678

658679
pub fn get_bytes_so_far(&self) -> u64 {

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2469,7 +2469,7 @@ impl NakamotoChainState {
24692469
) -> Result<bool, ChainstateError> {
24702470
test_debug!("Consider Nakamoto block {}", &block.block_id());
24712471
// do nothing if we already have this block
2472-
if let Some(_) = Self::get_block_header(headers_conn, &block.header.block_id())? {
2472+
if Self::get_block_header(headers_conn, &block.header.block_id())?.is_some() {
24732473
debug!("Already have block {}", &block.header.block_id());
24742474
return Ok(false);
24752475
}

stackslib/src/chainstate/stacks/block.rs

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -353,16 +353,13 @@ impl StacksMessageCodec for StacksBlock {
353353
// must be only one coinbase
354354
let mut coinbase_count = 0;
355355
for tx in txs.iter() {
356-
match tx.payload {
357-
TransactionPayload::Coinbase(..) => {
358-
coinbase_count += 1;
359-
if coinbase_count > 1 {
360-
return Err(codec_error::DeserializeError(
361-
"Invalid block: multiple coinbases found".to_string(),
362-
));
363-
}
356+
if let TransactionPayload::Coinbase(..) = tx.payload {
357+
coinbase_count += 1;
358+
if coinbase_count > 1 {
359+
return Err(codec_error::DeserializeError(
360+
"Invalid block: multiple coinbases found".to_string(),
361+
));
364362
}
365-
_ => {}
366363
}
367364
}
368365

@@ -515,26 +512,23 @@ impl StacksBlock {
515512
let mut found_coinbase = false;
516513
let mut coinbase_index = 0;
517514
for (i, tx) in txs.iter().enumerate() {
518-
match tx.payload {
519-
TransactionPayload::Coinbase(..) => {
520-
if !check_present {
521-
warn!("Found unexpected coinbase tx {}", tx.txid());
522-
return false;
523-
}
524-
525-
if found_coinbase {
526-
warn!("Found duplicate coinbase tx {}", tx.txid());
527-
return false;
528-
}
529-
530-
if tx.anchor_mode != TransactionAnchorMode::OnChainOnly {
531-
warn!("Invalid coinbase tx {}: not on-chain only", tx.txid());
532-
return false;
533-
}
534-
found_coinbase = true;
535-
coinbase_index = i;
515+
if let TransactionPayload::Coinbase(..) = tx.payload {
516+
if !check_present {
517+
warn!("Found unexpected coinbase tx {}", tx.txid());
518+
return false;
519+
}
520+
521+
if found_coinbase {
522+
warn!("Found duplicate coinbase tx {}", tx.txid());
523+
return false;
524+
}
525+
526+
if tx.anchor_mode != TransactionAnchorMode::OnChainOnly {
527+
warn!("Invalid coinbase tx {}: not on-chain only", tx.txid());
528+
return false;
536529
}
537-
_ => {}
530+
found_coinbase = true;
531+
coinbase_index = i;
538532
}
539533
}
540534

stackslib/src/chainstate/stacks/boot/contract_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ impl BurnStateDB for TestSimBurnStateDB {
486486
height: u32,
487487
sortition_id: &SortitionId,
488488
) -> Option<(Vec<TupleData>, u128)> {
489-
if let Some(_) = self.get_burn_header_hash(height, sortition_id) {
489+
if self.get_burn_header_hash(height, sortition_id).is_some() {
490490
let first_block = self.get_burn_start_height();
491491
let prepare_len = self.get_pox_prepare_length();
492492
let rc_len = self.get_pox_reward_cycle_length();

0 commit comments

Comments
 (0)