@@ -565,6 +565,12 @@ enum OnchainEvent {
565
565
/// output (and generate a SpendableOutput event).
566
566
on_to_local_output_csv : Option < u16 > ,
567
567
} ,
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 { } ,
568
574
}
569
575
570
576
impl Writeable for OnchainEventEntry {
@@ -609,6 +615,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
609
615
( 1 , MaturingOutput ) => {
610
616
( 0 , descriptor, required) ,
611
617
} ,
618
+ ( 2 , AlternativeFundingConfirmation ) => { } ,
612
619
( 3 , FundingSpendConfirmation ) => {
613
620
( 0 , on_local_output_csv, option) ,
614
621
( 1 , commitment_tx_to_counterparty_output, option) ,
@@ -618,7 +625,6 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
618
625
( 2 , preimage, option) ,
619
626
( 4 , on_to_local_output_csv, option) ,
620
627
} ,
621
-
622
628
) ;
623
629
624
630
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -4732,6 +4738,49 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4732
4738
}
4733
4739
}
4734
4740
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
+
4735
4784
if tx. input . len ( ) == 1 {
4736
4785
// Assuming our keys were not leaked (in which case we're screwed no matter what),
4737
4786
// commitment transactions and HTLC transactions will all only ever have one input
@@ -4863,7 +4912,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4863
4912
let unmatured_htlcs: Vec < _ > = self . onchain_events_awaiting_threshold_conf
4864
4913
. iter ( )
4865
4914
. filter_map ( |entry| match & entry. event {
4866
- OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
4915
+ OnchainEvent :: HTLCUpdate { source, .. } => Some ( source. clone ( ) ) ,
4867
4916
_ => None ,
4868
4917
} )
4869
4918
. collect ( ) ;
@@ -4878,7 +4927,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4878
4927
#[ cfg( debug_assertions) ]
4879
4928
{
4880
4929
debug_assert ! (
4881
- !unmatured_htlcs. contains( && source) ,
4930
+ !unmatured_htlcs. contains( & source) ,
4882
4931
"An unmature HTLC transaction conflicts with a maturing one; failed to \
4883
4932
call either transaction_unconfirmed for the conflicting transaction \
4884
4933
or block_disconnected for a block containing it.") ;
@@ -4925,6 +4974,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4925
4974
self . funding_spend_confirmed = Some ( entry. txid ) ;
4926
4975
self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
4927
4976
} ,
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
+ } ,
4928
4992
}
4929
4993
}
4930
4994
0 commit comments