@@ -2599,14 +2599,21 @@ impl ChainListener for ChannelManager {
2599
2599
}
2600
2600
{
2601
2601
let mut channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ;
2602
- for ( preimage , hash ) in hash_to_remove {
2603
- if let Some ( preimage) = preimage {
2602
+ for ( payment_preimage , payment_hash ) in hash_to_remove {
2603
+ if let Some ( preimage) = payment_preimage {
2604
2604
if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2605
- if let Some ( mut sources ) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & hash ) {
2606
- for source in sources . drain ( ..) {
2605
+ if let Some ( mut entry ) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash ) {
2606
+ for source in entry . drain ( ..) {
2607
2607
self . claim_funds_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , preimage) ;
2608
2608
}
2609
2609
}
2610
+ } else {
2611
+ if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2612
+ if let Some ( mut entry) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash) {
2613
+ for source in entry. drain ( ..) {
2614
+ self . fail_htlc_backwards_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , & payment_hash, HTLCFailReason :: Reason { failure_code : 0x1000 | 14 , data : Vec :: new ( ) } ) ;
2615
+ }
2616
+ }
2610
2617
}
2611
2618
}
2612
2619
}
@@ -6099,6 +6106,117 @@ mod tests {
6099
6106
}
6100
6107
}
6101
6108
6109
+ #[ test]
6110
+ fn test_htlc_on_chain_timeout ( ) {
6111
+ // Test that in case of an unilateral close onchain, we detect the state of output thanks to
6112
+ // ChainWatchInterface and timeout the HTLC bacward accordingly. So here we test that ChannelManager is
6113
+ // broadcasting the right event to other nodes in payment path.
6114
+ // A ------------------> B ----------------------> C (timeout)
6115
+ // A's commitment tx C's commitment tx
6116
+ // \ \
6117
+ // B's HTLC timeout tx B's timeout tx
6118
+
6119
+ let nodes = create_network ( 3 ) ;
6120
+
6121
+ // Create some intial channels
6122
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
6123
+ let chan_2 = create_announced_chan_between_nodes ( & nodes, 1 , 2 ) ;
6124
+
6125
+ // Rebalance the network a bit by relaying one payment thorugh all the channels...
6126
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
6127
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
6128
+
6129
+ let ( _payment_preimage, payment_hash) = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) , 3000000 ) ;
6130
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6131
+
6132
+ // Brodacast legit commitment tx from C on B's chain
6133
+ let commitment_tx = nodes[ 2 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_2. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6134
+ nodes[ 2 ] . node . fail_htlc_backwards ( & payment_hash, PaymentFailReason :: PreimageUnknown ) ;
6135
+ {
6136
+ let mut added_monitors = nodes[ 2 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
6137
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
6138
+ added_monitors. clear ( ) ;
6139
+ }
6140
+ let events = nodes[ 2 ] . node . get_and_clear_pending_msg_events ( ) ;
6141
+ assert_eq ! ( events. len( ) , 1 ) ;
6142
+ match events[ 0 ] {
6143
+ MessageSendEvent :: UpdateHTLCs { ref node_id, updates : msgs:: CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => {
6144
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
6145
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
6146
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
6147
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
6148
+ assert_eq ! ( nodes[ 1 ] . node. get_our_node_id( ) , * node_id) ;
6149
+ } ,
6150
+ _ => panic ! ( "Unexpected event" ) ,
6151
+ } ;
6152
+ nodes[ 2 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
6153
+ let events = nodes[ 2 ] . node . get_and_clear_pending_msg_events ( ) ;
6154
+ assert_eq ! ( events. len( ) , 1 ) ;
6155
+ match events[ 0 ] {
6156
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6157
+ _ => panic ! ( "Unexpected event" ) ,
6158
+ }
6159
+ let mut funding_tx_map = HashMap :: new ( ) ;
6160
+ funding_tx_map. insert ( chan_2. 3 . txid ( ) , chan_2. 3 . clone ( ) ) ;
6161
+ commitment_tx[ 0 ] . verify ( & funding_tx_map) . unwrap ( ) ;
6162
+
6163
+ // Broadcast timeout transaction by B on received output fron C's commitment tx on B's chain
6164
+ // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence
6165
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 200 ) ;
6166
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
6167
+ assert_eq ! ( node_txn. len( ) , 8 ) ; // ChannelManager : 2 (commitment tx, HTLC-Timeout), ChannelMonitor : 6 (commitment tx, HTLC-Timeout, timeout tx) * 2 (block-rescan)
6168
+ assert_eq ! ( node_txn[ 2 ] . input[ 0 ] . previous_output. txid, node_txn[ 1 ] . txid( ) ) ;
6169
+ assert_eq ! ( node_txn[ 2 ] . clone( ) . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 133 ) ;
6170
+
6171
+ let mut commitment_tx_map = HashMap :: new ( ) ;
6172
+ commitment_tx_map. insert ( commitment_tx[ 0 ] . txid ( ) , commitment_tx[ 0 ] . clone ( ) ) ;
6173
+ node_txn[ 0 ] . verify ( & commitment_tx_map) . unwrap ( ) ;
6174
+
6175
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ node_txn[ 0 ] . clone( ) ] } , 1 ) ;
6176
+ {
6177
+ let mut added_monitors = nodes[ 1 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
6178
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
6179
+ added_monitors. clear ( ) ;
6180
+ }
6181
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6182
+ assert_eq ! ( events. len( ) , 2 ) ;
6183
+ match events[ 0 ] {
6184
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6185
+ _ => panic ! ( "Unexpected event" ) ,
6186
+ }
6187
+ match events[ 1 ] {
6188
+ MessageSendEvent :: UpdateHTLCs { ref node_id, updates : msgs:: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
6189
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
6190
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
6191
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
6192
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
6193
+ assert_eq ! ( nodes[ 0 ] . node. get_our_node_id( ) , * node_id) ;
6194
+ } ,
6195
+ _ => panic ! ( "Unexpected event" ) ,
6196
+ } ;
6197
+
6198
+ // Broadcast legit commitment tx from A on B's chain
6199
+ // Broadcast HTLC Timeout tx by B on offered output from A commitment tx on A's chain
6200
+ let commitment_tx = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6201
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
6202
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6203
+ assert_eq ! ( events. len( ) , 1 ) ;
6204
+ match events[ 0 ] {
6205
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6206
+ _ => panic ! ( "Unexpected event" ) ,
6207
+ }
6208
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
6209
+
6210
+ // Verify that A's ChannelManager is able to detect that HTLC is timeout by a HTLC Timeout tx and react backward in consequence
6211
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : node_txn } , 1 ) ;
6212
+ let events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6213
+ assert_eq ! ( events. len( ) , 1 ) ;
6214
+ match events[ 0 ] {
6215
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6216
+ _ => panic ! ( "Unexpected event" ) ,
6217
+ }
6218
+ }
6219
+
6102
6220
#[ test]
6103
6221
fn test_htlc_ignore_latest_remote_commitment ( ) {
6104
6222
// Test that HTLC transactions spending the latest remote commitment transaction are simply
0 commit comments