Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/block rejections timeout heuristic #5731

Merged
merged 44 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
ea771ca
added heuristic for block rejections timeout
rdeioris Jan 22, 2025
daffba1
Merge branch 'develop' into feat/block_rejections_heuristic
rdeioris Jan 22, 2025
6ab756b
added rejections_timeout test exposure via BLOCK_REJECTIONS_CURRENT_T…
rdeioris Jan 22, 2025
bfd4793
improved test logic
rdeioris Jan 22, 2025
3cebb35
fixed integration test
rdeioris Jan 22, 2025
db14fba
Merge branch 'develop' into feat/block_rejections_heuristic
rdeioris Jan 22, 2025
c3e163e
fixed comment for BLOCK_REJECTIONS_CURRENT_TIMEOUT
rdeioris Jan 22, 2025
6b751c4
fixed test comment
rdeioris Jan 22, 2025
bb8df99
fmt
rdeioris Jan 22, 2025
280483b
added more comments
rdeioris Jan 22, 2025
05b3f92
fixed formatting
rdeioris Jan 23, 2025
9971d1a
added wanr! when timeout
rdeioris Jan 24, 2025
45ae015
initial prototype for configurable block_rejction timeout steps
rdeioris Jan 28, 2025
3071d36
improved config system
rdeioris Jan 29, 2025
f2ab500
fmt-stacks
rdeioris Jan 29, 2025
5c0805a
fixed default rejections timeout
rdeioris Jan 29, 2025
f22a990
improved comment for rejections timeout
rdeioris Jan 29, 2025
4f4b584
fixed typo
rdeioris Jan 29, 2025
463839f
ensure 0 key is specified for rejections timeout
rdeioris Jan 29, 2025
0e7461c
message typo
rdeioris Jan 29, 2025
420f861
use Counters instead of global test vars
rdeioris Jan 30, 2025
57f80fb
restored original wait_for_block_status
rdeioris Jan 30, 2025
d5abfdc
removed empty line
rdeioris Jan 30, 2025
ed48786
Merge branch 'develop' into feat/block_rejections_heuristic
rdeioris Jan 30, 2025
5269714
updated CHANGELOG
rdeioris Jan 30, 2025
5a70c43
updated CHANGELOG
rdeioris Jan 30, 2025
c424212
Secp256k1PrivateKey::random() instrad of new()
rdeioris Jan 30, 2025
d713290
removed useless test attributes
rdeioris Jan 30, 2025
adaabe6
use u32 for block_rejection_timeout_steps keys
rdeioris Jan 30, 2025
7cfbfdd
refactored block_rejection_timeout_steps percentage setup
rdeioris Jan 30, 2025
d4171d7
do not reset rejections_timer on block_status updates
rdeioris Jan 30, 2025
fbc3b7d
moved block_rejection_timeout_steps computation directly in SignerCoo…
rdeioris Jan 30, 2025
33642c3
Merge branch 'develop' into feat/block_rejections_heuristic
rdeioris Jan 31, 2025
790c1e1
merged with develop, reintroduces old logic for condition variables, …
rdeioris Jan 31, 2025
54aed16
rollback BlockStatus Default and PartialEq
rdeioris Jan 31, 2025
eb883ee
improved error messages on timeout
rdeioris Jan 31, 2025
fe429f4
report rejection step in miner log, ensure signe_test shutdown in int…
rdeioris Jan 31, 2025
6a238a7
added set_miner_current_rejections_timeout and set_miner_current_reje…
rdeioris Jan 31, 2025
8d2bb0d
refactored block_validation_check_rejection_timeout_heuristic test
rdeioris Feb 1, 2025
151c844
use From based cast for u32->u64
rdeioris Feb 1, 2025
b813afa
merged with develop
rdeioris Feb 1, 2025
f66c894
removed useless line
rdeioris Feb 1, 2025
0c86012
Merge branch 'develop' into feat/block_rejections_heuristic
rdeioris Feb 3, 2025
400c806
use u32 for rejections counter
rdeioris Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE

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

### Fixed

