@@ -2005,13 +2005,17 @@ impl ChainListener for ChannelManager {
2005
2005
for ( arr, vec) in payment_preimage. iter_mut ( ) . zip ( tx. input [ 0 ] . witness [ 3 ] . iter ( ) ) {
2006
2006
* arr = * vec;
2007
2007
}
2008
- hash_to_remove. push ( ( payment_preimage, htlc_with_hash. clone ( ) ) ) ;
2008
+ hash_to_remove. push ( ( Some ( payment_preimage) , htlc_with_hash. clone ( ) ) ) ;
2009
2009
} else if tx. input . len ( ) > 0 && tx. input [ 0 ] . witness . len ( ) == 3 && tx. input [ 0 ] . witness [ 2 ] . len ( ) == 133 && payment_hash160 == tx. input [ 0 ] . witness [ 2 ] [ 109 ..129 ] {
2010
2010
let mut payment_preimage = [ 0 ; 32 ] ;
2011
2011
for ( arr, vec) in payment_preimage. iter_mut ( ) . zip ( tx. input [ 0 ] . witness [ 1 ] . iter ( ) ) {
2012
2012
* arr = * vec;
2013
2013
}
2014
- hash_to_remove. push ( ( payment_preimage, htlc_with_hash. clone ( ) ) ) ;
2014
+ hash_to_remove. push ( ( Some ( payment_preimage) , htlc_with_hash. clone ( ) ) ) ;
2015
+ } else if tx. input . len ( ) > 0 && tx. input [ 0 ] . witness . len ( ) == 5 && tx. input [ 0 ] . witness [ 4 ] . len ( ) == 133 && payment_hash160 == tx. input [ 0 ] . witness [ 4 ] [ 109 ..129 ] {
2016
+ hash_to_remove. push ( ( None , htlc_with_hash. clone ( ) ) ) ;
2017
+ } else if tx. input . len ( ) > 0 && tx. input [ 0 ] . witness . len ( ) == 3 && tx. input [ 0 ] . witness [ 2 ] . len ( ) == 138 && payment_hash160 == tx. input [ 0 ] . witness [ 2 ] [ 69 ..89 ] {
2018
+ hash_to_remove. push ( ( None , htlc_with_hash. clone ( ) ) ) ;
2015
2019
}
2016
2020
}
2017
2021
}
@@ -2022,11 +2026,20 @@ impl ChainListener for ChannelManager {
2022
2026
2023
2027
{
2024
2028
let mut channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ;
2025
- for ( preimage, hash) in hash_to_remove {
2026
- if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2027
- if let Some ( mut entry) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove_entry ( & hash) {
2028
- for source in entry. 1 . drain ( ..) {
2029
- self . claim_funds_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , preimage) ;
2029
+ for ( payment_preimage, payment_hash) in hash_to_remove {
2030
+ if let Some ( preimage) = payment_preimage {
2031
+ if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2032
+ if let Some ( mut entry) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash) {
2033
+ for source in entry. drain ( ..) {
2034
+ self . claim_funds_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , preimage) ;
2035
+ }
2036
+ }
2037
+ } else {
2038
+ if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2039
+ if let Some ( mut entry) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash) {
2040
+ for source in entry. drain ( ..) {
2041
+ self . fail_htlc_backwards_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , & payment_hash, HTLCFailReason :: Reason { failure_code : 0x1000 | 14 , data : Vec :: new ( ) } ) ;
2042
+ }
2030
2043
}
2031
2044
}
2032
2045
}
@@ -3569,6 +3582,102 @@ mod tests {
3569
3582
}
3570
3583
}
3571
3584
3585
+ #[ test]
3586
+ fn test_htlc_on_chain_timeout ( ) {
3587
+ // Test that in case of an unilateral close onchain, we detect the state of output thanks to
3588
+ // ChainWatchInterface and timeout the HTLC bacward accordingly. So here we test that ChannelManager is
3589
+ // broadcasting the right event to other nodes in payment path.
3590
+ // A ------------------> B ----------------------> C (timeout)
3591
+ // A's commitment tx C's commitment tx
3592
+ // \ \
3593
+ // B's HTLC timeout tx B's timeout tx
3594
+
3595
+ let nodes = create_network ( 3 ) ;
3596
+
3597
+ // Create some intial channels
3598
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
3599
+ let chan_2 = create_announced_chan_between_nodes ( & nodes, 1 , 2 ) ;
3600
+
3601
+ // Rebalance the network a bit by relaying one payment thorugh all the channels...
3602
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
3603
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
3604
+
3605
+ let ( payment_preimage, payment_hash) = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) , 3000000 ) ;
3606
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
3607
+
3608
+ // Brodacast legit commitment tx from C on B's chain
3609
+ let commitment_tx = nodes[ 2 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_2. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
3610
+ nodes[ 2 ] . node . fail_htlc_backwards ( & payment_hash) ;
3611
+ {
3612
+ let mut added_monitors = nodes[ 2 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
3613
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
3614
+ added_monitors. clear ( ) ;
3615
+ }
3616
+ let events = nodes[ 2 ] . node . get_and_clear_pending_events ( ) ;
3617
+ assert_eq ! ( events. len( ) , 1 ) ;
3618
+ match events[ 0 ] {
3619
+ Event :: UpdateHTLCs { ref node_id, updates : msgs:: CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => {
3620
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
3621
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
3622
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
3623
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
3624
+ assert_eq ! ( nodes[ 1 ] . node. get_our_node_id( ) , * node_id) ;
3625
+ } ,
3626
+ _ => panic ! ( "Unexpected event" ) ,
3627
+ } ;
3628
+ nodes[ 2 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
3629
+ let events = nodes[ 2 ] . node . get_and_clear_pending_events ( ) ;
3630
+ assert_eq ! ( events. len( ) , 1 ) ;
3631
+ match events[ 0 ] {
3632
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
3633
+ _ => panic ! ( "Unexpected event" ) ,
3634
+ }
3635
+ let node_txn = nodes[ 2 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
3636
+
3637
+ // Broadcast timeout transaction by B on received output fron C's commitment tx on B's chain
3638
+ // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence
3639
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : node_txn} , 200 ) ;
3640
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ; //TODO: shouldn't be a HTLC-Timeout but actually that's one... => implement lacking parts in check_spend_remote_transaction
3641
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : node_txn} , 1 ) ;
3642
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
3643
+ assert_eq ! ( events. len( ) , 2 ) ;
3644
+ match events[ 0 ] {
3645
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
3646
+ _ => panic ! ( "Unexpected event" ) ,
3647
+ }
3648
+ match events[ 1 ] {
3649
+ Event :: UpdateHTLCs { ref node_id, updates : msgs:: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
3650
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
3651
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
3652
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
3653
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
3654
+ assert_eq ! ( nodes[ 0 ] . node. get_our_node_id( ) , * node_id) ;
3655
+ } ,
3656
+ _ => panic ! ( "Unexpected event" ) ,
3657
+ } ;
3658
+
3659
+ // Broadcast legit commitment tx from A on B's chain
3660
+ // Broadcast HTLC Timeout tx by B on offered output from A commitment tx on A's chain
3661
+ let commitment_tx = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
3662
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
3663
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
3664
+ assert_eq ! ( events. len( ) , 1 ) ;
3665
+ match events[ 0 ] {
3666
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
3667
+ _ => panic ! ( "Unexpected event" ) ,
3668
+ }
3669
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
3670
+
3671
+ // Verify that A's ChannelManager is able to detect that HTLC is timeout by a HTLC Timeout tx and react backward in consequence
3672
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : node_txn } , 1 ) ;
3673
+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
3674
+ assert_eq ! ( events. len( ) , 1 ) ;
3675
+ match events[ 0 ] {
3676
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
3677
+ _ => panic ! ( "Unexpected event" ) ,
3678
+ }
3679
+ }
3680
+
3572
3681
fn test_htlc_ignore_latest_remote_commitment ( ) {
3573
3682
// Test that HTLC transactions spending the latest remote commitment transaction are simply
3574
3683
// ignored if we cannot claim them. This originally tickled an invalid unwrap().
0 commit comments