Skip to content

Commit b813afa

Browse files
committed
merged with develop
2 parents 151c844 + fb6f2b7 commit b813afa

File tree

11 files changed

+445
-453
lines changed

11 files changed

+445
-453
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 2 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

CHANGELOG.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ 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+
- 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
1613

1714
### Changed
1815

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

2220
### Fixed
2321

stacks-signer/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to the versioning scheme outlined in the [README.md](README.md).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Add `dry_run` configuration option to `stacks-signer` config toml. Dry run mode will
13+
run the signer binary as if it were a registered signer. Instead of broadcasting
14+
`StackerDB` messages, it logs `INFO` messages. Other interactions with the `stacks-node`
15+
behave normally (e.g., submitting validation requests, submitting finished blocks). A
16+
dry run signer will error out if the supplied key is actually a registered signer.
17+
818
## [3.1.0.0.4.0]
919

1020
## Added

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/cli.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use crate::chainstate::burn::db::sortdb::{
4040
};
4141
use crate::chainstate::burn::{BlockSnapshot, ConsensusHash};
4242
use crate::chainstate::coordinator::OnChainRewardSetProvider;
43-
use crate::chainstate::nakamoto::miner::{NakamotoBlockBuilder, NakamotoTenureInfo};
43+
use crate::chainstate::nakamoto::miner::{BlockMetadata, NakamotoBlockBuilder, NakamotoTenureInfo};
4444
use crate::chainstate::nakamoto::{NakamotoBlock, NakamotoChainState};
4545
use crate::chainstate::stacks::db::blocks::StagingBlock;
4646
use crate::chainstate::stacks::db::{StacksBlockHeaderTypes, StacksChainState, StacksHeaderInfo};
@@ -504,7 +504,21 @@ pub fn command_try_mine(argv: &[String], conf: Option<&Config>) {
504504
None,
505505
0,
506506
)
507-
.map(|(block, cost, size, _)| (block.header.block_hash(), block.txs, cost, size))
507+
.map(
508+
|BlockMetadata {
509+
block,
510+
tenure_consumed,
511+
tenure_size,
512+
..
513+
}| {
514+
(
515+
block.header.block_hash(),
516+
block.txs,
517+
tenure_consumed,
518+
tenure_size,
519+
)
520+
},
521+
)
508522
}
509523
};
510524

stackslib/src/config/mod.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,41 @@ pub const OP_TX_ANY_ESTIM_SIZE: u64 = fmax!(
8686
OP_TX_VOTE_AGG_ESTIM_SIZE
8787
);
8888

89+
/// Default maximum percentage of `satoshis_per_byte` that a Bitcoin fee rate
90+
/// may be increased to when RBFing a transaction
8991
const DEFAULT_MAX_RBF_RATE: u64 = 150; // 1.5x
92+
/// Amount to increment the fee by, in Sats/vByte, when RBFing a Bitcoin
93+
/// transaction
9094
const DEFAULT_RBF_FEE_RATE_INCREMENT: u64 = 5;
95+
/// Default number of reward cycles of blocks to sync in a non-full inventory
96+
/// sync
9197
const INV_REWARD_CYCLES_TESTNET: u64 = 6;
98+
/// Default minimum time to wait between mining blocks in milliseconds. The
99+
/// value must be greater than or equal to 1000 ms because if a block is mined
100+
/// within the same second as its parent, it will be rejected by the signers.
92101
const DEFAULT_MIN_TIME_BETWEEN_BLOCKS_MS: u64 = 1_000;
102+
/// Default time in milliseconds to pause after receiving the first threshold
103+
/// rejection, before proposing a new block.
93104
const DEFAULT_FIRST_REJECTION_PAUSE_MS: u64 = 5_000;
105+
/// Default time in milliseconds to pause after receiving subsequent threshold
106+
/// rejections, before proposing a new block.
94107
const DEFAULT_SUBSEQUENT_REJECTION_PAUSE_MS: u64 = 10_000;
108+
/// Default time in milliseconds to wait for a Nakamoto block after seeing a
109+
/// burnchain block before submitting a block commit.
95110
const DEFAULT_BLOCK_COMMIT_DELAY_MS: u64 = 20_000;
111+
/// Default percentage of the remaining tenure cost limit to consume each block
96112
const DEFAULT_TENURE_COST_LIMIT_PER_BLOCK_PERCENTAGE: u8 = 25;
113+
/// Default number of seconds to wait in-between polling the sortition DB to
114+
/// see if we need to extend the ongoing tenure (e.g. because the current
115+
/// sortition is empty or invalid).
97116
const DEFAULT_TENURE_EXTEND_POLL_SECS: u64 = 1;
98-
99-
// This should be greater than the signers' timeout. This is used for issuing fallback tenure extends
100-
const DEFAULT_TENURE_TIMEOUT_SECS: u64 = 420;
117+
/// Default duration to wait before attempting to issue a tenure extend.
118+
/// This should be greater than the signers' timeout. This is used for issuing
119+
/// fallback tenure extends
120+
const DEFAULT_TENURE_TIMEOUT_SECS: u64 = 180;
121+
/// Default percentage of block budget that must be used before attempting a
122+
/// time-based tenure extend
123+
const DEFAULT_TENURE_EXTEND_COST_THRESHOLD: u64 = 50;
101124

