@@ -1738,42 +1738,84 @@ impl ChannelMonitor {
1738
1738
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
1739
1739
/// revoked using data in local_claimable_outpoints.
1740
1740
/// Should not be used if check_spend_revoked_transaction succeeds.
1741
- fn check_spend_local_transaction ( & self , tx : & Transaction , _height : u32 ) -> ( Vec < Transaction > , Vec < SpendableOutputDescriptor > , ( Sha256dHash , Vec < TxOut > ) ) {
1741
+ fn check_spend_local_transaction ( & mut self , tx : & Transaction , height : u32 ) -> ( Vec < Transaction > , Vec < SpendableOutputDescriptor > , ( Sha256dHash , Vec < TxOut > ) ) {
1742
1742
let commitment_txid = tx. txid ( ) ;
1743
- // TODO: If we find a match here we need to fail back HTLCs that weren't included in the
1744
- // broadcast commitment transaction, either because they didn't meet dust or because they
1745
- // weren't yet included in our commitment transaction(s).
1743
+ let mut local_txn = Vec :: new ( ) ;
1744
+ let mut spendable_outputs = Vec :: new ( ) ;
1745
+ let mut watch_outputs = Vec :: new ( ) ;
1746
+
1747
+ macro_rules! wait_threshold_conf {
1748
+ ( $height: expr, $source: expr, $update: expr, $commitment_tx: expr, $payment_hash: expr) => {
1749
+ log_info!( self , "Failing HTLC with payment_hash {} from {} local commitment tx due to broadcast of transaction, waiting confirmation (at height{})" , log_bytes!( $payment_hash. 0 ) , $commitment_tx, height + HTLC_FAIL_ANTI_REORG_DELAY - 1 ) ;
1750
+ match self . htlc_updated_waiting_threshold_conf. entry( $height + HTLC_FAIL_ANTI_REORG_DELAY - 1 ) {
1751
+ hash_map:: Entry :: Occupied ( mut entry) => {
1752
+ let e = entry. get_mut( ) ;
1753
+ e. retain( |ref update| update. 0 != $source) ;
1754
+ e. push( ( $source, $update, $payment_hash) ) ;
1755
+ }
1756
+ hash_map:: Entry :: Vacant ( entry) => {
1757
+ entry. insert( vec![ ( $source, $update, $payment_hash) ] ) ;
1758
+ }
1759
+ }
1760
+ }
1761
+ }
1762
+
1763
+ macro_rules! append_onchain_update {
1764
+ ( $updates: expr) => {
1765
+ local_txn. append( & mut $updates. 0 ) ;
1766
+ spendable_outputs. append( & mut $updates. 1 ) ;
1767
+ watch_outputs. append( & mut $updates. 2 ) ;
1768
+ }
1769
+ }
1770
+
1771
+ // HTLCs set may differ between last and previous local commitment txn, in case of one hitting chain, ensure we cancel all of them backward
1772
+ let is_local_tx = if self . current_local_signed_commitment_tx . is_some ( ) || self . prev_local_signed_commitment_tx . is_some ( ) { true } else { false } ;
1773
+
1746
1774
if let & Some ( ref local_tx) = & self . current_local_signed_commitment_tx {
1775
+ if is_local_tx {
1776
+ for & ( ref htlc, _, ref source) in & local_tx. htlc_outputs {
1777
+ if htlc. transaction_output_index . is_none ( ) {
1778
+ if let & Some ( ref source) = source {
1779
+ wait_threshold_conf ! ( height, source. clone( ) , None , "lastest" , htlc. payment_hash. clone( ) ) ;
1780
+ }
1781
+ }
1782
+ }
1783
+ }
1747
1784
if local_tx. txid == commitment_txid {
1748
1785
log_trace ! ( self , "Got latest local commitment tx broadcast, searching for available HTLCs to claim" ) ;
1749
1786
match self . key_storage {
1750
1787
Storage :: Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
1751
- let ( local_txn, spendable_outputs, watch_outputs) = self . broadcast_by_local_state ( local_tx, latest_per_commitment_point, & Some ( * delayed_payment_base_key) ) ;
1752
- return ( local_txn, spendable_outputs, ( commitment_txid, watch_outputs) ) ;
1788
+ append_onchain_update ! ( self . broadcast_by_local_state( local_tx, latest_per_commitment_point, & Some ( * delayed_payment_base_key) ) ) ;
1753
1789
} ,
1754
1790
Storage :: Watchtower { .. } => {
1755
- let ( local_txn, spendable_outputs, watch_outputs) = self . broadcast_by_local_state ( local_tx, & None , & None ) ;
1756
- return ( local_txn, spendable_outputs, ( commitment_txid, watch_outputs) ) ;
1791
+ append_onchain_update ! ( self . broadcast_by_local_state( local_tx, & None , & None ) ) ;
1757
1792
}
1758
1793
}
1759
1794
}
1760
1795
}
1761
1796
if let & Some ( ref local_tx) = & self . prev_local_signed_commitment_tx {
1797
+ if is_local_tx {
1798
+ for & ( ref htlc, _, ref source) in & local_tx. htlc_outputs {
1799
+ if htlc. transaction_output_index . is_none ( ) {
1800
+ if let & Some ( ref source) = source {
1801
+ wait_threshold_conf ! ( height, source. clone( ) , None , "previous" , htlc. payment_hash. clone( ) ) ;
1802
+ }
1803
+ }
1804
+ }
1805
+ }
1762
1806
if local_tx. txid == commitment_txid {
1763
1807
log_trace ! ( self , "Got previous local commitment tx broadcast, searching for available HTLCs to claim" ) ;
1764
1808
match self . key_storage {
1765
1809
Storage :: Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
1766
- let ( local_txn, spendable_outputs, watch_outputs) = self . broadcast_by_local_state ( local_tx, prev_latest_per_commitment_point, & Some ( * delayed_payment_base_key) ) ;
1767
- return ( local_txn, spendable_outputs, ( commitment_txid, watch_outputs) ) ;
1810
+ append_onchain_update ! ( self . broadcast_by_local_state( local_tx, prev_latest_per_commitment_point, & Some ( * delayed_payment_base_key) ) ) ;
1768
1811
} ,
1769
1812
Storage :: Watchtower { .. } => {
1770
- let ( local_txn, spendable_outputs, watch_outputs) = self . broadcast_by_local_state ( local_tx, & None , & None ) ;
1771
- return ( local_txn, spendable_outputs, ( commitment_txid, watch_outputs) ) ;
1813
+ append_onchain_update ! ( self . broadcast_by_local_state( local_tx, & None , & None ) ) ;
1772
1814
}
1773
1815
}
1774
1816
}
1775
1817
}
1776
- ( Vec :: new ( ) , Vec :: new ( ) , ( commitment_txid, Vec :: new ( ) ) )
1818
+ ( local_txn , spendable_outputs , ( commitment_txid, watch_outputs ) )
1777
1819
}
1778
1820
1779
1821
/// Generate a spendable output event when closing_transaction get registered onchain.
0 commit comments