@@ -565,6 +565,13 @@ enum OnchainEvent {
565
565
/// output (and generate a SpendableOutput event).
566
566
on_to_local_output_csv : Option < u16 > ,
567
567
} ,
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 { } ,
568
575
}
569
576
570
577
impl Writeable for OnchainEventEntry {
@@ -609,6 +616,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
609
616
( 1 , MaturingOutput ) => {
610
617
( 0 , descriptor, required) ,
611
618
} ,
619
+ ( 2 , AlternativeFundingConfirmation ) => { } ,
612
620
( 3 , FundingSpendConfirmation ) => {
613
621
( 0 , on_local_output_csv, option) ,
614
622
( 1 , commitment_tx_to_counterparty_output, option) ,
@@ -618,7 +626,6 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
618
626
( 2 , preimage, option) ,
619
627
( 4 , on_to_local_output_csv, option) ,
620
628
} ,
621
-
622
629
) ;
623
630
624
631
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -677,6 +684,7 @@ pub(crate) enum ChannelMonitorUpdateStep {
677
684
channel_parameters : ChannelTransactionParameters ,
678
685
holder_commitment_tx : HolderCommitmentTransaction ,
679
686
counterparty_commitment_tx : CommitmentTransaction ,
687
+ confirmation_depth : u32 ,
680
688
} ,
681
689
RenegotiatedFundingLocked {
682
690
funding_txid : Txid ,
@@ -744,6 +752,7 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
744
752
( 1 , channel_parameters, ( required: ReadableArgs , None ) ) ,
745
753
( 3 , holder_commitment_tx, required) ,
746
754
( 5 , counterparty_commitment_tx, required) ,
755
+ ( 7 , confirmation_depth, required) ,
747
756
} ,
748
757
( 12 , RenegotiatedFundingLocked ) => {
749
758
( 1 , funding_txid, required) ,
@@ -1280,6 +1289,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
1280
1289
// commitment transactions, their ordering with respect to each other must remain the same.
1281
1290
current_holder_htlc_data : CommitmentHTLCData ,
1282
1291
prev_holder_htlc_data : Option < CommitmentHTLCData > ,
1292
+
1293
+ alternative_funding_confirmed : Option < ( Txid , u32 ) > ,
1283
1294
}
1284
1295
1285
1296
// 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> {
1555
1566
( 29 , self . initial_counterparty_commitment_tx, option) ,
1556
1567
( 31 , self . funding. channel_parameters, required) ,
1557
1568
( 32 , self . pending_funding, optional_vec) ,
1569
+ ( 34 , self . alternative_funding_confirmed, option) ,
1558
1570
} ) ;
1559
1571
1560
1572
Ok ( ( ) )
@@ -1780,6 +1792,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
1780
1792
// There are never any HTLCs in the initial commitment transaction
1781
1793
current_holder_htlc_data : CommitmentHTLCData :: new ( ) ,
1782
1794
prev_holder_htlc_data : None ,
1795
+
1796
+ alternative_funding_confirmed : None ,
1783
1797
} )
1784
1798
}
1785
1799
@@ -3413,7 +3427,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3413
3427
3414
3428
let mut other_commitment_tx = None :: < & CommitmentTransaction > ;
3415
3429
for ( funding, commitment_tx) in
3416
- core:: iter:: once ( & self . funding ) . chain ( self . pending_funding . iter ( ) ) . zip ( commitment_txs)
3430
+ core:: iter:: once ( & self . funding ) . chain ( & self . pending_funding ) . zip ( commitment_txs)
3417
3431
{
3418
3432
let trusted_tx = & commitment_tx. trust ( ) . built_transaction ( ) . transaction ;
3419
3433
if trusted_tx. input . len ( ) != 1 {
@@ -3468,7 +3482,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3468
3482
self . current_holder_commitment_number = current_funding_commitment_tx. commitment_number ( ) ;
3469
3483
self . onchain_tx_handler . provide_latest_holder_tx ( current_funding_commitment_tx. clone ( ) ) ;
3470
3484
for ( funding, mut commitment_tx) in core:: iter:: once ( & mut self . funding )
3471
- . chain ( self . pending_funding . iter_mut ( ) )
3485
+ . chain ( & mut self . pending_funding )
3472
3486
. zip ( commitment_txs. into_iter ( ) )
3473
3487
{
3474
3488
mem:: swap ( & mut commitment_tx, & mut funding. current_holder_commitment_tx ) ;
@@ -3676,7 +3690,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3676
3690
& mut self , logger : & WithChannelMonitor < L > ,
3677
3691
channel_parameters : & ChannelTransactionParameters ,
3678
3692
alternative_holder_commitment_tx : & HolderCommitmentTransaction ,
3679
- alternative_counterparty_commitment_tx : & CommitmentTransaction ,
3693
+ alternative_counterparty_commitment_tx : & CommitmentTransaction , confirmation_depth : u32 ,
3680
3694
) -> Result < ( ) , ( ) >
3681
3695
where
3682
3696
L :: Target : Logger ,
@@ -3803,9 +3817,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3803
3817
if new_funding. is_none ( ) {
3804
3818
return Err ( ( ) ) ;
3805
3819
}
3806
- let mut new_funding = new_funding. unwrap ( ) ;
3820
+ let new_funding = new_funding. unwrap ( ) ;
3807
3821
3808
- mem:: swap ( & mut self . funding , & mut new_funding) ;
3822
+ mem:: swap ( & mut self . funding , new_funding) ;
3809
3823
self . onchain_tx_handler . update_after_renegotiated_funding_locked (
3810
3824
self . funding . current_holder_commitment_tx . clone ( ) ,
3811
3825
self . funding . prev_holder_commitment_tx . clone ( ) ,
@@ -3928,11 +3942,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3928
3942
} ,
3929
3943
ChannelMonitorUpdateStep :: RenegotiatedFunding {
3930
3944
channel_parameters, holder_commitment_tx, counterparty_commitment_tx,
3945
+ confirmation_depth,
3931
3946
} => {
3932
3947
log_trace ! ( logger, "Updating ChannelMonitor with alternative holder and counterparty commitment transactions for funding txid {}" ,
3933
3948
channel_parameters. funding_outpoint. unwrap( ) . txid) ;
3934
3949
if let Err ( _) = self . renegotiated_funding (
3935
3950
logger, channel_parameters, holder_commitment_tx, counterparty_commitment_tx,
3951
+ * confirmation_depth,
3936
3952
) {
3937
3953
ret = Err ( ( ) ) ;
3938
3954
}
@@ -4873,6 +4889,50 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
4873
4889
}
4874
4890
}
4875
4891
4892
+ // A splice/dual-funded RBF transaction has confirmed. We can't promote the
4893
+ // `FundingScope` scope until we see the
4894
+ // [`ChannelMonitorUpdateStep::RenegotiatedFundingLocked`] for it, but we track the txid
4895
+ // so we know which holder commitment transaction we may need to broadcast.
4896
+ if let Some ( alternative_funding) = self . pending_funding . iter ( )
4897
+ . find ( |funding| funding. funding_txid ( ) == txid)
4898
+ {
4899
+ debug_assert ! ( self . funding_spend_confirmed. is_none( ) ) ;
4900
+ debug_assert ! (
4901
+ !self . onchain_events_awaiting_threshold_conf. iter( )
4902
+ . any( |e| matches!( e. event, OnchainEvent :: FundingSpendConfirmation { .. } ) )
4903
+ ) ;
4904
+
4905
+ let ( desc, msg) = if alternative_funding. channel_parameters . splice_parent_funding_txid . is_some ( ) {
4906
+ debug_assert ! ( tx. input. iter( ) . any( |input| {
4907
+ let funding_outpoint = self . funding. funding_outpoint( ) . into_bitcoin_outpoint( ) ;
4908
+ input. previous_output == funding_outpoint
4909
+ } ) ) ;
4910
+ ( "Splice" , "splice_locked" )
4911
+ } else {
4912
+ ( "RBF" , "channel_ready" )
4913
+ } ;
4914
+ let action = if self . no_further_updates_allowed ( ) {
4915
+ if self . holder_tx_signed {
4916
+ ", broadcasting post-splice holder commitment transaction" . to_string ( )
4917
+ } else {
4918
+ "" . to_string ( )
4919
+ }
4920
+ } else {
4921
+ format ! ( ", waiting for `{msg}` exchange" )
4922
+ } ;
4923
+ log_info ! ( logger, "{desc} for channel {} confirmed with txid {txid}{action}" , self . channel_id( ) ) ;
4924
+
4925
+ self . onchain_events_awaiting_threshold_conf . push ( OnchainEventEntry {
4926
+ txid,
4927
+ transaction : Some ( ( * tx) . clone ( ) ) ,
4928
+ height,
4929
+ block_hash : Some ( block_hash) ,
4930
+ event : OnchainEvent :: AlternativeFundingConfirmation { } ,
4931
+ } ) ;
4932
+
4933
+ continue ' tx_iter;
4934
+ }
4935
+
4876
4936
if tx. input . len ( ) == 1 {
4877
4937
// Assuming our keys were not leaked (in which case we're screwed no matter what),
4878
4938
// commitment transactions and HTLC transactions will all only ever have one input
@@ -5004,7 +5064,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
5004
5064
let unmatured_htlcs: Vec < _ > = self . onchain_events_awaiting_threshold_conf
5005
5065
. iter ( )
5006
5066
. filter_map ( |entry| match & entry. event {
5007
- OnchainEvent :: HTLCUpdate { source, .. } => Some ( source) ,
5067
+ OnchainEvent :: HTLCUpdate { source, .. } => Some ( source. clone ( ) ) ,
5008
5068
_ => None ,
5009
5069
} )
5010
5070
. collect ( ) ;
@@ -5019,7 +5079,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
5019
5079
#[ cfg( debug_assertions) ]
5020
5080
{
5021
5081
debug_assert ! (
5022
- !unmatured_htlcs. contains( && source) ,
5082
+ !unmatured_htlcs. contains( & source) ,
5023
5083
"An unmature HTLC transaction conflicts with a maturing one; failed to \
5024
5084
call either transaction_unconfirmed for the conflicting transaction \
5025
5085
or block_disconnected for a block containing it.") ;
@@ -5066,6 +5126,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
5066
5126
self . funding_spend_confirmed = Some ( entry. txid ) ;
5067
5127
self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
5068
5128
} ,
5129
+ OnchainEvent :: AlternativeFundingConfirmation { } => {
5130
+ // An alternative funding transaction has irrevocably confirmed and we're no
5131
+ // longer allowing monitor updates, so promote the `FundingScope` now.
5132
+ debug_assert ! ( self . no_further_updates_allowed( ) ) ;
5133
+ debug_assert_ne ! ( self . funding. funding_txid( ) , entry. txid) ;
5134
+ if let Err ( _) = self . promote_funding ( entry. txid ) {
5135
+ log_error ! ( logger, "Missing scope for alternative funding confirmation with txid {}" , entry. txid) ;
5136
+ }
5137
+ } ,
5069
5138
}
5070
5139
}
5071
5140
@@ -5173,6 +5242,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
5173
5242
{
5174
5243
log_trace ! ( logger, "Block {} at height {} disconnected" , header. block_hash( ) , height) ;
5175
5244
5245
+ self . alternative_funding_confirmed . take_if ( |( _, conf_height) | * conf_height == height) ;
5246
+
5176
5247
//We may discard:
5177
5248
//- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
5178
5249
//- maturing spendable output has transaction paying us has been disconnected
@@ -5199,6 +5270,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
5199
5270
F :: Target : FeeEstimator ,
5200
5271
L :: Target : Logger ,
5201
5272
{
5273
+ self . alternative_funding_confirmed . take_if ( |( funding_txid, _) | funding_txid == txid) ;
5274
+
5202
5275
let mut removed_height = None ;
5203
5276
for entry in self . onchain_events_awaiting_threshold_conf . iter ( ) {
5204
5277
if entry. txid == * txid {
@@ -5870,6 +5943,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
5870
5943
let mut first_negotiated_funding_txo = RequiredWrapper ( None ) ;
5871
5944
let mut channel_parameters = None ;
5872
5945
let mut pending_funding = None ;
5946
+ let mut alternative_funding_confirmed = None ;
5873
5947
read_tlv_fields ! ( reader, {
5874
5948
( 1 , funding_spend_confirmed, option) ,
5875
5949
( 3 , htlcs_resolved_on_chain, optional_vec) ,
@@ -5888,6 +5962,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
5888
5962
( 29 , initial_counterparty_commitment_tx, option) ,
5889
5963
( 31 , channel_parameters, ( option: ReadableArgs , None ) ) ,
5890
5964
( 32 , pending_funding, optional_vec) ,
5965
+ ( 34 , alternative_funding_confirmed, option) ,
5891
5966
} ) ;
5892
5967
if let Some ( payment_preimages_with_info) = payment_preimages_with_info {
5893
5968
if payment_preimages_with_info. len ( ) != payment_preimages. len ( ) {
@@ -6057,6 +6132,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
6057
6132
6058
6133
current_holder_htlc_data,
6059
6134
prev_holder_htlc_data,
6135
+
6136
+ alternative_funding_confirmed,
6060
6137
} ) ) )
6061
6138
}
6062
6139
}
0 commit comments