Skip to content

Commit 75cd5ae

Browse files
authored
fix(cbf): break wallet chain source reference cycle (#23)
- Store the CBF wallet reference as Weak<Wallet> instead of Arc<Wallet>
1 parent 5f7d5c5 commit 75cd5ae

1 file changed

Lines changed: 17 additions & 7 deletions

File tree

src/chain/cbf.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use std::collections::{HashMap, HashSet, VecDeque};
99
use std::net::SocketAddr;
1010
use std::sync::atomic::{AtomicU32, Ordering};
11-
use std::sync::{Arc, Mutex, RwLock};
11+
use std::sync::{Arc, Mutex, RwLock, Weak};
1212
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
1313

1414
use bdk_chain::indexer::keychain_txout::KeychainTxOutIndex;
@@ -115,7 +115,7 @@ pub(super) struct CbfChainSource {
115115
/// Node configuration (network, storage path, etc.).
116116
config: Arc<Config>,
117117
/// On-chain wallet reference for deriving chain_state checkpoints on restart.
118-
onchain_wallet: Mutex<Option<Arc<Wallet>>>,
118+
onchain_wallet: Mutex<Option<Weak<Wallet>>>,
119119
/// Logger instance.
120120
logger: Arc<Logger>,
121121
/// Shared node metrics (sync timestamps, etc.).
@@ -194,7 +194,7 @@ impl CbfChainSource {
194194
///
195195
/// Delegates to [`Self::build_cbf_node_static`], passing all needed fields.
196196
fn build_cbf_node(&self) -> (CbfNode, Client) {
197-
let wallet = self.onchain_wallet.lock().expect("lock").clone();
197+
let wallet = self.onchain_wallet.lock().expect("lock").as_ref().and_then(Weak::upgrade);
198198
Self::build_cbf_node_static(
199199
&self.peers,
200200
&self.sync_config,
@@ -281,8 +281,9 @@ impl CbfChainSource {
281281
return;
282282
}
283283

284-
// Store the wallet reference for future restarts.
285-
*self.onchain_wallet.lock().expect("lock") = Some(Arc::clone(&onchain_wallet));
284+
// Store a weak wallet reference for future restarts without creating a
285+
// Wallet -> ChainSource -> Wallet reference cycle.
286+
*self.onchain_wallet.lock().expect("lock") = Some(Arc::downgrade(&onchain_wallet));
286287

287288
let (node, client) = self.build_cbf_node();
288289

@@ -304,7 +305,7 @@ impl CbfChainSource {
304305
let restart_peers = self.peers.clone();
305306
let restart_sync_config = self.sync_config.clone();
306307
let restart_config = Arc::clone(&self.config);
307-
let restart_wallet = Arc::clone(&onchain_wallet);
308+
let restart_wallet = Arc::downgrade(&onchain_wallet);
308309

309310
runtime.spawn_background_task(async move {
310311
let mut current_node = node;
@@ -373,11 +374,19 @@ impl CbfChainSource {
373374
event_handle.abort();
374375

375376
// Rebuild the node from scratch.
377+
let Some(wallet) = restart_wallet.upgrade() else {
378+
log_info!(
379+
restart_logger,
380+
"CBF restart aborted: on-chain wallet was dropped."
381+
);
382+
*restart_status.lock().expect("lock") = CbfRuntimeStatus::Stopped;
383+
break;
384+
};
376385
let (new_node, new_client) = Self::build_cbf_node_static(
377386
&restart_peers,
378387
&restart_sync_config,
379388
&restart_config,
380-
Some(&restart_wallet),
389+
Some(&wallet),
381390
&restart_logger,
382391
);
383392
let Client {
@@ -423,6 +432,7 @@ impl CbfChainSource {
423432
CbfRuntimeStatus::Stopped => {},
424433
}
425434
*status = CbfRuntimeStatus::Stopped;
435+
*self.onchain_wallet.lock().expect("lock") = None;
426436
}
427437

428438
async fn process_info_messages(mut info_rx: mpsc::Receiver<Info>, logger: Arc<Logger>) {

0 commit comments

Comments
 (0)