Skip to content

Conversation

@ZocoLini
Copy link
Collaborator

@ZocoLini ZocoLini commented Dec 4, 2025

Fix extracted from #189.

This fix aims to avoid re-downloading filters by starting from the last stored

Summary by CodeRabbit

  • New Features

    • Filter downloads now resume from the last stored filter height, reducing rework after interrupted syncs.
  • Bug Fixes

    • Graceful handling when no filter headers are available.
    • Improved sync phase transitions and logic to avoid invalid or redundant filter downloads.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

Walkthrough

Adds an async StorageManager method get_stored_filter_height (memory and disk implementations) and uses it in the DownloadingFilters phase to resume filter downloads from the highest stored compact-filter height instead of always starting at the sync base.

Changes

Cohort / File(s) Change Summary
StorageManager trait
dash-spv/src/storage/mod.rs
Added async method get_stored_filter_height(&self) -> StorageResult<Option<u32>> to the StorageManager trait.
Disk storage — trait impl & helper
dash-spv/src/storage/disk/state.rs, dash-spv/src/storage/disk/filters.rs
Implemented get_stored_filter_height for DiskStorageManager. state.rs exposes the trait method (delegates to internal logic); filters.rs adds a public helper that scans the filters directory for numeric {height}.dat files, parses heights (ignoring non-numeric/segment files and implausible values), and returns the max height or None.
Memory storage implementation
dash-spv/src/storage/memory.rs
Implemented get_stored_filter_height for MemoryStorageManager by returning the maximum key from the in-memory filters map, or None if empty.
DownloadingFilters phase logic
dash-spv/src/sync/phase_execution.rs
Integrated stored-height resume logic: early-exit when no filter headers, query get_stored_filter_height(), set start_height = stored_height + 1 when present (otherwise max(1, base)), compute count = filter_header_tip - start_height + 1, handle start > tip transitions, and add trace logs and progress updates.

Sequence Diagram

sequenceDiagram
    participant DF as DownloadingFilters
    participant SM as StorageManager
    participant FH as FilterHeaders

    rect rgb(248,249,255)
    Note over DF,FH: Initialize resume logic
    end

    DF->>DF: Read filter_header_tip
    alt no headers (filter_header_tip == 0)
        DF->>DF: Transition to next phase (no headers)
    else headers present
        DF->>SM: get_stored_filter_height()
        SM-->>DF: Option<u32> stored_height

        alt stored_height exists
            DF->>DF: start_height = stored_height + 1
        else none
            DF->>DF: start_height = max(1, sync_base)
        end

        DF->>DF: Calculate count = filter_header_tip - start_height + 1
        alt start_height > filter_header_tip
            DF->>DF: Transition to next phase (complete)
        else
            DF->>FH: Download filters [start_height .. start_height+count-1]
            FH-->>DF: Filters received
            DF->>DF: Update phase progress/total_filters
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay attention to phase_execution.rs for boundary conditions and correct transitions.
  • Review disk scanning logic in filters.rs for filename parsing, filtering rules, and error handling.
  • Verify memory impl handles empty map and concurrency/access patterns consistent with other accessors.

Poem

🐰 A tiny hop, a careful trace,
I remember where each filter's place.
From stored height I nudge and leap,
Resuming sync without losing sleep.
Hooray — small hops make syncing neat! 🌿

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: avoiding re-downloading filters by resuming from the last stored filter height during the DownloadingFilters phase.
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/filter-sync-from-last-stored

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
dash-spv/src/sync/phase_execution.rs (1)

152-157: Guard clause for missing filter headers is appropriate.

The early return when filter_header_tip <= 0 prevents unnecessary processing. Note that since filter_header_tip is u32, this is equivalent to == 0; consider using == 0 for clarity, though functionally identical.

