@@ -1515,6 +1515,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1515
1515
let htlc_commitment_tx_output_idx =
1516
1516
if let Some ( v) = htlc. transaction_output_index { v } else { return None ; } ;
1517
1517
1518
+ let mut htlc_spend_txid_opt = None ;
1518
1519
let mut htlc_spend_tx_opt = None ;
1519
1520
let mut holder_timeout_spend_pending = None ;
1520
1521
let mut htlc_spend_pending = None ;
@@ -1523,16 +1524,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1523
1524
match event. event {
1524
1525
OnchainEvent :: HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. }
1525
1526
if commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) => {
1527
+ htlc_spend_txid_opt = Some ( & event. txid ) ;
1526
1528
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 ( ) ;
1528
1530
debug_assert ! ( holder_timeout_spend_pending. is_none( ) ) ;
1529
1531
debug_assert_eq ! ( htlc_value_satoshis. unwrap( ) , htlc. amount_msat / 1000 ) ;
1530
1532
holder_timeout_spend_pending = Some ( event. confirmation_threshold ( ) ) ;
1531
1533
} ,
1532
1534
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. }
1533
1535
if commitment_tx_output_idx == htlc_commitment_tx_output_idx => {
1536
+ htlc_spend_txid_opt = Some ( & event. txid ) ;
1534
1537
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 ( ) ;
1536
1539
debug_assert ! ( htlc_spend_pending. is_none( ) ) ;
1537
1540
htlc_spend_pending = Some ( ( event. confirmation_threshold ( ) , preimage. is_some ( ) ) ) ;
1538
1541
} ,
@@ -1547,20 +1550,23 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1547
1550
}
1548
1551
let htlc_resolved = self . htlcs_resolved_on_chain . iter ( )
1549
1552
. find ( |v| if v. commitment_tx_output_idx == Some ( htlc_commitment_tx_output_idx) {
1553
+ htlc_spend_txid_opt = v. resolving_txid . as_ref ( ) ;
1550
1554
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 ( ) ;
1552
1556
true
1553
1557
} else { false } ) ;
1554
1558
debug_assert ! ( holder_timeout_spend_pending. is_some( ) as u8 + htlc_spend_pending. is_some( ) as u8 + htlc_resolved. is_some( ) as u8 <= 1 ) ;
1555
1559
1556
1560
let htlc_commitment_outpoint = BitcoinOutPoint :: new ( confirmed_txid. unwrap ( ) , htlc_commitment_tx_output_idx) ;
1557
1561
let htlc_output_to_spend =
1558
1562
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 ( )
1560
1566
. 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 ) )
1564
1570
} else {
1565
1571
htlc_commitment_outpoint
1566
1572
} ;
@@ -1585,9 +1591,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1585
1591
descriptor : SpendableOutputDescriptor :: StaticOutput { .. }
1586
1592
} = & event. event {
1587
1593
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
1591
1596
} else {
1592
1597
Some ( inp. previous_output . txid ) == confirmed_txid &&
1593
1598
inp. previous_output . vout == htlc_commitment_tx_output_idx
0 commit comments