Skip to content

Commit d122532

Browse files
committed
Refactor Sync Rate Rule
- Makes it look like any other mining rule
1 parent 8a28443 commit d122532

File tree

6 files changed

+96
-65
lines changed

6 files changed

+96
-65
lines changed

protocol/mining/src/rule_engine.rs

Lines changed: 18 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use std::{
2-
sync::{
3-
atomic::{AtomicBool, Ordering},
4-
Arc,
5-
},
2+
sync::{atomic::AtomicBool, Arc},
63
time::{Duration, Instant},
74
};
85

@@ -20,14 +17,16 @@ use kaspa_core::{
2017
tick::{TickReason, TickService},
2118
},
2219
time::unix_now,
23-
trace, warn,
20+
trace,
2421
};
2522
use kaspa_p2p_lib::Hub;
2623

27-
use crate::rules::{blue_parents_only_rule::BlueParentsOnlyRule, mining_rule::MiningRule, no_transactions_rule::NoTransactionsRule};
24+
use crate::rules::{
25+
blue_parents_only_rule::BlueParentsOnlyRule, mining_rule::MiningRule, no_transactions_rule::NoTransactionsRule,
26+
sync_rate_rule::SyncRateRule, ExtraData,
27+
};
2828

2929
const RULE_ENGINE: &str = "mining-rule-engine";
30-
const SYNC_RATE_THRESHOLD: f64 = 0.10;
3130

3231
#[derive(Clone)]
3332
pub struct MiningRuleEngine {
@@ -68,59 +67,25 @@ impl MiningRuleEngine {
6867
let delta = &snapshot - &last_snapshot;
6968

7069
if elapsed_time.as_secs() > 0 {
71-
let expected_blocks = (elapsed_time.as_millis() as u64) / self.config.target_time_per_block;
72-
let received_blocks = delta.body_counts.max(delta.header_counts);
73-
let rate: f64 = (received_blocks as f64) / (expected_blocks as f64);
74-
7570
let session = self.consensus_manager.consensus().unguarded_session();
7671

7772
let finality_point = session.async_finality_point().await;
7873
let finality_point_timestamp = session.async_get_header(finality_point).await.unwrap().timestamp;
79-
// Finality point is considered "recent" if it is within 3 finality durations from the current time
80-
let is_finality_recent = finality_point_timestamp >= unix_now().saturating_sub(self.config.finality_duration() * 3);
81-
82-
trace!(
83-
"Sync rate: {:.2} | Finality point recent: {} | Elapsed time: {}s | Connected: {} | Found/Expected blocks: {}/{}",
84-
rate,
85-
is_finality_recent,
86-
elapsed_time.as_secs(),
87-
delta.body_counts,
88-
self.has_sufficient_peer_connectivity(),
89-
expected_blocks,
90-
);
91-
92-
if is_finality_recent && rate < SYNC_RATE_THRESHOLD {
93-
// if sync rate rule conditions are met:
94-
if let Ok(false) = self.use_sync_rate_rule.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) {
95-
warn!("Sync rate {:.2} is below threshold: {}", rate, SYNC_RATE_THRESHOLD);
96-
}
97-
} else {
98-
// else when sync rate conditions are not met:
99-
if let Ok(true) = self.use_sync_rate_rule.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) {
100-
if !is_finality_recent {
101-
warn!("Sync rate {:.2} recovered: {} by entering IBD", rate, SYNC_RATE_THRESHOLD);
102-
} else {
103-
warn!("Sync rate {:.2} recovered: {}", rate, SYNC_RATE_THRESHOLD);
104-
}
105-
} else if !is_finality_recent {
106-
trace!("Finality period is old. Timestamp: {}. Sync rate: {:.2}", finality_point_timestamp, rate);
107-
}
108-
}
10974

110-
// END - Sync monitor
75+
let extra_data = ExtraData {
76+
finality_point_timestamp,
77+
target_time_per_block: self.config.target_time_per_block,
78+
has_sufficient_peer_connectivity: self.has_sufficient_peer_connectivity(),
79+
finality_duration: self.config.finality_duration(),
80+
elapsed_time,
81+
};
11182

112-
// START - Rule Engine
11383
trace!("Current Mining Rule: {:?}", self.mining_rules);
11484

115-
// Blue Parents Only Check:
85+
// Check for all the rules
11686
for rule in &self.rules {
117-
rule.check_rule(&snapshot);
87+
rule.check_rule(&delta, &extra_data);
11888
}
119-
120-
// No Transactions Check:
121-
// TODO: implement this part
122-
123-
// End - Rule Engine
12489
}
12590