-                if filter_header_tip <= 0 {
+                if filter_header_tip == 0 {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c76ddbb and c5ae92c.

📒 Files selected for processing (4)
  • dash-spv/src/storage/disk/state.rs (1 hunks)
  • dash-spv/src/storage/memory.rs (1 hunks)
  • dash-spv/src/storage/mod.rs (1 hunks)
  • dash-spv/src/sync/phase_execution.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Never hardcode network parameters, addresses, or keys in Rust code
Use proper error types with thiserror crate and propagate errors appropriately in Rust code
Use tokio runtime for async operations in Rust code
Use conditional compilation with feature flags for optional features
Write unit tests for new functionality in Rust
Format Rust code with cargo fmt before committing
Ensure clippy passes with all warnings as errors on all Rust code

**/*.rs: Each crate keeps sources in src/; unit tests live alongside code with #[cfg(test)]
Maintain MSRV of 1.89 for Rust code
Format Rust code with rustfmt (see rustfmt.toml); run cargo fmt --all before commits
Lint Rust code with clippy; avoid unwrap()/expect() in library code; use error types (e.g., thiserror)
Use snake_case for function and variable names in Rust
Use UpperCamelCase for types and traits in Rust
Use SCREAMING_SNAKE_CASE for constants in Rust
Follow mixed editions (2021/2024) and crate-specific idioms; prefer async via tokio where applicable
Unit tests should be placed near code with descriptive names (e.g., test_parse_address_mainnet)
Use #[ignore] for network-dependent or long-running tests; run with -- --ignored flag
Never commit secrets or real keys; avoid logging sensitive data in Rust code
Keep test vectors deterministic in Rust test code

Files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/sync/phase_execution.rs
  • dash-spv/src/storage/disk/state.rs
dash-spv/**/*.rs

📄 CodeRabbit inference engine (dash-spv/CLAUDE.md)

dash-spv/**/*.rs: Use trait-based abstractions for core components like NetworkManager and StorageManager to enable swappable implementations
Use async/await throughout the codebase with tokio runtime for all asynchronous operations
Use Minimum Rust Version (MSRV) 1.89 and ensure all code compiles with cargo check --all-features

Files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/sync/phase_execution.rs
  • dash-spv/src/storage/disk/state.rs
dash-spv/src/storage/**/*.rs

📄 CodeRabbit inference engine (dash-spv/CLAUDE.md)

Storage module should provide abstraction via StorageManager trait with concrete implementations for MemoryStorageManager and DiskStorageManager

Files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/storage/disk/state.rs
dash-spv/src/sync/**/*.rs

📄 CodeRabbit inference engine (dash-spv/CLAUDE.md)

Synchronization should use SyncManager for phase-based coordination: Phase 1 (Headers), Phase 2 (Masternode List), Phase 3 (Filter Headers), Phase 4 (Filters), Phase 5 (Blocks)

Files:

  • dash-spv/src/sync/phase_execution.rs
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/sync/**/*.rs : Synchronization should use `SyncManager` for phase-based coordination: Phase 1 (Headers), Phase 2 (Masternode List), Phase 3 (Filter Headers), Phase 4 (Filters), Phase 5 (Blocks)
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Storage should use segmented storage with headers stored in 10,000-header segments with index files, separate storage for filter headers and compact block filters
📚 Learning: 2025-12-04T15:51:59.632Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/storage/**/*.rs : Storage module should provide abstraction via `StorageManager` trait with concrete implementations for `MemoryStorageManager` and `DiskStorageManager`

Applied to files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/storage/disk/state.rs
📚 Learning: 2025-06-26T15:54:02.509Z
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T15:54:02.509Z
Learning: The `StorageManager` trait in `dash-spv/src/storage/mod.rs` uses `&mut self` methods but is also `Send + Sync`, and implementations often use interior mutability for concurrency. This can be confusing, so explicit documentation should clarify thread-safety expectations and the rationale for the API design.

Applied to files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/storage/disk/state.rs
📚 Learning: 2025-12-04T15:51:59.632Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/**/*.rs : Use trait-based abstractions for core components like `NetworkManager` and `StorageManager` to enable swappable implementations

Applied to files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/storage/disk/state.rs
📚 Learning: 2025-12-01T07:59:58.608Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-12-01T07:59:58.608Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : Use thread-local storage for error propagation via `dash_spv_ffi_get_last_error()` function

Applied to files:

  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/memory.rs
📚 Learning: 2025-12-04T15:51:59.632Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/sync/**/*.rs : Synchronization should use `SyncManager` for phase-based coordination: Phase 1 (Headers), Phase 2 (Masternode List), Phase 3 (Filter Headers), Phase 4 (Filters), Phase 5 (Blocks)

Applied to files:

  • dash-spv/src/sync/phase_execution.rs
📚 Learning: 2025-06-26T16:01:37.609Z
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T16:01:37.609Z
Learning: The mempool tracking infrastructure (UnconfirmedTransaction, MempoolState, configuration, and mempool_filter.rs) is fully implemented and integrated in the Dash SPV client as of this PR, including client logic, FFI APIs, and tests.

Applied to files:

  • dash-spv/src/sync/phase_execution.rs
🧬 Code graph analysis (4)
dash-spv/src/storage/mod.rs (2)
dash-spv/src/storage/disk/state.rs (1)
  • get_stored_filter_height (556-558)
dash-spv/src/storage/memory.rs (1)
  • get_stored_filter_height (261-268)
dash-spv/src/storage/memory.rs (2)
dash-spv/src/storage/disk/state.rs (1)
  • get_stored_filter_height (556-558)
dash-spv/src/storage/mod.rs (1)
  • get_stored_filter_height (132-132)
dash-spv/src/sync/phase_execution.rs (2)
dash-spv/src/client/core.rs (2)
  • storage (171-173)
  • network (166-168)
dash-spv/src/sync/headers/manager.rs (2)
  • storage (346-346)
  • get_sync_base_height (1035-1037)
dash-spv/src/storage/disk/state.rs (2)
dash-spv/src/storage/memory.rs (1)
  • get_stored_filter_height (261-268)
dash-spv/src/storage/mod.rs (1)
  • get_stored_filter_height (132-132)
🔇 Additional comments (6)
dash-spv/src/storage/mod.rs (1)

130-133: Well-designed trait method addition.

The new get_stored_filter_height method follows the existing trait patterns with appropriate documentation that clearly distinguishes it from get_filter_tip_height. The signature using &self correctly reflects the read-only nature of this operation.

dash-spv/src/storage/memory.rs (1)

261-268: LGTM!

The implementation correctly returns the maximum key from the filters HashMap, which stores absolute blockchain heights. The idiomatic use of .keys().max().copied() is clean and appropriate for in-memory storage.

dash-spv/src/sync/phase_execution.rs (3)

165-189: Resume logic correctly calculates start height from stored filters.

The implementation properly:

  1. Reads the last stored filter height from storage
  2. Resumes from stored_height + 1 if filters exist
  3. Falls back to sync_base_height.max(1) for fresh starts

This achieves the PR objective of avoiding re-downloads.


191-201: Correctly handles already-synced case.

When start_height > filter_header_tip, all filters are already downloaded. The transition to the next phase with appropriate logging prevents redundant work.


203-229: Filter download initiation with proper count calculation.

The count calculation filter_header_tip - start_height + 1 correctly computes the inclusive range. The phase's total_filters is updated to reflect the actual remaining count rather than the full range, which is appropriate for progress tracking during resumed syncs.

dash-spv/src/storage/disk/state.rs (1)

556-558: Implement missing get_stored_filter_height method in DiskStorageManager.

The trait impl delegates to Self::get_stored_filter_height(self).await, but this inherent method does not exist in DiskStorageManager. The MemoryStorageManager has a working implementation; DiskStorageManager must provide the corresponding disk-based implementation that scans the filter storage directory and returns the height of the highest stored filter.

⛔ Skipped due to learnings
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/storage/**/*.rs : Storage module should provide abstraction via `StorageManager` trait with concrete implementations for `MemoryStorageManager` and `DiskStorageManager`
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T15:54:02.509Z
Learning: The `StorageManager` trait in `dash-spv/src/storage/mod.rs` uses `&mut self` methods but is also `Send + Sync`, and implementations often use interior mutability for concurrency. This can be confusing, so explicit documentation should clarify thread-safety expectations and the rationale for the API design.
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/**/*.rs : Use trait-based abstractions for core components like `NetworkManager` and `StorageManager` to enable swappable implementations

@ZocoLini ZocoLini force-pushed the fix/filter-sync-from-last-stored branch from c5ae92c to b6cdf1e Compare December 4, 2025 22:58
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
dash-spv/src/storage/disk/filters.rs (1)

208-210: Consider async metadata check for better async hygiene.

The synchronous path.is_file() call can block the executor thread. While metadata checks are typically fast, it's better practice in async contexts to use async file operations.

Apply this diff to use async metadata checking:

             let path = entry.path();
 
-            // Skip if not a file
-            if !path.is_file() {
-                continue;
-            }
+            // Skip if not a file (use async metadata check)
+            let metadata = match tokio::fs::metadata(&path).await {
+                Ok(m) => m,
+                Err(_) => continue,
+            };
+            if !metadata.is_file() {
+                continue;
+            }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5ae92c and b6cdf1e.

📒 Files selected for processing (5)
  • dash-spv/src/storage/disk/filters.rs (1 hunks)
  • dash-spv/src/storage/disk/state.rs (1 hunks)
  • dash-spv/src/storage/memory.rs (1 hunks)
  • dash-spv/src/storage/mod.rs (1 hunks)
  • dash-spv/src/sync/phase_execution.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • dash-spv/src/storage/memory.rs
  • dash-spv/src/storage/mod.rs
  • dash-spv/src/storage/disk/state.rs
🧰 Additional context used
📓 Path-based instructions (4)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Never hardcode network parameters, addresses, or keys in Rust code
Use proper error types with thiserror crate and propagate errors appropriately in Rust code
Use tokio runtime for async operations in Rust code
Use conditional compilation with feature flags for optional features
Write unit tests for new functionality in Rust
Format Rust code with cargo fmt before committing
Ensure clippy passes with all warnings as errors on all Rust code

**/*.rs: Each crate keeps sources in src/; unit tests live alongside code with #[cfg(test)]
Maintain MSRV of 1.89 for Rust code
Format Rust code with rustfmt (see rustfmt.toml); run cargo fmt --all before commits
Lint Rust code with clippy; avoid unwrap()/expect() in library code; use error types (e.g., thiserror)
Use snake_case for function and variable names in Rust
Use UpperCamelCase for types and traits in Rust
Use SCREAMING_SNAKE_CASE for constants in Rust
Follow mixed editions (2021/2024) and crate-specific idioms; prefer async via tokio where applicable
Unit tests should be placed near code with descriptive names (e.g., test_parse_address_mainnet)
Use #[ignore] for network-dependent or long-running tests; run with -- --ignored flag
Never commit secrets or real keys; avoid logging sensitive data in Rust code
Keep test vectors deterministic in Rust test code

Files:

  • dash-spv/src/sync/phase_execution.rs
  • dash-spv/src/storage/disk/filters.rs
dash-spv/**/*.rs

📄 CodeRabbit inference engine (dash-spv/CLAUDE.md)

dash-spv/**/*.rs: Use trait-based abstractions for core components like NetworkManager and StorageManager to enable swappable implementations
Use async/await throughout the codebase with tokio runtime for all asynchronous operations
Use Minimum Rust Version (MSRV) 1.89 and ensure all code compiles with cargo check --all-features

Files:

  • dash-spv/src/sync/phase_execution.rs
  • dash-spv/src/storage/disk/filters.rs
dash-spv/src/sync/**/*.rs

📄 CodeRabbit inference engine (dash-spv/CLAUDE.md)

Synchronization should use SyncManager for phase-based coordination: Phase 1 (Headers), Phase 2 (Masternode List), Phase 3 (Filter Headers), Phase 4 (Filters), Phase 5 (Blocks)

Files:

  • dash-spv/src/sync/phase_execution.rs
dash-spv/src/storage/**/*.rs

📄 CodeRabbit inference engine (dash-spv/CLAUDE.md)

Storage module should provide abstraction via StorageManager trait with concrete implementations for MemoryStorageManager and DiskStorageManager

Files:

  • dash-spv/src/storage/disk/filters.rs
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/sync/**/*.rs : Synchronization should use `SyncManager` for phase-based coordination: Phase 1 (Headers), Phase 2 (Masternode List), Phase 3 (Filter Headers), Phase 4 (Filters), Phase 5 (Blocks)
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Storage should use segmented storage with headers stored in 10,000-header segments with index files, separate storage for filter headers and compact block filters
📚 Learning: 2025-12-04T15:51:59.632Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/sync/**/*.rs : Synchronization should use `SyncManager` for phase-based coordination: Phase 1 (Headers), Phase 2 (Masternode List), Phase 3 (Filter Headers), Phase 4 (Filters), Phase 5 (Blocks)

Applied to files:

  • dash-spv/src/sync/phase_execution.rs
📚 Learning: 2025-06-26T16:01:37.609Z
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T16:01:37.609Z
Learning: The mempool tracking infrastructure (UnconfirmedTransaction, MempoolState, configuration, and mempool_filter.rs) is fully implemented and integrated in the Dash SPV client as of this PR, including client logic, FFI APIs, and tests.

Applied to files:

  • dash-spv/src/sync/phase_execution.rs
📚 Learning: 2025-12-04T15:51:59.632Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/src/storage/**/*.rs : Storage module should provide abstraction via `StorageManager` trait with concrete implementations for `MemoryStorageManager` and `DiskStorageManager`

Applied to files:

  • dash-spv/src/storage/disk/filters.rs
📚 Learning: 2025-12-01T07:59:58.608Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-12-01T07:59:58.608Z
Learning: Applies to dash-spv-ffi/src/**/*.rs : Use thread-local storage for error propagation via `dash_spv_ffi_get_last_error()` function

Applied to files:

  • dash-spv/src/storage/disk/filters.rs
📚 Learning: 2025-12-04T15:51:59.632Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-04T15:51:59.632Z
Learning: Applies to dash-spv/**/*.rs : Use trait-based abstractions for core components like `NetworkManager` and `StorageManager` to enable swappable implementations

Applied to files:

  • dash-spv/src/storage/disk/filters.rs
🧬 Code graph analysis (2)
dash-spv/src/sync/phase_execution.rs (2)
dash-spv/src/client/core.rs (2)
  • storage (171-173)
  • network (166-168)
dash-spv/src/sync/headers/manager.rs (2)
  • storage (346-346)
  • get_sync_base_height (1035-1037)
dash-spv/src/storage/disk/filters.rs (3)
dash-spv/src/storage/disk/state.rs (1)
  • get_stored_filter_height (556-558)
dash-spv/src/storage/memory.rs (1)
  • get_stored_filter_height (261-268)
dash-spv/src/storage/mod.rs (1)
  • get_stored_filter_height (132-132)
🔇 Additional comments (4)
dash-spv/src/storage/disk/filters.rs (1)

185-246: LGTM! Resume logic correctly scans for stored filters.

The implementation correctly:

  • Returns None when no filters directory exists
  • Filters out segment files by checking for purely numeric filenames
  • Handles edge cases (non-files, non-.dat, parse errors)
  • Includes a reasonable sanity check for suspiciously high heights

The defensive error handling on line 227 (despite the comment noting it can't fail) is good practice.

dash-spv/src/sync/phase_execution.rs (3)

152-157: LGTM! Good defensive check for missing filter headers.

The early return when filter_header_tip == 0 prevents attempting to download filters when no filter headers are available, avoiding unnecessary work and potential errors.


165-174: LGTM! Proper storage integration with error handling.

The call to get_stored_filter_height is correctly wrapped with error handling and includes helpful logging for debugging the resume logic.


176-230: LGTM! Resume logic correctly avoids re-downloading filters.

The implementation correctly:

  • Resumes from stored_height + 1 when filters exist, avoiding re-downloads
  • Falls back to sync_base_height (minimum 1) when no filters are stored
  • Handles the edge case where all filters are already downloaded by transitioning to the next phase
  • Calculates the inclusive range correctly: count = filter_header_tip - start_height + 1
  • Updates the phase's total_filters to reflect the actual work needed
  • Provides comprehensive logging at each decision point

The use of max(1) on line 186 correctly ensures the start height is never below the genesis block.

@ZocoLini
Copy link
Collaborator Author

ZocoLini commented Dec 10, 2025

Waiting #244

@ZocoLini ZocoLini marked this pull request as draft December 10, 2025 20:53
@github-actions github-actions bot added the merge-conflict The PR conflicts with the target branch. label Dec 11, 2025
@github-actions
Copy link

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-conflict The PR conflicts with the target branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants