Skip to content

Commit 2a2b141

Browse files
authored
refactor: introduce ProgressPercentage trait (#431)
- add the `ProgressPercentage` trait - implement the trait for all progress structs where its relevant - adjust the default value (target_height == 0) for percentage from 1.0 to 0.0 because its more reasonable.
1 parent ea1c825 commit 2a2b141

File tree

17 files changed

+83
-84
lines changed

17 files changed

+83
-84
lines changed

dash-spv-ffi/include/dash_spv_ffi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ typedef struct FFIClientConfig {
5959
*/
6060
typedef struct FFIBlockHeadersProgress {
6161
enum FFISyncState state;
62-
uint32_t current_height;
62+
uint32_t tip_height;
6363
uint32_t target_height;
6464
uint32_t processed;
6565
uint32_t buffered;

dash-spv-ffi/src/bin/ffi_cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ extern "C" fn on_progress_update(progress: *const FFISyncProgress, _user_data: *
213213

214214
if !p.headers.is_null() {
215215
let h = unsafe { &*p.headers };
216-
print!("headers:{}/{} ", h.current_height + h.buffered, h.target_height);
216+
print!("headers:{}/{} ", h.tip_height + h.buffered, h.target_height);
217217
}
218218
if !p.filter_headers.is_null() {
219219
let fh = unsafe { &*p.filter_headers };

dash-spv-ffi/src/types.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use dash_spv::client::config::MempoolStrategy;
22
use dash_spv::sync::{
33
BlockHeadersProgress, BlocksProgress, ChainLockProgress, FilterHeadersProgress,
4-
FiltersProgress, InstantSendProgress, MasternodesProgress, SyncProgress, SyncState,
4+
FiltersProgress, InstantSendProgress, MasternodesProgress, ProgressPercentage, SyncProgress,
5+
SyncState,
56
};
67
use dash_spv::types::MempoolRemovalReason;
78
use std::ffi::{CStr, CString};
@@ -76,7 +77,7 @@ impl From<SyncState> for FFISyncState {
7677
#[derive(Debug, Clone, Default)]
7778
pub struct FFIBlockHeadersProgress {
7879
pub state: FFISyncState,
79-
pub current_height: u32,
80+
pub tip_height: u32,
8081
pub target_height: u32,
8182
pub processed: u32,
8283
pub buffered: u32,
@@ -88,7 +89,7 @@ impl From<&BlockHeadersProgress> for FFIBlockHeadersProgress {
8889
fn from(progress: &BlockHeadersProgress) -> Self {
8990
FFIBlockHeadersProgress {
9091
state: progress.state().into(),
91-
current_height: progress.current_height(),
92+
tip_height: progress.tip_height(),
9293
target_height: progress.target_height(),
9394
processed: progress.processed(),
9495
buffered: progress.buffered(),

dash-spv-ffi/tests/test_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ mod tests {
4949

5050
let mut headers = BlockHeadersProgress::default();
5151
headers.set_state(SyncState::Syncing);
52-
headers.update_current_height(100);
52+
headers.update_tip_height(100);
5353
headers.update_target_height(200);
5454
headers.add_processed(20);
5555
headers.update_buffered(5);
@@ -116,7 +116,7 @@ mod tests {
116116
unsafe {
117117
let headers = &*ffi_progress.headers;
118118
assert_eq!(headers.state, FFISyncState::Syncing);
119-
assert_eq!(headers.current_height, 100);
119+
assert_eq!(headers.tip_height, 100);
120120
assert_eq!(headers.target_height, 200);
121121
assert_eq!(headers.processed, 20);
122122
assert_eq!(headers.buffered, 5);

dash-spv-ffi/tests/unit/test_client_lifecycle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ mod tests {
198198

199199
// Basic consistency checks
200200
assert!(
201-
headers.current_height <= filter_headers.target_height
201+
headers.tip_height <= filter_headers.target_height
202202
|| filter_headers.current_height == 0
203203
);
204204
// headers_downloaded is u64, always >= 0

dash-spv/src/sync/block_headers/manager.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::error::{SyncError, SyncResult};
1515
use crate::network::RequestSender;
1616
use crate::storage::{BlockHeaderStorage, BlockHeaderTip};
1717
use crate::sync::block_headers::HeadersPipeline;
18-
use crate::sync::{BlockHeadersProgress, SyncEvent, SyncManager, SyncState};
18+
use crate::sync::{BlockHeadersProgress, ProgressPercentage, SyncEvent, SyncManager, SyncState};
1919
use crate::types::HashedBlockHeader;
2020
use crate::validation::{BlockHeaderValidator, Validator};
2121
use dashcore::block::Header;
@@ -83,7 +83,7 @@ impl<H: BlockHeaderStorage> BlockHeadersManager<H> {
8383
let tip = self.tip().await?;
8484

8585
// Update state
86-
self.progress.update_current_height(tip.height());
86+
self.progress.update_tip_height(tip.height());
8787
self.progress.add_processed(headers.len() as u32);
8888

8989
Ok(tip)
@@ -243,14 +243,14 @@ mod tests {
243243
#[tokio::test]
244244
async fn test_headers_manager_progress() {
245245
let mut manager = create_test_manager().await;
246-
manager.progress.update_current_height(100);
246+
manager.progress.update_tip_height(100);
247247
manager.progress.update_target_height(200);
248248
manager.progress.add_processed(50);
249249

250250
let progress = manager.progress();
251251
if let SyncManagerProgress::BlockHeaders(progress) = progress {
252252
assert_eq!(progress.state(), SyncState::Initializing);
253-
assert_eq!(progress.current_height(), 100);
253+
assert_eq!(progress.tip_height(), 100);
254254
assert_eq!(progress.target_height(), 200);
255255
assert_eq!(progress.processed(), 50);
256256
assert!(progress.last_activity().elapsed().as_secs() < 1);

dash-spv/src/sync/block_headers/progress.rs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::sync::progress::ProgressPercentage;
12
use crate::sync::SyncState;
23
use std::fmt;
34
use std::time::Instant;
@@ -8,7 +9,7 @@ pub struct BlockHeadersProgress {
89
/// Current sync state.
910
state: SyncState,
1011
/// The tip height of the block-header storage.
11-
current_height: u32,
12+
tip_height: u32,
1213
/// Equals to current_height (blockchain tip) when synced and to the best height of connected peers during initial sync.
1314
target_height: u32,
1415
/// Number of block-headers processed (stored) in the current sync session.
@@ -23,7 +24,7 @@ impl Default for BlockHeadersProgress {
2324
fn default() -> Self {
2425
Self {
2526
state: SyncState::default(),
26-
current_height: 0,
27+
tip_height: 0,
2728
target_height: 0,
2829
processed: 0,
2930
buffered: 0,
@@ -33,35 +34,18 @@ impl Default for BlockHeadersProgress {
3334
}
3435

3536
impl BlockHeadersProgress {
36-
/// Get completion percentage (0.0 to 1.0).
37-
/// Includes buffered headers for more accurate progress during parallel sync.
38-
pub fn percentage(&self) -> f64 {
39-
if self.target_height == 0 {
40-
return 1.0;
41-
}
42-
// Include buffered headers in progress calculation
43-
(self.effective_height() as f64 / self.target_height as f64).min(1.0)
44-
}
4537
/// Get the current sync state.
4638
pub fn state(&self) -> SyncState {
4739
self.state
4840
}
4941
/// Get the current height (last successfully processed height).
50-
pub fn current_height(&self) -> u32 {
51-
self.current_height
52-
}
53-
/// Get the target height (the best height of the connected peers)
54-
pub fn target_height(&self) -> u32 {
55-
self.target_height
42+
pub fn tip_height(&self) -> u32 {
43+
self.tip_height
5644
}
5745
/// Number of block-headers processed (stored) in the current sync session.
5846
pub fn processed(&self) -> u32 {
5947
self.processed
6048
}
61-
/// Get the effective height (current_height + buffered).
62-
pub fn effective_height(&self) -> u32 {
63-
self.current_height + self.buffered
64-
}
6549
/// The last time a block-header was stored to disk or the last manager state change.
6650
pub fn last_activity(&self) -> Instant {
6751
self.last_activity
@@ -71,9 +55,9 @@ impl BlockHeadersProgress {
7155
self.state = state;
7256
self.bump_last_activity();
7357
}
74-
/// Update the current height (last successfully processed height).
75-
pub fn update_current_height(&mut self, height: u32) {
76-
self.current_height = height;
58+
/// Update the tip height (last successfully processed height).
59+
pub fn update_tip_height(&mut self, height: u32) {
60+
self.tip_height = height;
7761
self.bump_last_activity();
7862
}
7963
/// Update the target height (the best height of the connected peers).
@@ -110,7 +94,7 @@ impl fmt::Display for BlockHeadersProgress {
11094
f,
11195
"{:?} {}/{} ({:.1}%) processed: {}, buffered: {}, last_activity: {}s",
11296
self.state,
113-
self.effective_height(),
97+
self.current_height(),
11498
self.target_height,
11599
pct,
116100
self.processed,
@@ -119,3 +103,14 @@ impl fmt::Display for BlockHeadersProgress {
119103
)
120104
}
121105
}
106+
107+
impl ProgressPercentage for BlockHeadersProgress {
108+
fn target_height(&self) -> u32 {
109+
self.target_height
110+
}
111+
fn current_height(&self) -> u32 {
112+
// Use the effective height here for the progress to show more realistic values since
113+
// we download headers in parallel and the tip height is only updated when sequential segments complete.
114+
self.tip_height + self.buffered
115+
}
116+
}

dash-spv/src/sync/block_headers/sync_manager.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crate::error::SyncResult;
22
use crate::network::{Message, MessageType, NetworkEvent, RequestSender};
33
use crate::storage::BlockHeaderStorage;
44
use crate::sync::{
5-
BlockHeadersManager, ManagerIdentifier, SyncEvent, SyncManager, SyncManagerProgress, SyncState,
5+
BlockHeadersManager, ManagerIdentifier, ProgressPercentage, SyncEvent, SyncManager,
6+
SyncManagerProgress, SyncState,
67
};
78
use crate::SyncError;
89
use async_trait::async_trait;
@@ -45,7 +46,7 @@ impl<H: BlockHeaderStorage> SyncManager for BlockHeadersManager<H> {
4546
.ok_or_else(|| SyncError::MissingDependency("No tip in storage".to_string()))?;
4647

4748
self.progress.set_state(SyncState::WaitingForConnections);
48-
self.progress.update_current_height(tip.height());
49+
self.progress.update_tip_height(tip.height());
4950
self.progress.update_target_height(tip.height());
5051

5152
tracing::info!("BlockHeadersManager initialized at height {}", tip.height());
@@ -182,13 +183,13 @@ impl<H: BlockHeaderStorage> SyncManager for BlockHeadersManager<H> {
182183
// When already synced but behind peer height, request missing headers
183184
if self.state() == SyncState::Synced {
184185
if let Some(best_height) = best_height {
185-
if *best_height > self.progress.current_height()
186+
if *best_height > self.progress.tip_height()
186187
&& !self.pipeline.tip_segment_has_pending_request()
187188
{
188189
tracing::info!(
189190
"Peer height {} > our height {}, requesting headers to catch up",
190191
best_height,
191-
self.progress.current_height()
192+
self.progress.tip_height()
192193
);
193194
// Reset tip segment and send requests via pipeline
194195
self.pipeline.reset_tip_segment();

dash-spv/src/sync/filter_headers/manager.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::error::SyncResult;
1313
use crate::network::RequestSender;
1414
use crate::storage::{BlockHeaderStorage, FilterHeaderStorage};
1515
use crate::sync::filter_headers::util::compute_filter_headers;
16+
use crate::sync::progress::ProgressPercentage;
1617
use crate::sync::{FilterHeadersProgress, SyncEvent, SyncManager, SyncState};
1718

1819
/// Filter headers manager for downloading compact block filter headers.

dash-spv/src/sync/filter_headers/progress.rs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
use crate::sync::progress::ProgressPercentage;
2+
use crate::sync::SyncState;
13
use std::fmt;
24
use std::time::Instant;
35

4-
use crate::sync::SyncState;
5-
66
/// Progress for filter-header synchronization.
77
#[derive(Debug, Clone, PartialEq)]
88
pub struct FilterHeadersProgress {
@@ -34,30 +34,10 @@ impl Default for FilterHeadersProgress {
3434
}
3535

3636
impl FilterHeadersProgress {
37-
/// Get completion percentage (0.0 to 1.0).
38-
/// Uses target_height (peer's best height) for accurate progress display.
39-
pub fn percentage(&self) -> f64 {
40-
if self.target_height == 0 {
41-
return 1.0;
42-
}
43-
(self.current_height as f64 / self.target_height as f64).min(1.0)
44-
}
45-
4637
/// Get the current sync state.
4738
pub fn state(&self) -> SyncState {
4839
self.state
4940
}
50-
51-
/// Get the current height (last successfully processed filter-header height).
52-
pub fn current_height(&self) -> u32 {
53-
self.current_height
54-
}
55-
56-
/// Get the target height (peer's best height, for progress display).
57-
pub fn target_height(&self) -> u32 {
58-
self.target_height
59-
}
60-
6141
/// Get the block-header tip height (the download limit for filter headers).
6242
pub fn block_header_tip_height(&self) -> u32 {
6343
self.block_header_tip_height
@@ -127,3 +107,12 @@ impl fmt::Display for FilterHeadersProgress {
127107
)
128108
}
129109
}
110+
111+
impl ProgressPercentage for FilterHeadersProgress {
112+
fn target_height(&self) -> u32 {
113+
self.target_height
114+
}
115+
fn current_height(&self) -> u32 {
116+
self.current_height
117+
}
118+
}

0 commit comments

Comments
 (0)