102125
static HELIUM_DEFAULT_CONNECTION_OPTIONS: LazyLock<ConnectionOptions> =
103126
LazyLock::new(|| ConnectionOptions {
@@ -1191,9 +1214,13 @@ pub struct BurnchainConfig {
11911214
pub process_exit_at_block_height: Option<u64>,
11921215
pub poll_time_secs: u64,
11931216
pub satoshis_per_byte: u64,
1217+
/// Maximum percentage of `satoshis_per_byte` that a Bitcoin fee rate may
1218+
/// be increased to when RBFing a transaction
11941219
pub max_rbf: u64,
11951220
pub leader_key_tx_estimated_size: u64,
11961221
pub block_commit_tx_estimated_size: u64,
1222+
/// Amount to increment the fee by, in Sats/vByte, when RBFing a Bitcoin
1223+
/// transaction
11971224
pub rbf_fee_increment: u64,
11981225
pub first_burn_block_height: Option<u64>,
11991226
pub first_burn_block_timestamp: Option<u32>,
@@ -2155,6 +2182,8 @@ pub struct MinerConfig {
21552182
pub tenure_extend_poll_secs: Duration,
21562183
/// Duration to wait before attempting to issue a tenure extend
21572184
pub tenure_timeout: Duration,
2185+
/// Percentage of block budget that must be used before attempting a time-based tenure extend
2186+
pub tenure_extend_cost_threshold: u64,
21582187
/// Define the timeout to apply while waiting for signers responses, based on the amount of rejections
21592188
pub block_rejection_timeout_steps: HashMap<u32, Duration>,
21602189
}
@@ -2195,6 +2224,8 @@ impl Default for MinerConfig {
21952224
),
21962225
tenure_extend_poll_secs: Duration::from_secs(DEFAULT_TENURE_EXTEND_POLL_SECS),
21972226
tenure_timeout: Duration::from_secs(DEFAULT_TENURE_TIMEOUT_SECS),
2227+
tenure_extend_cost_threshold: DEFAULT_TENURE_EXTEND_COST_THRESHOLD,
2228+
21982229
block_rejection_timeout_steps: {
21992230
let mut rejections_timeouts_default_map = HashMap::<u32, Duration>::new();
22002231
rejections_timeouts_default_map.insert(0, Duration::from_secs(600));
@@ -2599,6 +2630,7 @@ pub struct MinerConfigFile {
25992630
pub tenure_cost_limit_per_block_percentage: Option<u8>,
26002631
pub tenure_extend_poll_secs: Option<u64>,
26012632
pub tenure_timeout_secs: Option<u64>,
2633+
pub tenure_extend_cost_threshold: Option<u64>,
26022634
pub block_rejection_timeout_steps: Option<HashMap<String, u64>>,
26032635
}
26042636

@@ -2742,6 +2774,8 @@ impl MinerConfigFile {
27422774
tenure_cost_limit_per_block_percentage,
27432775
tenure_extend_poll_secs: self.tenure_extend_poll_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_extend_poll_secs),
27442776
tenure_timeout: self.tenure_timeout_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_timeout),
2777+
tenure_extend_cost_threshold: self.tenure_extend_cost_threshold.unwrap_or(miner_default_config.tenure_extend_cost_threshold),
2778+
27452779
block_rejection_timeout_steps: {
27462780
if let Some(block_rejection_timeout_items) = self.block_rejection_timeout_steps {
27472781
let mut rejection_timeout_durations = HashMap::<u32, Duration>::new();

stackslib/src/net/connection.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ pub struct ConnectionOptions {
379379
/// Units are milliseconds. A value of 0 means "never".
380380
pub log_neighbors_freq: u64,
381381
pub inv_sync_interval: u64,
382+
// how many reward cycles of blocks to sync in a non-full inventory sync
382383
pub inv_reward_cycles: u64,
383384
pub download_interval: u64,
384385
pub pingback_timeout: u64,

0 commit comments

Comments
 (0)