12691
last_snapshot = snapshot;
@@ -136,21 +101,14 @@ impl MiningRuleEngine {
136101
hub: Hub,
137102
mining_rules: Arc<MiningRules>,
138103
) -> Self {
104+
let use_sync_rate_rule = Arc::new(AtomicBool::new(false));
139105
let rules: Vec<Arc<(dyn MiningRule + 'static)>> = vec![
106+
Arc::new(SyncRateRule::new(use_sync_rate_rule.clone())),
140107
Arc::new(BlueParentsOnlyRule::new(mining_rules.blue_parents_only.clone())),
141108
Arc::new(NoTransactionsRule::new(mining_rules.no_transactions.clone())),
142109
];
143110

144-
Self {
145-
consensus_manager,
146-
config,
147-
processing_counters,
148-
tick_service,
149-
hub,
150-
use_sync_rate_rule: Arc::new(AtomicBool::new(false)),
151-
mining_rules,
152-
rules,
153-
}
111+
Self { consensus_manager, config, processing_counters, tick_service, hub, use_sync_rate_rule, mining_rules, rules }
154112
}
155113

156114
pub fn should_mine(&self, sink_daa_score_timestamp: DaaScoreTimestamp) -> bool {

protocol/mining/src/rules/blue_parents_only_rule.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::{
66
use kaspa_consensus_core::api::counters::ProcessingCountersSnapshot;
77
use kaspa_core::{trace, warn};
88

9-
use super::mining_rule::MiningRule;
9+
use super::{mining_rule::MiningRule, ExtraData};
1010

1111
const VIRTUAL_PROCESSING_TRIGGER_THRESHOLD: f64 = 500.0; // 500 milliseconds
1212
const VIRTUAL_PROCESSING_RECOVERY_THRESHOLD: f64 = 100.0; // 100 milliseconds
@@ -22,7 +22,7 @@ impl BlueParentsOnlyRule {
2222
}
2323

2424
impl MiningRule for BlueParentsOnlyRule {
25-
fn check_rule(&self, delta: &ProcessingCountersSnapshot) {
25+
fn check_rule(&self, delta: &ProcessingCountersSnapshot, _extra_data: &ExtraData) {
2626
let received_blocks = delta.body_counts.max(delta.header_counts) as f64;
2727
let virtual_processing_avg_time_per_block_ms =
2828
if received_blocks > 0.0 { (delta.virtual_processing_time as f64) / received_blocks } else { 0.0 };
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use kaspa_consensus_core::api::counters::ProcessingCountersSnapshot;
22

3+
use super::ExtraData;
4+
35
pub trait MiningRule: Send + Sync + 'static {
4-
fn check_rule(&self, delta: &ProcessingCountersSnapshot);
6+
fn check_rule(&self, delta: &ProcessingCountersSnapshot, extra_data: &ExtraData);
57
}

protocol/mining/src/rules/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1+
use std::time::Duration;
2+
13
pub mod blue_parents_only_rule;
24
pub mod no_transactions_rule;
5+
pub mod sync_rate_rule;
36

47
pub mod mining_rule;
8+
9+
pub struct ExtraData {
10+
pub finality_point_timestamp: u64,
11+
pub target_time_per_block: u64,
12+
pub has_sufficient_peer_connectivity: bool,
13+
pub finality_duration: u64,
14+
pub elapsed_time: Duration,
15+
}

protocol/mining/src/rules/no_transactions_rule.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::sync::{atomic::AtomicBool, Arc};
22

33
use kaspa_consensus_core::api::counters::ProcessingCountersSnapshot;
44

5-
use super::mining_rule::MiningRule;
5+
use super::{mining_rule::MiningRule, ExtraData};
66

77
pub struct NoTransactionsRule {
88
pub is_enabled: Arc<AtomicBool>,
@@ -15,7 +15,7 @@ impl NoTransactionsRule {
1515
}
1616

1717
impl MiningRule for NoTransactionsRule {
18-
fn check_rule(&self, _delta: &ProcessingCountersSnapshot) {
18+
fn check_rule(&self, _delta: &ProcessingCountersSnapshot, _extra_data: &ExtraData) {
1919
// TODO: Add the rule and recovery condition
2020
}
2121
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use std::sync::{
2+
atomic::{AtomicBool, Ordering},
3+
Arc,
4+
};
5+
6+
use kaspa_consensus_core::api::counters::ProcessingCountersSnapshot;
7+
use kaspa_core::{time::unix_now, trace, warn};
8+
9+
use super::{mining_rule::MiningRule, ExtraData};
10+
11+
const SYNC_RATE_THRESHOLD: f64 = 0.10;
12+
13+
pub struct SyncRateRule {
14+
pub use_sync_rate_rule: Arc<AtomicBool>,
15+
}
16+
17+
impl SyncRateRule {
18+
pub fn new(use_sync_rate_rule: Arc<AtomicBool>) -> Self {
19+
Self { use_sync_rate_rule }
20+
}
21+
}
22+
23+
impl MiningRule for SyncRateRule {
24+
fn check_rule(&self, delta: &ProcessingCountersSnapshot, extra_data: &ExtraData) {
25+
let expected_blocks = (extra_data.elapsed_time.as_millis() as u64) / extra_data.target_time_per_block;
26+
let received_blocks = delta.body_counts.max(delta.header_counts);
27+
let rate: f64 = (received_blocks as f64) / (expected_blocks as f64);
28+
29+
// Finality point is considered "recent" if it is within 3 finality durations from the current time
30+
let is_finality_recent = extra_data.finality_point_timestamp >= unix_now().saturating_sub(extra_data.finality_duration * 3);
31+
32+
trace!(
33+
"Sync rate: {:.2} | Finality point recent: {} | Elapsed time: {}s | Connected: {} | Found/Expected blocks: {}/{}",
34+
rate,
35+
is_finality_recent,
36+
extra_data.elapsed_time.as_secs(),
37+
extra_data.has_sufficient_peer_connectivity,
38+
delta.body_counts,
39+
expected_blocks,
40+
);
41+
42+
if is_finality_recent && rate < SYNC_RATE_THRESHOLD {
43+
// if sync rate rule conditions are met:
44+
if let Ok(false) = self.use_sync_rate_rule.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) {
45+
warn!("Sync rate {:.2} is below threshold: {}", rate, SYNC_RATE_THRESHOLD);
46+
}
47+
} else {
48+
// else when sync rate conditions are not met:
49+
if let Ok(true) = self.use_sync_rate_rule.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) {
50+
if !is_finality_recent {
51+
warn!("Sync rate {:.2} recovered: {} by entering IBD", rate, SYNC_RATE_THRESHOLD);
52+
} else {
53+
warn!("Sync rate {:.2} recovered: {}", rate, SYNC_RATE_THRESHOLD);
54+
}
55+
} else if !is_finality_recent {
56+
trace!("Finality period is old. Timestamp: {}. Sync rate: {:.2}", extra_data.finality_point_timestamp, rate);
57+
}
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)