Skip to content

Commit e1dbbe2

Browse files
committed
fix(cbf): clean up scan state on filter scan failure
Extract cleanup_scan_state() helper and call it on error paths in run_filter_scan() to prevent stale watched_scripts, matched_block_hashes, and filter_skip_height from leaking between scans.
1 parent 6a2d78e commit e1dbbe2

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

src/chain/cbf.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,19 @@ impl CbfChainSource {
501501
}
502502
}
503503

504+
/// Reset filter scan state to a clean baseline.
505+
///
506+
/// Called on both success and error paths in `run_filter_scan()` to ensure
507+
/// no stale state leaks between scans.
508+
fn cleanup_scan_state(&self) {
509+
self.filter_skip_height.store(0, Ordering::Release);
510+
self.watched_scripts.write().unwrap().clear();
511+
self.matched_block_hashes.lock().unwrap().clear();
512+
if let Some(tx) = self.sync_completion_tx.lock().unwrap().take() {
513+
drop(tx);
514+
}
515+
}
516+
504517
/// Register a transaction script for Lightning channel monitoring.
505518
pub(crate) fn register_tx(&self, _txid: &Txid, script_pubkey: &Script) {
506519
self.registered_scripts.lock().unwrap().push(script_pubkey.to_owned());
@@ -530,21 +543,27 @@ impl CbfChainSource {
530543
let (tx, rx) = oneshot::channel();
531544
*self.sync_completion_tx.lock().unwrap() = Some(tx);
532545

533-
requester.rescan().map_err(|e| {
546+
if let Err(e) = requester.rescan().map_err(|e| {
534547
log_error!(self.logger, "Failed to trigger CBF rescan: {:?}", e);
535548
Error::WalletOperationFailed
536-
})?;
537-
538-
let sync_update = rx.await.map_err(|e| {
539-
log_error!(self.logger, "CBF sync completion channel dropped: {:?}", e);
540-
Error::WalletOperationFailed
541-
})?;
542-
543-
self.filter_skip_height.store(0, Ordering::Release);
544-
self.watched_scripts.write().unwrap().clear();
545-
let matched = std::mem::take(&mut *self.matched_block_hashes.lock().unwrap());
549+
}) {
550+
self.cleanup_scan_state();
551+
return Err(e);
552+
}
546553

547-
Ok((sync_update, matched))
554+
match rx.await {
555+
Ok(sync_update) => {
556+
self.filter_skip_height.store(0, Ordering::Release);
557+
self.watched_scripts.write().unwrap().clear();
558+
let matched = std::mem::take(&mut *self.matched_block_hashes.lock().unwrap());
559+
Ok((sync_update, matched))
560+
},
561+
Err(e) => {
562+
log_error!(self.logger, "CBF sync completion channel dropped: {:?}", e);
563+
self.cleanup_scan_state();
564+
Err(Error::WalletOperationFailed)
565+
},
566+
}
548567
}
549568

550569
/// Sync the on-chain wallet by scanning compact block filters for relevant transactions.

0 commit comments

Comments
 (0)