@@ -565,6 +565,13 @@ enum OnchainEvent {
565565 /// output (and generate a SpendableOutput event).
566566 on_to_local_output_csv : Option < u16 > ,
567567 } ,
568+ /// An alternative funding transaction (due to a splice/RBF) has confirmed but can no longer be
569+ /// locked not as the monitor is no longer allowing updates. Note that we wait to promote the
570+ /// corresponding `FundingScope` until we see a
571+ /// [`ChannelMonitorUpdateStep::RenegotiatedFundingLocked`], but this event is only applicable
572+ /// once [`ChannelMonitor::no_further_updates_allowed`] returns true. We promote the
573+ /// `FundingScope` once the funding transaction is irrevocably confirmed.
574+ AlternativeFundingConfirmation { } ,
568575}
569576
570577impl Writeable for OnchainEventEntry {
@@ -609,6 +616,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
609616 ( 1 , MaturingOutput ) => {
610617 ( 0 , descriptor, required) ,
611618 } ,
619+ ( 2 , AlternativeFundingConfirmation ) => { } ,
612620 ( 3 , FundingSpendConfirmation ) => {
613621 ( 0 , on_local_output_csv, option) ,
614622 ( 1 , commitment_tx_to_counterparty_output, option) ,
@@ -618,7 +626,6 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
618626 ( 2 , preimage, option) ,
619627 ( 4 , on_to_local_output_csv, option) ,
620628 } ,
621-
622629) ;
623630
624631#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -1280,6 +1287,10 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
12801287 // commitment transactions, their ordering with respect to each other must remain the same.
12811288 current_holder_htlc_data : CommitmentHTLCData ,
12821289 prev_holder_htlc_data : Option < CommitmentHTLCData > ,
1290+
1291+ // Tracks the txid and confirmation height of a renegotiated funding transaction upon
1292+ // confirmation. Used to determine which commitment we should broadcast when necessary.
1293+ alternative_funding_confirmed : Option < ( Txid , u32 ) > ,
12831294}
12841295
12851296// Macro helper to access holder commitment HTLC data (including both non-dust and dust) while
@@ -1555,6 +1566,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
15551566 ( 29 , self . initial_counterparty_commitment_tx, option) ,
15561567 ( 31 , self . funding. channel_parameters, required) ,
15571568 ( 32 , self . pending_funding, optional_vec) ,
1569+ ( 34 , self . alternative_funding_confirmed, option) ,
15581570 } ) ;
15591571
15601572 Ok ( ( ) )
@@ -1780,6 +1792,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17801792 // There are never any HTLCs in the initial commitment transaction
17811793 current_holder_htlc_data : CommitmentHTLCData :: new ( ) ,
17821794 prev_holder_htlc_data : None ,
1795+
1796+ alternative_funding_confirmed : None ,
17831797 } )
17841798 }
17851799
@@ -3815,6 +3829,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38153829 for funding in self . pending_funding . drain ( ..) {
38163830 self . outputs_to_watch . remove ( & funding. funding_txid ( ) ) ;
38173831 }
3832+ if let Some ( ( alternative_funding_txid, _) ) = self . alternative_funding_confirmed . take ( ) {
3833+ debug_assert_eq ! ( alternative_funding_txid, new_funding_txid) ;
3834+ }
38183835
38193836 Ok ( ( ) )
38203837 }
@@ -4873,6 +4890,44 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
48734890 }
48744891 }
48754892
4893+ // A splice/dual-funded RBF transaction has confirmed. We can't promote the
4894+ // `FundingScope` scope until we see the
4895+ // [`ChannelMonitorUpdateStep::RenegotiatedFundingLocked`] for it, but we track the txid
4896+ // so we know which holder commitment transaction we may need to broadcast.
4897+ if let Some ( _alternative_funding) = self
4898+ . pending_funding
4899+ . iter ( )
4900+ . find ( |funding| funding. funding_txid ( ) == txid)
4901+ {
4902+ debug_assert ! ( self . alternative_funding_confirmed. is_none( ) ) ;
4903+ debug_assert ! (
4904+ !self . onchain_events_awaiting_threshold_conf. iter( )
4905+ . any( |e| matches!( e. event, OnchainEvent :: AlternativeFundingConfirmation { } ) )
4906+ ) ;
4907+ debug_assert ! ( self . funding_spend_confirmed. is_none( ) ) ;
4908+ debug_assert ! (
4909+ !self . onchain_events_awaiting_threshold_conf. iter( )
4910+ . any( |e| matches!( e. event, OnchainEvent :: FundingSpendConfirmation { .. } ) )
4911+ ) ;
4912+
4913+ self . alternative_funding_confirmed = Some ( ( txid, height) ) ;
4914+
4915+ if self . no_further_updates_allowed ( ) {
4916+ // We can no longer rely on
4917+ // [`ChannelMonitorUpdateStep::RenegotiatedFundingLocked`] to promote the
4918+ // scope, do so when the funding is no longer under reorg risk.
4919+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
4920+ txid,
4921+ transaction : Some ( ( * tx) . clone ( ) ) ,
4922+ height,
4923+ block_hash : Some ( block_hash) ,
4924+ event : OnchainEvent :: AlternativeFundingConfirmation { } ,
4925+ } ) ;
4926+ }
4927+
4928+ continue ' tx_iter;
4929+ }
4930+
48764931 if tx. input . len ( ) == 1 {
48774932 // Assuming our keys were not leaked (in which case we're screwed no matter what),
48784933 // commitment transactions and HTLC transactions will all only ever have one input
@@ -5004,7 +5059,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
50045059 let unmatured_htlcs: Vec < _ > = self . onchain_events_awaiting_threshold_conf
50055060 . iter ( )
50065061 . filter_map ( |entry| match & entry. event {
5007- OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
5062+ OnchainEvent :: HTLCUpdate { source, .. } => Some ( source. clone ( ) ) ,
50085063 _ => None ,
50095064 } )
50105065 . collect ( ) ;
@@ -5019,7 +5074,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
50195074 #[ cfg( debug_assertions) ]
50205075 {
50215076 debug_assert ! (
5022- !unmatured_htlcs. contains( && source) ,
5077+ !unmatured_htlcs. contains( & source) ,
50235078 "An unmature HTLC transaction conflicts with a maturing one; failed to \
50245079 call either transaction_unconfirmed for the conflicting transaction \
50255080 or block_disconnected for a block containing it.") ;
@@ -5066,6 +5121,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
50665121 self . funding_spend_confirmed = Some ( entry. txid ) ;
50675122 self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
50685123 } ,
5124+ OnchainEvent :: AlternativeFundingConfirmation { } => {
5125+ // An alternative funding transaction has irrevocably confirmed and we're no
5126+ // longer allowing monitor updates, so promote the `FundingScope` now.
5127+ debug_assert ! ( self . no_further_updates_allowed( ) ) ;
5128+ debug_assert_ne ! ( self . funding. funding_txid( ) , entry. txid) ;
5129+ if let Err ( _) = self . promote_funding ( entry. txid ) {
5130+ log_error ! ( logger, "Missing scope for alternative funding confirmation with txid {}" , entry. txid) ;
5131+ }
5132+ } ,
50695133 }
50705134 }
50715135
@@ -5178,6 +5242,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
51785242 //- maturing spendable output has transaction paying us has been disconnected
51795243 self . onchain_events_awaiting_threshold_conf . retain ( |ref entry| entry. height < height) ;
51805244
5245+ // TODO: Replace with `take_if` once our MSRV is >= 1.80.
5246+ if let Some ( ( _, conf_height) ) = self . alternative_funding_confirmed . as_ref ( ) {
5247+ if * conf_height == height {
5248+ self . alternative_funding_confirmed . take ( ) ;
5249+ }
5250+ }
5251+
51815252 let bounded_fee_estimator = LowerBoundedFeeEstimator :: new ( fee_estimator) ;
51825253 let conf_target = self . closure_conf_target ( ) ;
51835254 self . onchain_tx_handler . block_disconnected (
@@ -5217,6 +5288,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
52175288
52185289 debug_assert ! ( !self . onchain_events_awaiting_threshold_conf. iter( ) . any( |ref entry| entry. txid == * txid) ) ;
52195290
5291+ // TODO: Replace with `take_if` once our MSRV is >= 1.80.
5292+ if let Some ( ( alternative_funding_txid, _) ) = self . alternative_funding_confirmed . as_ref ( ) {
5293+ if alternative_funding_txid == txid {
5294+ self . alternative_funding_confirmed . take ( ) ;
5295+ }
5296+ }
5297+
52205298 let conf_target = self . closure_conf_target ( ) ;
52215299 self . onchain_tx_handler . transaction_unconfirmed (
52225300 txid, broadcaster, conf_target, & self . destination_script , fee_estimator, logger
@@ -5870,6 +5948,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
58705948 let mut first_negotiated_funding_txo = RequiredWrapper ( None ) ;
58715949 let mut channel_parameters = None ;
58725950 let mut pending_funding = None ;
5951+ let mut alternative_funding_confirmed = None ;
58735952 read_tlv_fields ! ( reader, {
58745953 ( 1 , funding_spend_confirmed, option) ,
58755954 ( 3 , htlcs_resolved_on_chain, optional_vec) ,
@@ -5888,6 +5967,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
58885967 ( 29 , initial_counterparty_commitment_tx, option) ,
58895968 ( 31 , channel_parameters, ( option: ReadableArgs , None ) ) ,
58905969 ( 32 , pending_funding, optional_vec) ,
5970+ ( 34 , alternative_funding_confirmed, option) ,
58915971 } ) ;
58925972 if let Some ( payment_preimages_with_info) = payment_preimages_with_info {
58935973 if payment_preimages_with_info. len ( ) != payment_preimages. len ( ) {
@@ -6057,6 +6137,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
60576137
60586138 current_holder_htlc_data,
60596139 prev_holder_htlc_data,
6140+
6141+ alternative_funding_confirmed,
60606142 } ) ) )
60616143 }
60626144}
0 commit comments