@@ -619,7 +619,7 @@ pub enum Balance {
619
619
/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
620
620
#[ derive( PartialEq ) ]
621
621
struct IrrevocablyResolvedHTLC {
622
- commitment_tx_output_idx : u32 ,
622
+ commitment_tx_output_idx : Option < u32 > ,
623
623
/// The txid of the transaction which resolved the HTLC, this may be a commitment (if the HTLC
624
624
/// was not present in the confirmed commitment transaction), HTLC-Success, or HTLC-Timeout
625
625
/// transaction.
@@ -628,11 +628,39 @@ struct IrrevocablyResolvedHTLC {
628
628
payment_preimage : Option < PaymentPreimage > ,
629
629
}
630
630
631
- impl_writeable_tlv_based ! ( IrrevocablyResolvedHTLC , {
632
- ( 0 , commitment_tx_output_idx, required) ,
633
- ( 1 , resolving_txid, option) ,
634
- ( 2 , payment_preimage, option) ,
635
- } ) ;
631
+ // In LDK versions prior to 0.0.111 commitment_tx_output_idx was not Option-al and
632
+ // IrrevocablyResolvedHTLC objects only existed for non-dust HTLCs. This was a bug, but to maintain
633
+ // backwards compatibility we must ensure we always write out a commitment_tx_output_idx field,
634
+ // using `u32::max_value()` as a sentinal to indicate the HTLC was dust.
635
+ impl Writeable for IrrevocablyResolvedHTLC {
636
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
637
+ let mapped_commitment_tx_output_idx = self . commitment_tx_output_idx . unwrap_or ( u32:: max_value ( ) ) ;
638
+ write_tlv_fields ! ( writer, {
639
+ ( 0 , mapped_commitment_tx_output_idx, required) ,
640
+ ( 1 , self . resolving_txid, option) ,
641
+ ( 2 , self . payment_preimage, option) ,
642
+ } ) ;
643
+ Ok ( ( ) )
644
+ }
645
+ }
646
+
647
+ impl Readable for IrrevocablyResolvedHTLC {
648
+ fn read < R : io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
649
+ let mut mapped_commitment_tx_output_idx = 0 ;
650
+ let mut resolving_txid = None ;
651
+ let mut payment_preimage = None ;
652
+ read_tlv_fields ! ( reader, {
653
+ ( 0 , mapped_commitment_tx_output_idx, required) ,
654
+ ( 1 , resolving_txid, option) ,
655
+ ( 2 , payment_preimage, option) ,
656
+ } ) ;
657
+ Ok ( Self {
658
+ commitment_tx_output_idx : if mapped_commitment_tx_output_idx == u32:: max_value ( ) { None } else { Some ( mapped_commitment_tx_output_idx) } ,
659
+ resolving_txid,
660
+ payment_preimage,
661
+ } )
662
+ }
663
+ }
636
664
637
665
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
638
666
/// on-chain transactions to ensure no loss of funds occurs.
@@ -1485,7 +1513,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1485
1513
}
1486
1514
}
1487
1515
let htlc_resolved = self . htlcs_resolved_on_chain . iter ( )
1488
- . find ( |v| if v. commitment_tx_output_idx == htlc_commitment_tx_output_idx {
1516
+ . find ( |v| if v. commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) {
1489
1517
debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
1490
1518
htlc_spend_txid_opt = v. resolving_txid ;
1491
1519
true
@@ -1775,7 +1803,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1775
1803
macro_rules! walk_htlcs {
1776
1804
( $holder_commitment: expr, $htlc_iter: expr) => {
1777
1805
for ( htlc, source) in $htlc_iter {
1778
- if us. htlcs_resolved_on_chain. iter( ) . any( |v| Some ( v. commitment_tx_output_idx) == htlc. transaction_output_index) {
1806
+ if us. htlcs_resolved_on_chain. iter( ) . any( |v| v. commitment_tx_output_idx == htlc. transaction_output_index) {
1779
1807
// We should assert that funding_spend_confirmed is_some() here, but we
1780
1808
// have some unit tests which violate HTLC transaction CSVs entirely and
1781
1809
// would fail.
@@ -2902,12 +2930,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2902
2930
source : source. clone ( ) ,
2903
2931
htlc_value_satoshis,
2904
2932
} ) ) ;
2905
- if let Some ( idx) = commitment_tx_output_idx {
2906
- self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC {
2907
- commitment_tx_output_idx : idx, resolving_txid : Some ( entry. txid ) ,
2908
- payment_preimage : None ,
2909
- } ) ;
2910
- }
2933
+ self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC {
2934
+ commitment_tx_output_idx, resolving_txid : Some ( entry. txid ) ,
2935
+ payment_preimage : None ,
2936
+ } ) ;
2911
2937
} ,
2912
2938
OnchainEvent :: MaturingOutput { descriptor } => {
2913
2939
log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
@@ -2917,7 +2943,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2917
2943
} ,
2918
2944
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
2919
2945
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC {
2920
- commitment_tx_output_idx, resolving_txid : Some ( entry. txid ) ,
2946
+ commitment_tx_output_idx : Some ( commitment_tx_output_idx ) , resolving_txid : Some ( entry. txid ) ,
2921
2947
payment_preimage : preimage,
2922
2948
} ) ;
2923
2949
} ,
0 commit comments