Skip to content

Commit 1b38e9c

Browse files
fix(dash-spv): unify status display height calculation for genesis and checkpoint sync
Previously, the status display used different logic for calculating header heights: - Checkpoint sync: correctly used sync_base_height + storage_count - Genesis sync: incorrectly checked chain_state.headers which was kept minimal This caused status to show all zeros when syncing from genesis, while headers were actually being synced to disk successfully. The fix unifies both paths to use the same formula: - Genesis sync: 0 + storage_count = actual height - Checkpoint sync: checkpoint_height + storage_count = actual height This ensures accurate progress reporting regardless of sync method. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 295d76f commit 1b38e9c

File tree

1 file changed

+21
-66
lines changed

1 file changed

+21
-66
lines changed

dash-spv/src/client/status_display.rs

Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -43,51 +43,21 @@ impl<'a> StatusDisplay<'a> {
4343
state: &ChainState,
4444
with_logging: bool,
4545
) -> u32 {
46-
if state.synced_from_checkpoint && state.sync_base_height > 0 {
47-
// Get the actual number of headers in storage
48-
if let Ok(Some(storage_tip)) = self.storage.get_tip_height().await {
49-
// The blockchain height is sync_base_height + storage_tip
50-
let blockchain_height = state.sync_base_height + storage_tip;
51-
if with_logging {
52-
tracing::debug!(
53-
"Status display (checkpoint sync): storage_tip={}, sync_base={}, blockchain_height={}",
54-
storage_tip, state.sync_base_height, blockchain_height
55-
);
56-
}
57-
blockchain_height
58-
} else {
59-
// No headers in storage yet, use the checkpoint height
60-
state.sync_base_height
46+
// Unified formula for both checkpoint and genesis sync:
47+
// For genesis sync: sync_base_height = 0, so height = 0 + storage_count
48+
// For checkpoint sync: height = checkpoint_height + storage_count
49+
if let Ok(Some(storage_tip)) = self.storage.get_tip_height().await {
50+
let blockchain_height = state.sync_base_height + storage_tip;
51+
if with_logging {
52+
tracing::debug!(
53+
"Status display: storage_tip={}, sync_base={}, blockchain_height={}",
54+
storage_tip, state.sync_base_height, blockchain_height
55+
);
6156
}
57+
blockchain_height
6258
} else {
63-
// Normal sync from genesis
64-
// Check if headers are in storage but not loaded into memory yet
65-
if state.headers.is_empty() {
66-
// Headers might be in storage but not loaded into ChainState yet
67-
if let Ok(Some(storage_tip)) = self.storage.get_tip_height().await {
68-
if with_logging {
69-
tracing::debug!(
70-
"Status display (normal sync): ChainState empty but storage has {} headers",
71-
storage_tip
72-
);
73-
}
74-
storage_tip
75-
} else {
76-
// No headers in storage or ChainState
77-
0
78-
}
79-
} else {
80-
// Headers are loaded in ChainState, use tip_height()
81-
let tip = state.tip_height();
82-
if with_logging {
83-
tracing::debug!(
84-
"Status display (normal sync): chain state has {} headers, tip_height={}",
85-
state.headers.len(),
86-
tip
87-
);
88-
}
89-
tip
90-
}
59+
// No headers in storage yet
60+
state.sync_base_height
9161
}
9262
}
9363

@@ -242,30 +212,15 @@ impl<'a> StatusDisplay<'a> {
242212
/// This helper method encapsulates the logic for determining the current filter header height,
243213
/// taking into account whether we're syncing from a checkpoint or from genesis.
244214
async fn calculate_filter_header_height(&self, state: &ChainState) -> u32 {
245-
if state.synced_from_checkpoint && state.sync_base_height > 0 {
246-
// Get the actual number of filter headers in storage
247-
if let Ok(Some(storage_height)) = self.storage.get_filter_tip_height().await {
248-
// The blockchain height is sync_base_height + storage_height
249-
state.sync_base_height + storage_height
250-
} else {
251-
// No filter headers in storage yet, use the checkpoint height
252-
state.sync_base_height
253-
}
215+
// Unified formula for both checkpoint and genesis sync:
216+
// For genesis sync: sync_base_height = 0, so height = 0 + storage_count
217+
// For checkpoint sync: height = checkpoint_height + storage_count
218+
if let Ok(Some(storage_height)) = self.storage.get_filter_tip_height().await {
219+
// The blockchain height is sync_base_height + storage_height
220+
state.sync_base_height + storage_height
254221
} else {
255-
// Normal sync from genesis
256-
// Check if filter headers are in storage but not loaded into memory yet
257-
if state.filter_headers.is_empty() {
258-
// Filter headers might be in storage but not loaded into ChainState yet
259-
if let Ok(Some(storage_height)) = self.storage.get_filter_tip_height().await {
260-
storage_height
261-
} else {
262-
// No filter headers in storage or ChainState
263-
0
264-
}
265-
} else {
266-
// Filter headers are loaded in ChainState
267-
state.filter_headers.len().saturating_sub(1) as u32
268-
}
222+
// No filter headers in storage yet
223+
state.sync_base_height
269224
}
270225
}
271226
}

0 commit comments

Comments
 (0)