@@ -1175,6 +1175,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
11751175 /// True once we've observed either funding transaction on-chain. Older monitors assume this is
11761176 /// `true` when absent during upgrade so holder broadcasts aren't gated unexpectedly.
11771177 funding_seen_onchain : bool ,
1178+ /// Tracks whether manual-broadcasting was requested before the funding transaction appeared on-chain.
1179+ manual_broadcast_pending : bool ,
11781180
11791181 latest_update_id : u64 ,
11801182 commitment_transaction_number_obscure_factor : u64 ,
@@ -1707,6 +1709,7 @@ pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
17071709 ( 34 , channel_monitor. alternative_funding_confirmed, option) ,
17081710 ( 35 , channel_monitor. is_manual_broadcast, required) ,
17091711 ( 37 , channel_monitor. funding_seen_onchain, required) ,
1712+ ( 39 , channel_monitor. manual_broadcast_pending, required) ,
17101713 } ) ;
17111714
17121715 Ok ( ( ) )
@@ -1884,6 +1887,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
18841887
18851888 is_manual_broadcast,
18861889 funding_seen_onchain : false ,
1890+ manual_broadcast_pending : false ,
18871891
18881892 latest_update_id : 0 ,
18891893 commitment_transaction_number_obscure_factor,
@@ -4011,6 +4015,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40114015 // the funding transaction on-chain, do not queue any transactions.
40124016 if require_funding_seen && self . is_manual_broadcast && !self . funding_seen_onchain {
40134017 log_info ! ( logger, "Not broadcasting holder commitment for manual-broadcast channel before funding appears on-chain" ) ;
4018+ self . manual_broadcast_pending = true ;
40144019 return ;
40154020 }
40164021 let reason = ClosureReason :: HolderForceClosed {
@@ -4023,6 +4028,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40234028 claimable_outpoints, self . best_block . height , self . best_block . height , broadcaster,
40244029 conf_target, & self . destination_script , fee_estimator, logger,
40254030 ) ;
4031+ self . manual_broadcast_pending = false ;
40264032 }
40274033
40284034 fn renegotiated_funding < L : Deref > (
@@ -5274,6 +5280,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
52745280
52755281 let mut watch_outputs = Vec :: new ( ) ;
52765282 let mut claimable_outpoints = Vec :: new ( ) ;
5283+
5284+ if self . is_manual_broadcast && self . funding_seen_onchain && self . manual_broadcast_pending {
5285+ self . queue_latest_holder_commitment_txn_for_broadcast (
5286+ & broadcaster,
5287+ fee_estimator,
5288+ logger,
5289+ true ,
5290+ ) ;
5291+ }
52775292 ' tx_iter: for tx in & txn_matched {
52785293 let txid = tx. compute_txid ( ) ;
52795294 log_trace ! ( logger, "Transaction {} confirmed in block {}" , txid , block_hash) ;
@@ -5488,12 +5503,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
54885503 }
54895504
54905505 if should_broadcast_commitment {
5491- // Avoid broadcasting in manual-broadcast mode until funding is seen on-chain.
5492- if !self . is_manual_broadcast || self . funding_seen_onchain {
5493- let ( mut claimables, mut outputs) =
5494- self . generate_claimable_outpoints_and_watch_outputs ( None ) ;
5506+ // Always update holder state, but only enqueue broadcast data once funding is seen in
5507+ // manual-broadcast mode.
5508+ let ( mut claimables, mut outputs) =
5509+ self . generate_claimable_outpoints_and_watch_outputs ( None ) ;
5510+ if self . is_manual_broadcast && !self . funding_seen_onchain {
5511+ self . manual_broadcast_pending = true ;
5512+ } else {
54955513 claimable_outpoints. append ( & mut claimables) ;
54965514 watch_outputs. append ( & mut outputs) ;
5515+ self . manual_broadcast_pending = false ;
54975516 }
54985517 }
54995518
@@ -5531,13 +5550,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
55315550 let should_broadcast = self . should_broadcast_holder_commitment_txn ( logger) ;
55325551 if let Some ( payment_hash) = should_broadcast {
55335552 let reason = ClosureReason :: HTLCsTimedOut { payment_hash : Some ( payment_hash) } ;
5553+ let ( mut new_outpoints, mut new_outputs) =
5554+ self . generate_claimable_outpoints_and_watch_outputs ( Some ( reason) ) ;
55345555 if self . is_manual_broadcast && !self . funding_seen_onchain {
5535- let _ = self . generate_claimable_outpoints_and_watch_outputs ( Some ( reason ) ) ;
5556+ self . manual_broadcast_pending = true ;
55365557 } else {
5537- let ( mut new_outpoints, mut new_outputs) =
5538- self . generate_claimable_outpoints_and_watch_outputs ( Some ( reason) ) ;
55395558 claimable_outpoints. append ( & mut new_outpoints) ;
55405559 watch_outputs. append ( & mut new_outputs) ;
5560+ self . manual_broadcast_pending = false ;
55415561 }
55425562 }
55435563
@@ -6493,6 +6513,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
64936513 let mut alternative_funding_confirmed = None ;
64946514 let mut is_manual_broadcast = None ;
64956515 let mut funding_seen_onchain = None ;
6516+ let mut manual_broadcast_pending = None ;
64966517 read_tlv_fields ! ( reader, {
64976518 ( 1 , funding_spend_confirmed, option) ,
64986519 ( 3 , htlcs_resolved_on_chain, optional_vec) ,
@@ -6514,6 +6535,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65146535 ( 34 , alternative_funding_confirmed, option) ,
65156536 ( 35 , is_manual_broadcast, option) ,
65166537 ( 37 , funding_seen_onchain, option) ,
6538+ ( 39 , manual_broadcast_pending, option) ,
65176539 } ) ;
65186540 // Note that `payment_preimages_with_info` was added (and is always written) in LDK 0.1, so
65196541 // we can use it to determine if this monitor was last written by LDK 0.1 or later.
@@ -6548,6 +6570,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65486570 let channel_parameters = channel_parameters. unwrap_or_else ( || {
65496571 onchain_tx_handler. channel_parameters ( ) . clone ( )
65506572 } ) ;
6573+ let manual_broadcast_pending = manual_broadcast_pending. unwrap_or ( false ) ;
65516574
65526575 // Monitors for anchor outputs channels opened in v0.0.116 suffered from a bug in which the
65536576 // wrong `counterparty_payment_script` was being tracked. Fix it now on deserialization to
@@ -6634,6 +6657,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66346657 is_manual_broadcast : is_manual_broadcast. unwrap_or ( false ) ,
66356658 // Assume "seen" when absent to prevent gating holder broadcasts after upgrade.
66366659 funding_seen_onchain : funding_seen_onchain. unwrap_or ( true ) ,
6660+ manual_broadcast_pending,
66376661
66386662 latest_update_id,
66396663 commitment_transaction_number_obscure_factor,
@@ -7122,6 +7146,11 @@ mod tests {
71227146 let header = create_dummy_header ( prev_hash, 0 ) ;
71237147 monitor. best_block_updated ( & header, 10 , & * broadcaster, & fee_estimator, & logger) ;
71247148 assert ! ( broadcaster. txn_broadcast( ) . is_empty( ) ) ;
7149+ {
7150+ let inner = monitor. inner . lock ( ) . unwrap ( ) ;
7151+ assert ! ( !inner. funding_seen_onchain) ;
7152+ assert ! ( inner. manual_broadcast_pending) ;
7153+ }
71257154
71267155 // Now confirm the funding transaction via transactions_confirmed.
71277156 let fund_block = create_dummy_block ( header. block_hash ( ) , 1 , vec ! [ funding_tx. clone( ) ] ) ;
@@ -7135,6 +7164,10 @@ mod tests {
71357164 & fee_estimator,
71367165 & logger,
71377166 ) ;
7167+ {
7168+ let inner = monitor. inner . lock ( ) . unwrap ( ) ;
7169+ assert ! ( !inner. manual_broadcast_pending) ;
7170+ }
71387171
71397172 // Next height update should allow broadcast.
71407173 {
0 commit comments