@@ -1515,6 +1515,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15151515 let htlc_commitment_tx_output_idx =
15161516 if let Some ( v) = htlc. transaction_output_index { v } else { return None ; } ;
15171517
1518+ let mut htlc_spend_txid_opt = None ;
15181519 let mut htlc_spend_tx_opt = None ;
15191520 let mut holder_timeout_spend_pending = None ;
15201521 let mut htlc_spend_pending = None ;
@@ -1523,16 +1524,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15231524 match event. event {
15241525 OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
15251526 if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1527+ htlc_spend_txid_opt = Some ( & event. txid ) ;
15261528 debug_assert ! ( htlc_spend_tx_opt. is_none( ) ) ;
1527- htlc_spend_tx_opt = event. transaction . clone ( ) ;
1529+ htlc_spend_tx_opt = event. transaction . as_ref ( ) ;
15281530 debug_assert ! ( holder_timeout_spend_pending. is_none( ) ) ;
15291531 debug_assert_eq ! ( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
15301532 holder_timeout_spend_pending = Some ( event. confirmation_threshold ( ) ) ;
15311533 } ,
15321534 OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
15331535 if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1536+ htlc_spend_txid_opt = Some ( & event. txid ) ;
15341537 debug_assert ! ( htlc_spend_tx_opt. is_none( ) ) ;
1535- htlc_spend_tx_opt = event. transaction . clone ( ) ;
1538+ htlc_spend_tx_opt = event. transaction . as_ref ( ) ;
15361539 debug_assert ! ( htlc_spend_pending. is_none( ) ) ;
15371540 htlc_spend_pending = Some ( ( event. confirmation_threshold ( ) , preimage. is_some ( ) ) ) ;
15381541 } ,
@@ -1547,20 +1550,23 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15471550 }
15481551 let htlc_resolved = self . htlcs_resolved_on_chain . iter ( )
15491552 . find ( |v| if v. commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) {
1553+ htlc_spend_txid_opt = v. resolving_txid . as_ref ( ) ;
15501554 debug_assert ! ( htlc_spend_tx_opt. is_none( ) ) ;
1551- htlc_spend_tx_opt = v. resolving_tx . clone ( ) ;
1555+ htlc_spend_tx_opt = v. resolving_tx . as_ref ( ) ;
15521556 true
15531557 } else { false } ) ;
15541558 debug_assert ! ( holder_timeout_spend_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
15551559
15561560 let htlc_commitment_outpoint = BitcoinOutPoint :: new ( confirmed_txid. unwrap ( ) , htlc_commitment_tx_output_idx) ;
15571561 let htlc_output_to_spend =
15581562 if let Some ( ref tx) = htlc_spend_tx_opt {
1559- let htlc_input_idx = tx. input . iter ( ) . enumerate ( )
1563+ // Because HTLCs are signed with SIGHASH_SINGLE, we can locate the correct output
1564+ // by ensuring its adjacent input spends the HTLC output in the commitment.
1565+ let htlc_input_idx_opt = tx. input . iter ( ) . enumerate ( )
15601566 . find ( |( _, input) | input. previous_output == htlc_commitment_outpoint)
1561- . map ( |( idx, _) | idx as u32 )
1562- . unwrap ( ) ;
1563- BitcoinOutPoint :: new ( tx . txid ( ) , htlc_input_idx )
1567+ . map ( |( idx, _) | idx as u32 ) ;
1568+ debug_assert ! ( htlc_input_idx_opt . is_some ( ) ) ;
1569+ BitcoinOutPoint :: new ( * htlc_spend_txid_opt . unwrap ( ) , htlc_input_idx_opt . unwrap_or ( 0 ) )
15641570 } else {
15651571 htlc_commitment_outpoint
15661572 } ;
@@ -1585,9 +1591,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15851591 descriptor : SpendableOutputDescriptor :: StaticOutput { .. }
15861592 } = & event. event {
15871593 if event. transaction . as_ref ( ) . map ( |tx| tx. input . iter ( ) . any ( |inp| {
1588- if let Some ( ref htlc_spend_tx) = htlc_spend_tx_opt {
1589- let htlc_spend_txid = htlc_spend_tx. txid ( ) ;
1590- tx. txid ( ) == htlc_spend_txid || inp. previous_output . txid == htlc_spend_txid
1594+ if let Some ( htlc_spend_txid) = htlc_spend_txid_opt {
1595+ tx. txid ( ) == * htlc_spend_txid || inp. previous_output . txid == * htlc_spend_txid
15911596 } else {
15921597 Some ( inp. previous_output . txid ) == confirmed_txid &&
15931598 inp. previous_output . vout == htlc_commitment_tx_output_idx
0 commit comments