@@ -623,7 +623,6 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
623
623
624
624
#[ derive( Clone , Debug , PartialEq , Eq ) ]
625
625
pub ( crate ) enum ChannelMonitorUpdateStep {
626
- // Update LatestHolderCommitmentTXInfo in channel.rs if adding new fields to this variant.
627
626
LatestHolderCommitmentTXInfo {
628
627
commitment_tx : HolderCommitmentTransaction ,
629
628
/// Note that LDK after 0.0.115 supports this only containing dust HTLCs (implying the
@@ -636,6 +635,11 @@ pub(crate) enum ChannelMonitorUpdateStep {
636
635
claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
637
636
nondust_htlc_sources : Vec < HTLCSource > ,
638
637
} ,
638
+ LatestHolderCommitment {
639
+ commitment_txs : Vec < HolderCommitmentTransaction > ,
640
+ htlc_data : CommitmentHTLCData ,
641
+ claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
642
+ } ,
639
643
LatestCounterpartyCommitmentTXInfo {
640
644
commitment_txid : Txid ,
641
645
htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > ,
@@ -683,6 +687,7 @@ impl ChannelMonitorUpdateStep {
683
687
fn variant_name ( & self ) -> & ' static str {
684
688
match self {
685
689
ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo" ,
690
+ ChannelMonitorUpdateStep :: LatestHolderCommitment { .. } => "LatestHolderCommitment" ,
686
691
ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo" ,
687
692
ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTX { .. } => "LatestCounterpartyCommitmentTX" ,
688
693
ChannelMonitorUpdateStep :: PaymentPreimage { .. } => "PaymentPreimage" ,
@@ -728,6 +733,11 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
728
733
( 0 , htlc_outputs, required_vec) ,
729
734
( 2 , commitment_tx, required) ,
730
735
} ,
736
+ ( 8 , LatestHolderCommitment ) => {
737
+ ( 1 , commitment_txs, required_vec) ,
738
+ ( 3 , htlc_data, required) ,
739
+ ( 5 , claimed_htlcs, required_vec) ,
740
+ } ,
731
741
( 10 , RenegotiatedFunding ) => {
732
742
( 1 , channel_parameters, ( required: ReadableArgs , None ) ) ,
733
743
( 3 , holder_commitment_tx, required) ,
@@ -988,12 +998,12 @@ where
988
998
}
989
999
}
990
1000
991
- #[ derive( Clone , PartialEq ) ]
992
- struct CommitmentHTLCData {
1001
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
1002
+ pub ( crate ) struct CommitmentHTLCData {
993
1003
// These must be sorted in increasing output index order to match the expected order of the
994
1004
// HTLCs in the `CommitmentTransaction`.
995
- nondust_htlc_sources : Vec < HTLCSource > ,
996
- dust_htlcs : Vec < ( HTLCOutputInCommitment , Option < HTLCSource > ) > ,
1005
+ pub nondust_htlc_sources : Vec < HTLCSource > ,
1006
+ pub dust_htlcs : Vec < ( HTLCOutputInCommitment , Option < HTLCSource > ) > ,
997
1007
}
998
1008
999
1009
impl CommitmentHTLCData {
@@ -1002,6 +1012,11 @@ impl CommitmentHTLCData {
1002
1012
}
1003
1013
}
1004
1014
1015
+ impl_writeable_tlv_based ! ( CommitmentHTLCData , {
1016
+ ( 1 , nondust_htlc_sources, required_vec) ,
1017
+ ( 3 , dust_htlcs, required_vec) ,
1018
+ } ) ;
1019
+
1005
1020
impl TryFrom < HolderSignedTx > for CommitmentHTLCData {
1006
1021
type Error = ( ) ;
1007
1022
#[ rustfmt:: skip]
@@ -3309,11 +3324,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3309
3324
/// Panics if set_on_holder_tx_csv has never been called.
3310
3325
#[ rustfmt:: skip]
3311
3326
fn provide_latest_holder_commitment_tx (
3312
- & mut self , mut holder_commitment_tx : HolderCommitmentTransaction ,
3313
- htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) > ,
3327
+ & mut self , holder_commitment_tx : HolderCommitmentTransaction ,
3328
+ htlc_outputs : & [ ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) ] ,
3314
3329
claimed_htlcs : & [ ( SentHTLCId , PaymentPreimage ) ] , mut nondust_htlc_sources : Vec < HTLCSource > ,
3315
- ) {
3316
- let dust_htlcs: Vec < _ > = if htlc_outputs. iter ( ) . any ( |( _, s, _) | s. is_some ( ) ) {
3330
+ ) -> Result < ( ) , & ' static str > {
3331
+ let dust_htlcs = if htlc_outputs. iter ( ) . any ( |( _, s, _) | s. is_some ( ) ) {
3317
3332
// If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the
3318
3333
// `holder_commitment_tx`. In the future, we'll no longer provide the redundant data
3319
3334
// and just pass in source data via `nondust_htlc_sources`.
@@ -3329,19 +3344,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3329
3344
// Backfill the non-dust HTLC sources.
3330
3345
debug_assert ! ( nondust_htlc_sources. is_empty( ) ) ;
3331
3346
nondust_htlc_sources. reserve_exact ( holder_commitment_tx. nondust_htlcs ( ) . len ( ) ) ;
3332
- let dust_htlcs = htlc_outputs. into_iter ( ) . filter_map ( |( htlc, _, source) | {
3347
+ htlc_outputs. iter ( ) . filter_map ( |( htlc, _, source) | {
3333
3348
// Filter our non-dust HTLCs, while at the same time pushing their sources into
3334
3349
// `nondust_htlc_sources`.
3335
3350
if htlc. transaction_output_index . is_none ( ) {
3336
- return Some ( ( htlc, source) ) ;
3351
+ return Some ( ( htlc. clone ( ) , source. clone ( ) ) ) ;
3337
3352
}
3338
3353
if htlc. offered {
3339
- nondust_htlc_sources. push ( source. expect ( "Outbound HTLCs should have a source" ) ) ;
3354
+ nondust_htlc_sources. push ( source. clone ( ) . expect ( "Outbound HTLCs should have a source" ) ) ;
3340
3355
}
3341
3356
None
3342
- } ) . collect ( ) ;
3343
-
3344
- dust_htlcs
3357
+ } ) . collect ( )
3345
3358
} else {
3346
3359
// If we don't have any non-dust HTLCs in htlc_outputs, assume they were all passed via
3347
3360
// `nondust_htlc_sources`, building up the final htlc_outputs by combining
@@ -3368,30 +3381,112 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3368
3381
assert ! ( sources. next( ) . is_none( ) , "All HTLC sources should have been exhausted" ) ;
3369
3382
3370
3383
// This only includes dust HTLCs as checked above.
3371
- htlc_outputs. into_iter ( ) . map ( |( htlc, _, source) | ( htlc, source) ) . collect ( )
3384
+ htlc_outputs. iter ( ) . map ( |( htlc, _, source) | ( htlc. clone ( ) , source. clone ( ) ) ) . collect ( )
3372
3385
} ;
3373
3386
3374
- self . current_holder_commitment_number = holder_commitment_tx. trust ( ) . commitment_number ( ) ;
3375
- self . onchain_tx_handler . provide_latest_holder_tx ( holder_commitment_tx. clone ( ) ) ;
3387
+ let htlc_data = CommitmentHTLCData { nondust_htlc_sources, dust_htlcs } ;
3388
+ self . update_holder_commitment_data (
3389
+ vec ! [ holder_commitment_tx] , htlc_data, claimed_htlcs. to_vec ( ) ,
3390
+ )
3391
+ }
3392
+
3393
+ fn verify_matching_commitment_transactions <
3394
+ ' a ,
3395
+ I : Iterator < Item = & ' a CommitmentTransaction > + Clone ,
3396
+ > (
3397
+ & self , commitment_txs : I ,
3398
+ ) -> Result < ( ) , & ' static str > {
3399
+ if self . pending_funding . len ( ) + 1 != commitment_txs. clone ( ) . count ( ) {
3400
+ return Err ( "Commitment transaction count mismatch" ) ;
3401
+ }
3402
+
3403
+ let mut other_commitment_tx = None :: < & CommitmentTransaction > ;
3404
+ for ( funding, commitment_tx) in
3405
+ core:: iter:: once ( & self . funding ) . chain ( self . pending_funding . iter ( ) ) . zip ( commitment_txs)
3406
+ {
3407
+ let trusted_tx = & commitment_tx. trust ( ) . built_transaction ( ) . transaction ;
3408
+ if trusted_tx. input . len ( ) != 1 {
3409
+ return Err ( "Commitment transactions must only spend one input" ) ;
3410
+ }
3411
+ let funding_outpoint_spent = trusted_tx. input [ 0 ] . previous_output ;
3412
+ if funding_outpoint_spent != funding. funding_outpoint ( ) . into_bitcoin_outpoint ( ) {
3413
+ return Err ( "Commitment transaction spends invalid funding outpoint" ) ;
3414
+ }
3415
+
3416
+ if let Some ( other_commitment_tx) = other_commitment_tx {
3417
+ if commitment_tx. commitment_number ( ) != other_commitment_tx. commitment_number ( ) {
3418
+ return Err ( "Commitment number mismatch" ) ;
3419
+ }
3420
+ if commitment_tx. per_commitment_point ( )
3421
+ != other_commitment_tx. per_commitment_point ( )
3422
+ {
3423
+ return Err ( "Per-commitment-point mismatch" ) ;
3424
+ }
3425
+ if commitment_tx. feerate_per_kw ( ) != other_commitment_tx. feerate_per_kw ( ) {
3426
+ return Err ( "Commitment fee rate mismatch" ) ;
3427
+ }
3428
+ let nondust_htlcs = commitment_tx. nondust_htlcs ( ) ;
3429
+ let other_nondust_htlcs = other_commitment_tx. nondust_htlcs ( ) ;
3430
+ if nondust_htlcs. len ( ) != other_nondust_htlcs. len ( ) {
3431
+ return Err ( "Non-dust HTLC count mismatch" ) ;
3432
+ }
3433
+ for ( nondust_htlc, other_nondust_htlc) in
3434
+ nondust_htlcs. iter ( ) . zip ( other_nondust_htlcs. iter ( ) )
3435
+ {
3436
+ if !nondust_htlc. is_data_equal ( other_nondust_htlc) {
3437
+ return Err ( "Non-dust HTLC mismatch" ) ;
3438
+ }
3439
+ }
3440
+ }
3441
+
3442
+ other_commitment_tx = Some ( commitment_tx) ;
3443
+ }
3444
+
3445
+ Ok ( ( ) )
3446
+ }
3447
+
3448
+ fn update_holder_commitment_data (
3449
+ & mut self , commitment_txs : Vec < HolderCommitmentTransaction > ,
3450
+ mut htlc_data : CommitmentHTLCData , claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
3451
+ ) -> Result < ( ) , & ' static str > {
3452
+ self . verify_matching_commitment_transactions (
3453
+ commitment_txs. iter ( ) . map ( |holder_commitment_tx| holder_commitment_tx. deref ( ) ) ,
3454
+ ) ?;
3376
3455
3377
- mem:: swap ( & mut holder_commitment_tx, & mut self . funding . current_holder_commitment_tx ) ;
3378
- self . funding . prev_holder_commitment_tx = Some ( holder_commitment_tx) ;
3379
- let mut holder_htlc_data = CommitmentHTLCData { nondust_htlc_sources, dust_htlcs } ;
3380
- mem:: swap ( & mut holder_htlc_data, & mut self . current_holder_htlc_data ) ;
3381
- self . prev_holder_htlc_data = Some ( holder_htlc_data) ;
3456
+ let current_funding_commitment_tx = commitment_txs. first ( ) . unwrap ( ) ;
3457
+ self . current_holder_commitment_number = current_funding_commitment_tx. commitment_number ( ) ;
3458
+ self . onchain_tx_handler . provide_latest_holder_tx ( current_funding_commitment_tx. clone ( ) ) ;
3459
+ for ( funding, mut commitment_tx) in core:: iter:: once ( & mut self . funding )
3460
+ . chain ( self . pending_funding . iter_mut ( ) )
3461
+ . zip ( commitment_txs. into_iter ( ) )
3462
+ {
3463
+ mem:: swap ( & mut commitment_tx, & mut funding. current_holder_commitment_tx ) ;
3464
+ funding. prev_holder_commitment_tx = Some ( commitment_tx) ;
3465
+ }
3466
+
3467
+ mem:: swap ( & mut htlc_data, & mut self . current_holder_htlc_data ) ;
3468
+ self . prev_holder_htlc_data = Some ( htlc_data) ;
3382
3469
3383
3470
for ( claimed_htlc_id, claimed_preimage) in claimed_htlcs {
3384
- #[ cfg( debug_assertions) ] {
3385
- let cur_counterparty_htlcs = self . funding . counterparty_claimable_outpoints . get (
3386
- & self . funding . current_counterparty_commitment_txid . unwrap ( ) ) . unwrap ( ) ;
3471
+ #[ cfg( debug_assertions) ]
3472
+ {
3473
+ let cur_counterparty_htlcs = self
3474
+ . funding
3475
+ . counterparty_claimable_outpoints
3476
+ . get ( & self . funding . current_counterparty_commitment_txid . unwrap ( ) )
3477
+ . unwrap ( ) ;
3387
3478
assert ! ( cur_counterparty_htlcs. iter( ) . any( |( _, source_opt) | {
3388
3479
if let Some ( source) = source_opt {
3389
- SentHTLCId :: from_source( source) == * claimed_htlc_id
3390
- } else { false }
3480
+ SentHTLCId :: from_source( source) == claimed_htlc_id
3481
+ } else {
3482
+ false
3483
+ }
3391
3484
} ) ) ;
3392
3485
}
3393
- self . counterparty_fulfilled_htlcs . insert ( * claimed_htlc_id, * claimed_preimage) ;
3486
+ self . counterparty_fulfilled_htlcs . insert ( claimed_htlc_id, claimed_preimage) ;
3394
3487
}
3488
+
3489
+ Ok ( ( ) )
3395
3490
}
3396
3491
3397
3492
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
@@ -3734,9 +3829,27 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3734
3829
ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => {
3735
3830
log_trace ! ( logger, "Updating ChannelMonitor with latest holder commitment transaction info" ) ;
3736
3831
if self . lockdown_from_offchain { panic ! ( ) ; }
3737
- self . provide_latest_holder_commitment_tx ( commitment_tx. clone ( ) , htlc_outputs. clone ( ) , & claimed_htlcs, nondust_htlc_sources. clone ( ) ) ;
3832
+ if let Err ( e) = self . provide_latest_holder_commitment_tx (
3833
+ commitment_tx. clone ( ) , htlc_outputs, & claimed_htlcs,
3834
+ nondust_htlc_sources. clone ( )
3835
+ ) {
3836
+ log_error ! ( logger, "Failed updating latest holder commitment transaction info: {}" , e) ;
3837
+ ret = Err ( ( ) ) ;
3838
+ }
3738
3839
}
3739
- // Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitmentTX`.
3840
+ ChannelMonitorUpdateStep :: LatestHolderCommitment {
3841
+ commitment_txs, htlc_data, claimed_htlcs,
3842
+ } => {
3843
+ log_trace ! ( logger, "Updating ChannelMonitor with latest holder commitment" ) ;
3844
+ assert ! ( !self . lockdown_from_offchain) ;
3845
+ if let Err ( e) = self . update_holder_commitment_data (
3846
+ commitment_txs. clone ( ) , htlc_data. clone ( ) , claimed_htlcs. clone ( ) ,
3847
+ ) {
3848
+ log_error ! ( logger, "Failed updating latest holder commitment state: {}" , e) ;
3849
+ ret = Err ( ( ) ) ;
3850
+ }
3851
+ } ,
3852
+ // Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitment`.
3740
3853
// For now we just add the code to handle the new updates.
3741
3854
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
3742
3855
ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => {
@@ -3819,6 +3932,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
3819
3932
for update in updates. updates . iter ( ) {
3820
3933
match update {
3821
3934
ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { .. }
3935
+ |ChannelMonitorUpdateStep :: LatestHolderCommitment { .. }
3822
3936
|ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { .. }
3823
3937
|ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTX { .. }
3824
3938
|ChannelMonitorUpdateStep :: ShutdownScript { .. }
0 commit comments