@@ -1166,6 +1166,14 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
11661166 /// The node_id of our counterparty
11671167 counterparty_node_id : PublicKey ,
11681168
1169+ /// Controls whether the monitor is allowed to automatically broadcast the latest holder commitment transaction.
1170+ ///
1171+ /// This flag is set to `false` when a channel is force-closed with `should_broadcast: false`,
1172+ /// indicating that broadcasting the latest holder commitment transaction would be unsafe.
1173+ ///
1174+ /// Default: `true`.
1175+ allow_automated_broadcast : bool ,
1176+
11691177 /// Initial counterparty commmitment data needed to recreate the commitment tx
11701178 /// in the persistence pipeline for third-party watchtowers. This will only be present on
11711179 /// monitors created after 0.0.117.
@@ -1467,6 +1475,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
14671475 ( 27 , self . first_confirmed_funding_txo, required) ,
14681476 ( 29 , self . initial_counterparty_commitment_tx, option) ,
14691477 ( 31 , self . funding. channel_parameters, required) ,
1478+ ( 33 , self . allow_automated_broadcast, required) ,
14701479 } ) ;
14711480
14721481 Ok ( ( ) )
@@ -1684,6 +1693,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
16841693
16851694 best_block,
16861695 counterparty_node_id : counterparty_node_id,
1696+ allow_automated_broadcast : true ,
16871697 initial_counterparty_commitment_info : None ,
16881698 initial_counterparty_commitment_tx : None ,
16891699 balances_empty_height : None ,
@@ -2038,7 +2048,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
20382048 /// may be to contact the other node operator out-of-band to coordinate other options available
20392049 /// to you.
20402050 #[ rustfmt:: skip]
2041- pub fn broadcast_latest_holder_commitment_txn < B : Deref , F : Deref , L : Deref > (
2051+ pub fn force_broadcast_latest_holder_commitment_txn_unsafe < B : Deref , F : Deref , L : Deref > (
20422052 & self , broadcaster : & B , fee_estimator : & F , logger : & L
20432053 )
20442054 where
@@ -3453,6 +3463,32 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34533463 ) ;
34543464 }
34553465
3466+ fn maybe_broadcast_latest_holder_commitment_txn < B : Deref , F : Deref , L : Deref > (
3467+ & mut self , broadcaster : & B , fee_estimator : & LowerBoundedFeeEstimator < F > ,
3468+ logger : & WithChannelMonitor < L > ,
3469+ ) where
3470+ B :: Target : BroadcasterInterface ,
3471+ F :: Target : FeeEstimator ,
3472+ L :: Target : Logger ,
3473+ {
3474+ if !self . allow_automated_broadcast {
3475+ return ;
3476+ }
3477+ let detected_funding_spend = self . funding_spend_confirmed . is_some ( )
3478+ || self
3479+ . onchain_events_awaiting_threshold_conf
3480+ . iter ( )
3481+ . any ( |event| matches ! ( event. event, OnchainEvent :: FundingSpendConfirmation { .. } ) ) ;
3482+ if detected_funding_spend {
3483+ log_trace ! (
3484+ logger,
3485+ "Avoiding commitment broadcast, already detected confirmed spend onchain"
3486+ ) ;
3487+ return ;
3488+ }
3489+ self . queue_latest_holder_commitment_txn_for_broadcast ( broadcaster, fee_estimator, logger) ;
3490+ }
3491+
34563492 #[ rustfmt:: skip]
34573493 fn update_monitor < B : Deref , F : Deref , L : Deref > (
34583494 & mut self , updates : & ChannelMonitorUpdate , broadcaster : & B , fee_estimator : & F , logger : & WithChannelMonitor < L >
@@ -3535,28 +3571,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35353571 ChannelMonitorUpdateStep :: ChannelForceClosed { should_broadcast } => {
35363572 log_trace ! ( logger, "Updating ChannelMonitor: channel force closed, should broadcast: {}" , should_broadcast) ;
35373573 self . lockdown_from_offchain = true ;
3538- if * should_broadcast {
3539- // There's no need to broadcast our commitment transaction if we've seen one
3540- // confirmed (even with 1 confirmation) as it'll be rejected as
3541- // duplicate/conflicting.
3542- let detected_funding_spend = self . funding_spend_confirmed . is_some ( ) ||
3543- self . onchain_events_awaiting_threshold_conf . iter ( ) . any (
3544- |event| matches ! ( event. event, OnchainEvent :: FundingSpendConfirmation { .. } ) ) ;
3545- if detected_funding_spend {
3546- log_trace ! ( logger, "Avoiding commitment broadcast, already detected confirmed spend onchain" ) ;
3547- continue ;
3548- }
3549- self . queue_latest_holder_commitment_txn_for_broadcast ( broadcaster, & bounded_fee_estimator, logger) ;
3550- } else if !self . holder_tx_signed {
3551- log_error ! ( logger, "WARNING: You have a potentially-unsafe holder commitment transaction available to broadcast" ) ;
3552- log_error ! ( logger, " in channel monitor for channel {}!" , & self . channel_id( ) ) ;
3553- log_error ! ( logger, " Read the docs for ChannelMonitor::broadcast_latest_holder_commitment_txn to take manual action!" ) ;
3554- } else {
3574+ if self . allow_automated_broadcast {
3575+ self . allow_automated_broadcast = * should_broadcast;
3576+ }
3577+ if !* should_broadcast && self . holder_tx_signed {
35553578 // If we generated a MonitorEvent::HolderForceClosed, the ChannelManager
35563579 // will still give us a ChannelForceClosed event with !should_broadcast, but we
35573580 // shouldn't print the scary warning above.
35583581 log_info ! ( logger, "Channel off-chain state closed after we broadcasted our latest commitment transaction." ) ;
35593582 }
3583+ self . maybe_broadcast_latest_holder_commitment_txn ( broadcaster, & bounded_fee_estimator, logger) ;
35603584 } ,
35613585 ChannelMonitorUpdateStep :: ShutdownScript { scriptpubkey } => {
35623586 log_trace ! ( logger, "Updating ChannelMonitor with shutdown script" ) ;
@@ -5438,6 +5462,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
54385462 let mut payment_preimages_with_info: Option < HashMap < _ , _ > > = None ;
54395463 let mut first_confirmed_funding_txo = RequiredWrapper ( None ) ;
54405464 let mut channel_parameters = None ;
5465+ let mut allow_automated_broadcast = None ;
54415466 read_tlv_fields ! ( reader, {
54425467 ( 1 , funding_spend_confirmed, option) ,
54435468 ( 3 , htlcs_resolved_on_chain, optional_vec) ,
@@ -5455,6 +5480,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
54555480 ( 27 , first_confirmed_funding_txo, ( default_value, outpoint) ) ,
54565481 ( 29 , initial_counterparty_commitment_tx, option) ,
54575482 ( 31 , channel_parameters, ( option: ReadableArgs , None ) ) ,
5483+ ( 33 , allow_automated_broadcast, option) ,
54585484 } ) ;
54595485 if let Some ( payment_preimages_with_info) = payment_preimages_with_info {
54605486 if payment_preimages_with_info. len ( ) != payment_preimages. len ( ) {
@@ -5618,6 +5644,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
56185644
56195645 best_block,
56205646 counterparty_node_id : counterparty_node_id. unwrap ( ) ,
5647+ allow_automated_broadcast : allow_automated_broadcast. unwrap_or ( true ) ,
56215648 initial_counterparty_commitment_info,
56225649 initial_counterparty_commitment_tx,
56235650 balances_empty_height,
0 commit comments