@@ -565,6 +565,12 @@ enum OnchainEvent {
565565 /// output (and generate a SpendableOutput event).
566566 on_to_local_output_csv : Option < u16 > ,
567567 } ,
568+ /// The txid of an alternative funding transaction (due to a splice) that has confirmed but is
569+ /// not yet locked, invalidating the previous funding transaction as it now spent. Note that we
570+ /// wait to promote the corresponding `FundingScope` until we see a
571+ /// [`ChannelMonitorUpdateStep::RenegotiatedFundingLocked`] or if the alternative funding
572+ /// transaction is irrevocably confirmed.
573+ AlternativeFundingConfirmation { } ,
568574}
569575
570576impl Writeable for OnchainEventEntry {
@@ -609,6 +615,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
609615 ( 1 , MaturingOutput ) => {
610616 ( 0 , descriptor, required) ,
611617 } ,
618+ ( 2 , AlternativeFundingConfirmation ) => { } ,
612619 ( 3 , FundingSpendConfirmation ) => {
613620 ( 0 , on_local_output_csv, option) ,
614621 ( 1 , commitment_tx_to_counterparty_output, option) ,
@@ -618,7 +625,6 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
618625 ( 2 , preimage, option) ,
619626 ( 4 , on_to_local_output_csv, option) ,
620627 } ,
621-
622628) ;
623629
624630#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -4732,6 +4738,49 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
47324738 }
47334739 }
47344740
4741+ // A splice transaction has confirmed. We can't promote the splice's scope until we see
4742+ // the corresponding monitor update for it, but we track the txid so we know which
4743+ // holder commitment transaction we may need to broadcast.
4744+ if let Some ( alternative_funding) = self . pending_funding . iter ( )
4745+ . find ( |funding| funding. funding_txid ( ) == txid)
4746+ {
4747+ debug_assert ! ( self . funding_spend_confirmed. is_none( ) ) ;
4748+ debug_assert ! (
4749+ !self . onchain_events_awaiting_threshold_conf. iter( )
4750+ . any( |e| matches!( e. event, OnchainEvent :: FundingSpendConfirmation { .. } ) )
4751+ ) ;
4752+ debug_assert_eq ! (
4753+ self . funding. funding_outpoint( ) . into_bitcoin_outpoint( ) ,
4754+ tx. input[ 0 ] . previous_output
4755+ ) ;
4756+
4757+ let ( desc, msg) = if alternative_funding. channel_parameters . splice_parent_funding_txid . is_some ( ) {
4758+ ( "Splice" , "splice_locked" )
4759+ } else {
4760+ ( "RBF" , "channel_ready" )
4761+ } ;
4762+ let action = if self . no_further_updates_allowed ( ) {
4763+ if self . holder_tx_signed {
4764+ ", broadcasting post-splice holder commitment transaction" . to_string ( )
4765+ } else {
4766+ "" . to_string ( )
4767+ }
4768+ } else {
4769+ format ! ( ", waiting for `{}` exchange" , msg)
4770+ } ;
4771+ log_info ! ( logger, "{desc} for channel {} confirmed with txid {txid}{action}" , self . channel_id( ) ) ;
4772+
4773+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
4774+ txid,
4775+ transaction : Some ( ( * tx) . clone ( ) ) ,
4776+ height,
4777+ block_hash : Some ( block_hash) ,
4778+ event : OnchainEvent :: AlternativeFundingConfirmation { } ,
4779+ } ) ;
4780+
4781+ continue ' tx_iter;
4782+ }
4783+
47354784 if tx. input . len ( ) == 1 {
47364785 // Assuming our keys were not leaked (in which case we're screwed no matter what),
47374786 // commitment transactions and HTLC transactions will all only ever have one input
@@ -4863,7 +4912,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
48634912 let unmatured_htlcs: Vec < _ > = self . onchain_events_awaiting_threshold_conf
48644913 . iter ( )
48654914 . filter_map ( |entry| match & entry. event {
4866- OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
4915+ OnchainEvent :: HTLCUpdate { source, .. } => Some ( source. clone ( ) ) ,
48674916 _ => None ,
48684917 } )
48694918 . collect ( ) ;
@@ -4878,7 +4927,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
48784927 #[ cfg( debug_assertions) ]
48794928 {
48804929 debug_assert ! (
4881- !unmatured_htlcs. contains( && source) ,
4930+ !unmatured_htlcs. contains( & source) ,
48824931 "An unmature HTLC transaction conflicts with a maturing one; failed to \
48834932 call either transaction_unconfirmed for the conflicting transaction \
48844933 or block_disconnected for a block containing it.") ;
@@ -4925,6 +4974,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
49254974 self . funding_spend_confirmed = Some ( entry. txid ) ;
49264975 self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
49274976 } ,
4977+ OnchainEvent :: AlternativeFundingConfirmation { } => {
4978+ // An alternative funding transaction has irrevocably confirmed. Locate the
4979+ // corresponding scope and promote it if the monitor is no longer allowing
4980+ // updates. Otherwise, we expect it to be promoted via
4981+ // [`ChannelMonitorUpdateStep::RenegotiatedFundingLocked`].
4982+ if self . no_further_updates_allowed ( ) {
4983+ let funding_txid = entry. transaction
4984+ . expect ( "Transactions are always present for AlternativeFundingConfirmation entries" )
4985+ . compute_txid ( ) ;
4986+ debug_assert_ne ! ( self . funding. funding_txid( ) , funding_txid) ;
4987+ if let Err ( _) = self . promote_funding ( funding_txid) {
4988+ log_error ! ( logger, "Missing scope for alternative funding confirmation with txid {}" , entry. txid) ;
4989+ }
4990+ }
4991+ } ,
49284992 }
49294993 }
49304994
0 commit comments