@@ -586,6 +586,11 @@ pub(crate) enum ChannelMonitorUpdateStep {
586
586
claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
587
587
nondust_htlc_sources : Vec < HTLCSource > ,
588
588
} ,
589
+ LatestHolderCommitment {
590
+ commitment_txs : Vec < HolderCommitmentTransaction > ,
591
+ htlc_data : CommitmentHTLCData ,
592
+ claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
593
+ } ,
589
594
LatestCounterpartyCommitmentTXInfo {
590
595
commitment_txid : Txid ,
591
596
htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > ,
@@ -632,6 +637,7 @@ impl ChannelMonitorUpdateStep {
632
637
fn variant_name ( & self ) -> & ' static str {
633
638
match self {
634
639
ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo" ,
640
+ ChannelMonitorUpdateStep :: LatestHolderCommitment { .. } => "LatestHolderCommitment" ,
635
641
ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo" ,
636
642
ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTX { .. } => "LatestCounterpartyCommitmentTX" ,
637
643
ChannelMonitorUpdateStep :: PaymentPreimage { .. } => "PaymentPreimage" ,
@@ -676,6 +682,10 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
676
682
( 6 , LatestCounterpartyCommitmentTX ) => {
677
683
( 0 , htlc_outputs, required_vec) ,
678
684
( 2 , commitment_tx, required) ,
685
+ ( 8 , LatestHolderCommitment ) => {
686
+ ( 1 , commitment_txs, required_vec) ,
687
+ ( 3 , htlc_data, required) ,
688
+ ( 5 , claimed_htlcs, required_vec) ,
679
689
} ,
680
690
( 10 , RenegotiatedFunding ) => {
681
691
( 1 , channel_parameters, ( required: ReadableArgs , None ) ) ,
@@ -932,12 +942,12 @@ impl<Signer: EcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer:
932
942
}
933
943
}
934
944
935
- #[ derive( Clone , PartialEq ) ]
936
- struct CommitmentHTLCData {
945
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
946
+ pub ( crate ) struct CommitmentHTLCData {
937
947
// These must be sorted in increasing output index order to match the expected order of the
938
948
// HTLCs in the `CommitmentTransaction`.
939
- nondust_htlc_sources : Vec < HTLCSource > ,
940
- dust_htlcs : Vec < ( HTLCOutputInCommitment , Option < HTLCSource > ) > ,
949
+ pub nondust_htlc_sources: Vec <HTLCSource >,
950
+ pub dust_htlcs: Vec <( HTLCOutputInCommitment , Option <HTLCSource >) >,
941
951
}
942
952
943
953
impl CommitmentHTLCData {
@@ -946,6 +956,11 @@ impl CommitmentHTLCData {
946
956
}
947
957
}
948
958
959
+ impl_writeable_tlv_based!( CommitmentHTLCData , {
960
+ ( 1 , nondust_htlc_sources, required_vec) ,
961
+ ( 3 , dust_htlcs, required_vec) ,
962
+ } ) ;
963
+
949
964
impl TryFrom <HolderSignedTx > for CommitmentHTLCData {
950
965
type Error = ( ) ;
951
966
fn try_from( value: HolderSignedTx ) -> Result <Self , Self :: Error > {
@@ -3192,11 +3207,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3192
3207
/// up-to-date as our holder commitment transaction is updated.
3193
3208
/// Panics if set_on_holder_tx_csv has never been called.
3194
3209
fn provide_latest_holder_commitment_tx(
3195
- & mut self , mut holder_commitment_tx : HolderCommitmentTransaction ,
3210
+ & mut self , holder_commitment_tx: HolderCommitmentTransaction ,
3196
3211
htlc_outputs: Vec <( HTLCOutputInCommitment , Option <Signature >, Option <HTLCSource >) >,
3197
3212
claimed_htlcs: & [ ( SentHTLCId , PaymentPreimage ) ] , mut nondust_htlc_sources: Vec <HTLCSource >,
3198
- ) {
3199
- let dust_htlcs : Vec < _ > = if htlc_outputs. iter ( ) . any ( |( _, s, _) | s. is_some ( ) ) {
3213
+ ) -> Result < ( ) , & ' static str > {
3214
+ let htlc_data = if htlc_outputs. iter( ) . any( |( _, s, _) | s. is_some( ) ) {
3200
3215
// If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the
3201
3216
// `holder_commitment_tx`. In the future, we'll no longer provide the redundant data
3202
3217
// and just pass in source data via `nondust_htlc_sources`.
@@ -3224,7 +3239,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3224
3239
None
3225
3240
} ) . collect( ) ;
3226
3241
3227
- dust_htlcs
3242
+ CommitmentHTLCData { nondust_htlc_sources , dust_htlcs }
3228
3243
} else {
3229
3244
// If we don't have any non-dust HTLCs in htlc_outputs, assume they were all passed via
3230
3245
// `nondust_htlc_sources`, building up the final htlc_outputs by combining
@@ -3251,30 +3266,67 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3251
3266
assert!( sources. next( ) . is_none( ) , "All HTLC sources should have been exhausted" ) ;
3252
3267
3253
3268
// This only includes dust HTLCs as checked above.
3254
- htlc_outputs. into_iter ( ) . map ( |( htlc, _, source) | ( htlc, source) ) . collect ( )
3269
+ let dust_htlcs = htlc_outputs. into_iter( ) . map( |( htlc, _, source) | ( htlc, source) ) . collect( ) ;
3270
+
3271
+ CommitmentHTLCData { nondust_htlc_sources, dust_htlcs }
3255
3272
} ;
3256
3273
3257
- self . current_holder_commitment_number = holder_commitment_tx. trust ( ) . commitment_number ( ) ;
3258
- self . onchain_tx_handler . provide_latest_holder_tx ( holder_commitment_tx. clone ( ) ) ;
3274
+ self . update_holder_commitment_data(
3275
+ vec![ holder_commitment_tx] , htlc_data, claimed_htlcs. to_vec( ) ,
3276
+ )
3277
+ }
3259
3278
3260
- mem:: swap ( & mut holder_commitment_tx, & mut self . funding . current_holder_commitment_tx ) ;
3261
- self . funding . prev_holder_commitment_tx = Some ( holder_commitment_tx) ;
3262
- let mut holder_htlc_data = CommitmentHTLCData { nondust_htlc_sources, dust_htlcs } ;
3263
- mem:: swap ( & mut holder_htlc_data, & mut self . current_holder_htlc_data ) ;
3264
- self . prev_holder_htlc_data = Some ( holder_htlc_data) ;
3279
+ fn update_holder_commitment_data(
3280
+ & mut self , mut commitment_txs: Vec <HolderCommitmentTransaction >,
3281
+ mut htlc_data: CommitmentHTLCData , claimed_htlcs: Vec <( SentHTLCId , PaymentPreimage ) >,
3282
+ ) -> Result <( ) , & ' static str > {
3283
+ if self . pending_funding. len( ) + 1 != commitment_txs. len( ) {
3284
+ return Err ( "Commitment transaction(s) mismatch" ) ;
3285
+ }
3286
+
3287
+ let mut current_funding_commitment = commitment_txs. remove( 0 ) ;
3288
+ let holder_commitment_number = current_funding_commitment. commitment_number( ) ;
3289
+ for ( pending_funding, mut commitment_tx) in self . pending_funding. iter_mut( ) . zip( commitment_txs. into_iter( ) ) {
3290
+ let trusted_tx = commitment_tx. trust( ) ;
3291
+ if trusted_tx. commitment_number( ) != holder_commitment_number {
3292
+ return Err ( "Commitment number mismatch" ) ;
3293
+ }
3294
+
3295
+ let funding_outpoint_spent =
3296
+ trusted_tx. built_transaction( ) . transaction. tx_in( 0 ) . map( |input| input. previous_output) . ok( ) ;
3297
+ let expected_funding_outpoint_spent =
3298
+ pending_funding. channel_parameters. funding_outpoint. map( |op| op. into_bitcoin_outpoint( ) ) ;
3299
+ if funding_outpoint_spent != expected_funding_outpoint_spent {
3300
+ return Err ( "Funding outpoint mismatch" ) ;
3301
+ }
3302
+
3303
+ mem:: swap( & mut commitment_tx, & mut pending_funding. current_holder_commitment_tx) ;
3304
+ pending_funding. prev_holder_commitment_tx = Some ( commitment_tx) ;
3305
+ }
3306
+
3307
+ self . current_holder_commitment_number = holder_commitment_number;
3308
+ self . onchain_tx_handler. provide_latest_holder_tx( current_funding_commitment. clone( ) ) ;
3309
+ mem:: swap( & mut current_funding_commitment, & mut self . funding. current_holder_commitment_tx) ;
3310
+ self . funding. prev_holder_commitment_tx = Some ( current_funding_commitment) ;
3311
+
3312
+ mem:: swap( & mut htlc_data, & mut self . current_holder_htlc_data) ;
3313
+ self . prev_holder_htlc_data = Some ( htlc_data) ;
3265
3314
3266
3315
for ( claimed_htlc_id, claimed_preimage) in claimed_htlcs {
3267
3316
#[ cfg( debug_assertions) ] {
3268
3317
let cur_counterparty_htlcs = self . funding. counterparty_claimable_outpoints. get(
3269
- & self . funding . current_counterparty_commitment_txid . unwrap ( ) ) . unwrap ( ) ;
3318
+ & self . funding. current_counterparty_commitment_txid. unwrap( )
3319
+ ) . unwrap( ) ;
3270
3320
assert!( cur_counterparty_htlcs. iter( ) . any( |( _, source_opt) | {
3271
3321
if let Some ( source) = source_opt {
3272
- SentHTLCId :: from_source( source) == * claimed_htlc_id
3322
+ SentHTLCId :: from_source( source) == claimed_htlc_id
3273
3323
} else { false }
3274
3324
} ) ) ;
3275
3325
}
3276
- self . counterparty_fulfilled_htlcs . insert ( * claimed_htlc_id, * claimed_preimage) ;
3326
+ self . counterparty_fulfilled_htlcs. insert( claimed_htlc_id, claimed_preimage) ;
3277
3327
}
3328
+
3329
+ Ok ( ( ) )
3278
3330
}
3279
3331
3280
3332
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
@@ -3579,9 +3631,25 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3579
3631
ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => {
3580
3632
log_trace!( logger, "Updating ChannelMonitor with latest holder commitment transaction info" ) ;
3581
3633
if self . lockdown_from_offchain { panic!( ) ; }
3582
- self . provide_latest_holder_commitment_tx ( commitment_tx. clone ( ) , htlc_outputs. clone ( ) , & claimed_htlcs, nondust_htlc_sources. clone ( ) ) ;
3634
+ if let Err ( e) = self . provide_latest_holder_commitment_tx(
3635
+ commitment_tx. clone( ) , htlc_outputs. clone( ) , & claimed_htlcs,
3636
+ nondust_htlc_sources. clone( )
3637
+ ) {
3638
+ log_error!( logger, "Failed updating latest holder commitment transaction info: {}" , e) ;
3639
+ }
3583
3640
}
3584
- // Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitmentTX`.
3641
+ ChannelMonitorUpdateStep :: LatestHolderCommitment {
3642
+ commitment_txs, htlc_data, claimed_htlcs,
3643
+ } => {
3644
+ log_trace!( logger, "Updating ChannelMonitor with latest holder commitment" ) ;
3645
+ assert!( !self . lockdown_from_offchain) ;
3646
+ if let Err ( e) = self . update_holder_commitment_data(
3647
+ commitment_txs. clone( ) , htlc_data. clone( ) , claimed_htlcs. clone( ) ,
3648
+ ) {
3649
+ log_error!( logger, "Failed updating latest holder commitment state: {}" , e) ;
3650
+ }
3651
+ } ,
3652
+ // Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitment`.
3585
3653
// For now we just add the code to handle the new updates.
3586
3654
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
3587
3655
ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => {
@@ -3664,6 +3732,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3664
3732
for update in updates. updates. iter( ) {
3665
3733
match update {
3666
3734
ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { .. }
3735
+ |ChannelMonitorUpdateStep :: LatestHolderCommitment { .. }
3667
3736
|ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { .. }
3668
3737
|ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTX { .. }
3669
3738
|ChannelMonitorUpdateStep :: ShutdownScript { .. }
0 commit comments