Skip to content

Commit a3f6814

Browse files
lklimekclaude
andcommitted
fix(spv): reset filter_committed_height on Clear SPV Data
At rust-dashcore 309fac8, WalletManager gained an independent filter_committed_height field. FiltersManager::new() reads filter_committed_height() for its "already synced" guard; the field is no longer derived from synced_height. Previously clear_data_dir called update_synced_height(0), which pre-bump effectively reset both fields via the trait's default impl. Post-bump it only resets synced_height, leaving filter_committed_height at its stale previous value. FiltersManager then logs "Filters already synced to N" and skips the rescan, producing zero balance after a Clear SPV Data. Switch clear_data_dir to update_filter_committed_height(0), which unconditionally sets the field and only bumps synced_height upward if the incoming height is larger — exactly the semantics we need for a rescan-floor reset. Adds a regression test asserting filter_committed_height is lowered to 0 after clear_data_dir(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c370779 commit a3f6814

2 files changed

Lines changed: 56 additions & 4 deletions

File tree

src/spv/manager.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,14 +813,19 @@ impl SpvManager {
813813
wallet_map.clear();
814814
}
815815

816-
// Reset the in-memory WalletManager's synced_height so the next SPV session
817-
// scans filters from genesis instead of the stale height from the previous run.
816+
// Reset the in-memory WalletManager's filter_committed_height so the next
817+
// SPV session scans filters from genesis instead of the stale height from the
818+
// previous run. We reset filter_committed_height (not synced_height) because at
819+
// rust-dashcore 309fac8 these became independent fields — FiltersManager::new()
820+
// reads filter_committed_height() for its "already synced" guard.
818821
match self.wallet.try_write() {
819822
Ok(mut wm) => {
820-
wm.update_synced_height(0);
823+
wm.update_filter_committed_height(0);
821824
}
822825
Err(_) => {
823-
tracing::warn!("Failed to reset WalletManager synced_height during SPV data clear");
826+
tracing::warn!(
827+
"Failed to reset WalletManager filter_committed_height during SPV data clear"
828+
);
824829
}
825830
}
826831

src/spv/tests.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::spv::SpvStatus;
55
use crate::spv::manager::SpvManager;
66
use crate::utils::tasks::TaskManager;
77
use dash_sdk::dpp::dashcore::Network;
8+
use dash_sdk::dpp::key_wallet_manager::WalletInterface;
89
use std::sync::{Arc, RwLock};
910
use tokio::time::{Duration, timeout};
1011

@@ -637,3 +638,49 @@ async fn test_live_testnet_sync_and_shutdown() {
637638

638639
let _ = task_manager.shutdown();
639640
}
641+
642+
/// Regression test: clear_data_dir must reset filter_committed_height (not just synced_height).
643+
///
644+
/// At rust-dashcore 309fac8, WalletManager gained an independent filter_committed_height
645+
/// field. FiltersManager::new() reads filter_committed_height() for its "already synced"
646+
/// guard — the field is no longer derived from synced_height. Calling update_synced_height(0)
647+
/// alone leaves filter_committed_height stale and causes the next SPV session to declare
648+
/// itself "already synced" and skip the rescan, producing zero balance after a Clear SPV Data.
649+
///
650+
/// Given a manager with a non-zero filter_committed_height,
651+
/// When clear_data_dir() is called,
652+
/// Then filter_committed_height is reset to 0.
653+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
654+
async fn test_clear_data_dir_resets_filter_committed_height() {
655+
let (manager, _tm, _tmp_dir) = create_test_manager();
656+
657+
// Pre-seed a non-zero filter_committed_height to simulate a previous session.
658+
const PRESEED_HEIGHT: u32 = 5_000;
659+
let wallet_arc = manager.wallet();
660+
{
661+
let mut wm = wallet_arc.write().await;
662+
wm.update_filter_committed_height(PRESEED_HEIGHT);
663+
}
664+
665+
// Verify pre-condition.
666+
{
667+
let wm = wallet_arc.read().await;
668+
assert_eq!(
669+
wm.filter_committed_height(),
670+
PRESEED_HEIGHT,
671+
"pre-condition: filter_committed_height should be PRESEED_HEIGHT"
672+
);
673+
}
674+
675+
manager
676+
.clear_data_dir()
677+
.expect("clear_data_dir should succeed");
678+
679+
// After clearing, filter_committed_height must be 0.
680+
let wm = wallet_arc.read().await;
681+
assert_eq!(
682+
wm.filter_committed_height(),
683+
0,
684+
"clear_data_dir must reset filter_committed_height to 0"
685+
);
686+
}

0 commit comments

Comments
 (0)