Expand Down
7 changes: 7 additions & 0 deletions stackslib/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,8 @@ pub struct MinerConfig {
pub tenure_extend_poll_secs: Duration,
/// Duration to wait before attempting to issue a tenure extend
pub tenure_timeout: Duration,
/// Percentage of block budget that must be used before attempting a time-based tenure extend
pub tenure_extend_cost_threshold: u64,
/// Define the timeout to apply while waiting for signers responses, based on the amount of rejections
pub block_rejection_timeout_steps: HashMap<u32, Duration>,
}
Expand Down Expand Up @@ -2222,6 +2224,8 @@ impl Default for MinerConfig {
),
tenure_extend_poll_secs: Duration::from_secs(DEFAULT_TENURE_EXTEND_POLL_SECS),
tenure_timeout: Duration::from_secs(DEFAULT_TENURE_TIMEOUT_SECS),
tenure_extend_cost_threshold: DEFAULT_TENURE_EXTEND_COST_THRESHOLD,

block_rejection_timeout_steps: {
let mut rejections_timeouts_default_map = HashMap::<u32, Duration>::new();
rejections_timeouts_default_map.insert(0, Duration::from_secs(600));
Expand Down Expand Up @@ -2626,6 +2630,7 @@ pub struct MinerConfigFile {
pub tenure_cost_limit_per_block_percentage: Option<u8>,
pub tenure_extend_poll_secs: Option<u64>,
pub tenure_timeout_secs: Option<u64>,
pub tenure_extend_cost_threshold: Option<u64>,
pub block_rejection_timeout_steps: Option<HashMap<String, u64>>,
}

Expand Down Expand Up @@ -2769,6 +2774,8 @@ impl MinerConfigFile {
tenure_cost_limit_per_block_percentage,
tenure_extend_poll_secs: self.tenure_extend_poll_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_extend_poll_secs),
tenure_timeout: self.tenure_timeout_secs.map(Duration::from_secs).unwrap_or(miner_default_config.tenure_timeout),
tenure_extend_cost_threshold: self.tenure_extend_cost_threshold.unwrap_or(miner_default_config.tenure_extend_cost_threshold),

block_rejection_timeout_steps: {
if let Some(block_rejection_timeout_items) = self.block_rejection_timeout_steps {
let mut rejection_timeout_durations = HashMap::<u32, Duration>::new();
Expand Down
6 changes: 3 additions & 3 deletions testnet/stacks-node/src/nakamoto_node/signer_coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ impl SignerCoordinator {
return false;
}
// number or rejections changed?
if status.total_reject_weight as u64 != rejections {
if u64::from(status.total_reject_weight) != rejections {
rdeioris marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
// enough signatures?
Expand Down Expand Up @@ -388,8 +388,8 @@ impl SignerCoordinator {
}
};

if rejections != block_status.total_reject_weight as u64 {
rejections = block_status.total_reject_weight as u64;
if rejections != u64::from(block_status.total_reject_weight) {
rejections = u64::from(block_status.total_reject_weight);
let (rejections_step, new_rejections_timeout) = self
.block_rejection_timeout_steps
.range((Included(0), Included(rejections)))
Expand Down
1 change: 0 additions & 1 deletion testnet/stacks-node/src/tests/signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,6 @@ fn setup_stx_btc_node<G: FnMut(&mut NeonConfig)>(
let counters = run_loop.counters();

let coord_channel = run_loop.coordinator_channels();

let run_loop_thread = thread::spawn(move || run_loop.start(None, 0));

// Give the run loop some time to start up!
Expand Down
183 changes: 33 additions & 150 deletions testnet/stacks-node/src/tests/signer/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7951,166 +7951,49 @@ fn block_validation_check_rejection_timeout_heuristic() {

// note we just use mined nakamoto_blocks as the second block is not going to be confirmed

rdeioris marked this conversation as resolved.
Show resolved Hide resolved
info!("------------------------- Check Rejections-based timeout with 1 rejection -------------------------");
let mut test_rejections = |signer_split_index: usize, expected_timeout: u64| {
let blocks_before = test_observer::get_mined_nakamoto_blocks().len();
let (ignore_signers, reject_signers) = all_signers.split_at(signer_split_index);

let blocks_before = test_observer::get_mined_nakamoto_blocks().len();
info!("------------------------- Check Rejections-based timeout with {} rejections -------------------------", reject_signers.len());

TEST_REJECT_ALL_BLOCK_PROPOSAL.set(vec![all_signers[19]]);
TEST_IGNORE_ALL_BLOCK_PROPOSALS.set(all_signers[0..19].to_vec());
TEST_REJECT_ALL_BLOCK_PROPOSAL.set(reject_signers.to_vec());
TEST_IGNORE_ALL_BLOCK_PROPOSALS.set(ignore_signers.to_vec());

next_block_and(
&mut signer_test.running_nodes.btc_regtest_controller,
30,
|| Ok(test_observer::get_mined_nakamoto_blocks().len() > blocks_before),
)
.unwrap();

signer_test
.wait_for_block_rejections(timeout.as_secs(), &[all_signers[19]])
.unwrap();

wait_for(60, || {
Ok(signer_test
.running_nodes
.counters
.naka_miner_current_rejections
.get()
>= 1)
})
.unwrap();
assert_eq!(
signer_test
.running_nodes
.counters
.naka_miner_current_rejections_timeout_secs
.get(),
123
);

info!("------------------------- Check Rejections-based timeout with 2 rejections -------------------------");

let blocks_before = test_observer::get_mined_nakamoto_blocks().len();

TEST_REJECT_ALL_BLOCK_PROPOSAL.set(vec![all_signers[18], all_signers[19]]);
TEST_IGNORE_ALL_BLOCK_PROPOSALS.set(all_signers[0..18].to_vec());

next_block_and(
&mut signer_test.running_nodes.btc_regtest_controller,
30,
|| Ok(test_observer::get_mined_nakamoto_blocks().len() > blocks_before),
)
.unwrap();

signer_test
.wait_for_block_rejections(timeout.as_secs(), &[all_signers[18], all_signers[19]])
.unwrap();

wait_for(60, || {
Ok(signer_test
.running_nodes
.counters
.naka_miner_current_rejections
.get()
>= 2)
})
.unwrap();
assert_eq!(
signer_test
.running_nodes
.counters
.naka_miner_current_rejections_timeout_secs
.get(),
20
);

info!("------------------------- Check Rejections-based timeout with 3 rejections -------------------------");

let blocks_before = test_observer::get_mined_nakamoto_blocks().len();

TEST_REJECT_ALL_BLOCK_PROPOSAL.set(vec![all_signers[17], all_signers[18], all_signers[19]]);
TEST_IGNORE_ALL_BLOCK_PROPOSALS.set(all_signers[0..17].to_vec());

next_block_and(
&mut signer_test.running_nodes.btc_regtest_controller,
30,
|| Ok(test_observer::get_mined_nakamoto_blocks().len() > blocks_before),
)
.unwrap();

signer_test
.wait_for_block_rejections(
timeout.as_secs(),
&[all_signers[17], all_signers[18], all_signers[19]],
next_block_and(
&mut signer_test.running_nodes.btc_regtest_controller,
30,
|| Ok(test_observer::get_mined_nakamoto_blocks().len() > blocks_before),
)
.unwrap();

wait_for(60, || {
Ok(signer_test
.running_nodes
.counters
.naka_miner_current_rejections
.get()
>= 3)
})
.unwrap();

assert_eq!(
signer_test
.running_nodes
.counters
.naka_miner_current_rejections_timeout_secs
.get(),
10
);

info!("------------------------- Check Rejections-based timeout with 4 rejections -------------------------");

let blocks_before = test_observer::get_mined_nakamoto_blocks().len();

TEST_REJECT_ALL_BLOCK_PROPOSAL.set(vec![
all_signers[16],
all_signers[17],
all_signers[18],
all_signers[19],
]);
TEST_IGNORE_ALL_BLOCK_PROPOSALS.set(all_signers[0..16].to_vec());

next_block_and(
&mut signer_test.running_nodes.btc_regtest_controller,
30,
|| Ok(test_observer::get_mined_nakamoto_blocks().len() > blocks_before),
)
.unwrap();
.wait_for_block_rejections(timeout.as_secs(), &reject_signers)
.unwrap();

signer_test
.wait_for_block_rejections(
timeout.as_secs(),
&[
all_signers[16],
all_signers[17],
all_signers[18],
all_signers[19],
],
)
wait_for(60, || {
Ok(signer_test
.running_nodes
.counters
.naka_miner_current_rejections
.get()
>= reject_signers.len() as u64)
})
.unwrap();
assert_eq!(
signer_test
.running_nodes
.counters
.naka_miner_current_rejections_timeout_secs
.get(),
expected_timeout
);
};

wait_for(60, || {
Ok(signer_test
.running_nodes
.counters
.naka_miner_current_rejections
.get()
>= 4)
})
.unwrap();
assert_eq!(
signer_test
.running_nodes
.counters
.naka_miner_current_rejections_timeout_secs
.get(),
99
);
test_rejections(19, 123);
test_rejections(18, 20);
test_rejections(17, 10);
test_rejections(16, 99);

// reset reject/ignore
TEST_REJECT_ALL_BLOCK_PROPOSAL.set(vec![]);
Expand Down
Loading