@@ -619,7 +619,7 @@ pub enum Balance {
619619/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
620620#[ derive( PartialEq ) ]
621621struct IrrevocablyResolvedHTLC {
622- commitment_tx_output_idx : u32 ,
622+ commitment_tx_output_idx : Option < u32 > ,
623623 /// The txid of the transaction which resolved the HTLC, this may be a commitment (if the HTLC
624624 /// was not present in the confirmed commitment transaction), HTLC-Success, or HTLC-Timeout
625625 /// transaction.
@@ -628,11 +628,39 @@ struct IrrevocablyResolvedHTLC {
628628 payment_preimage : Option < PaymentPreimage > ,
629629}
630630
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+ }
636664
637665/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
638666/// on-chain transactions to ensure no loss of funds occurs.
@@ -1485,7 +1513,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
14851513 }
14861514 }
14871515 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) {
14891517 debug_assert ! ( htlc_spend_txid_opt. is_none( ) ) ;
14901518 htlc_spend_txid_opt = v. resolving_txid ;
14911519 true
@@ -1775,7 +1803,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
17751803 macro_rules! walk_htlcs {
17761804 ( $holder_commitment: expr, $htlc_iter: expr) => {
17771805 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) {
17791807 // We should assert that funding_spend_confirmed is_some() here, but we
17801808 // have some unit tests which violate HTLC transaction CSVs entirely and
17811809 // would fail.
@@ -2902,12 +2930,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
29022930 source : source. clone ( ) ,
29032931 htlc_value_satoshis,
29042932 } ) ) ;
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+ } ) ;
29112937 } ,
29122938 OnchainEvent :: MaturingOutput { descriptor } => {
29132939 log_debug ! ( logger, "Descriptor {} has got enough confirmations to be passed upstream" , log_spendable!( descriptor) ) ;
@@ -2917,7 +2943,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
29172943 } ,
29182944 OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
29192945 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 ) ,
29212947 payment_preimage : preimage,
29222948 } ) ;
29232949 } ,
0 commit comments