88use std:: collections:: { HashMap , HashSet , VecDeque } ;
99use std:: net:: SocketAddr ;
1010use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
11- use std:: sync:: { Arc , Mutex , RwLock } ;
11+ use std:: sync:: { Arc , Mutex , RwLock , Weak } ;
1212use std:: time:: { Duration , Instant , SystemTime , UNIX_EPOCH } ;
1313
1414use 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