@@ -1520,7 +1520,8 @@ impl ChannelManager {
1520
1520
rejected_by_dest : !payment_retryable,
1521
1521
} ) ;
1522
1522
} else {
1523
- panic ! ( "should have onion error packet here" ) ;
1523
+ //TODO (ariard) which failure code to generate from unilateral/revoked channel closing event ? currently NODE|2 (temporary_node_failure)
1524
+ //panic!("should have onion error packet here");
1524
1525
}
1525
1526
} ,
1526
1527
HTLCSource :: PreviousHopData ( HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret } ) => {
@@ -2657,11 +2658,14 @@ impl ChainListener for ChannelManager {
2657
2658
}
2658
2659
{
2659
2660
let mut channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ;
2660
- for ( _ , payment_preimage, htlc_source) in self . monitor . fetch_pending_htlc_updated ( ) {
2661
+ for ( payment_hash , payment_preimage, htlc_source) in self . monitor . fetch_pending_htlc_updated ( ) {
2661
2662
if let Some ( source) = htlc_source {
2662
2663
if let Some ( preimage) = payment_preimage {
2663
2664
if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2664
2665
self . claim_funds_internal ( channel_state. take ( ) . unwrap ( ) , source, preimage) ;
2666
+ } else {
2667
+ if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2668
+ self . fail_htlc_backwards_internal ( channel_state. take ( ) . unwrap ( ) , source, & payment_hash, HTLCFailReason :: Reason { failure_code : 0x2000 | 2 , data : Vec :: new ( ) } ) ;
2665
2669
}
2666
2670
}
2667
2671
}
@@ -6168,6 +6172,117 @@ mod tests {
6168
6172
}
6169
6173
}
6170
6174
6175
+ #[ test]
6176
+ fn test_htlc_on_chain_timeout ( ) {
6177
+ // Test that in case of an unilateral close onchain, we detect the state of output thanks to
6178
+ // ChainWatchInterface and timeout the HTLC bacward accordingly. So here we test that ChannelManager is
6179
+ // broadcasting the right event to other nodes in payment path.
6180
+ // A ------------------> B ----------------------> C (timeout)
6181
+ // A's commitment tx C's commitment tx
6182
+ // \ \
6183
+ // B's HTLC timeout tx B's timeout tx
6184
+
6185
+ let nodes = create_network ( 3 ) ;
6186
+
6187
+ // Create some intial channels
6188
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
6189
+ let chan_2 = create_announced_chan_between_nodes ( & nodes, 1 , 2 ) ;
6190
+
6191
+ // Rebalance the network a bit by relaying one payment thorugh all the channels...
6192
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
6193
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
6194
+
6195
+ let ( _payment_preimage, payment_hash) = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) , 3000000 ) ;
6196
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
6197
+
6198
+ // Brodacast legit commitment tx from C on B's chain
6199
+ let commitment_tx = nodes[ 2 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_2. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6200
+ nodes[ 2 ] . node . fail_htlc_backwards ( & payment_hash, PaymentFailReason :: PreimageUnknown ) ;
6201
+ {
6202
+ let mut added_monitors = nodes[ 2 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
6203
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
6204
+ added_monitors. clear ( ) ;
6205
+ }
6206
+ let events = nodes[ 2 ] . node . get_and_clear_pending_msg_events ( ) ;
6207
+ assert_eq ! ( events. len( ) , 1 ) ;
6208
+ match events[ 0 ] {
6209
+ 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, .. } } => {
6210
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
6211
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
6212
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
6213
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
6214
+ assert_eq ! ( nodes[ 1 ] . node. get_our_node_id( ) , * node_id) ;
6215
+ } ,
6216
+ _ => panic ! ( "Unexpected event" ) ,
6217
+ } ;
6218
+ nodes[ 2 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
6219
+ let events = nodes[ 2 ] . node . get_and_clear_pending_msg_events ( ) ;
6220
+ assert_eq ! ( events. len( ) , 1 ) ;
6221
+ match events[ 0 ] {
6222
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6223
+ _ => panic ! ( "Unexpected event" ) ,
6224
+ }
6225
+ let mut funding_tx_map = HashMap :: new ( ) ;
6226
+ funding_tx_map. insert ( chan_2. 3 . txid ( ) , chan_2. 3 . clone ( ) ) ;
6227
+ commitment_tx[ 0 ] . verify ( & funding_tx_map) . unwrap ( ) ;
6228
+
6229
+ // Broadcast timeout transaction by B on received output fron C's commitment tx on B's chain
6230
+ // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence
6231
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 200 ) ;
6232
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
6233
+ assert_eq ! ( node_txn. len( ) , 8 ) ; // ChannelManager : 2 (commitment tx, HTLC-Timeout), ChannelMonitor : 6 (commitment tx, HTLC-Timeout, timeout tx) * 2 (block-rescan)
6234
+ assert_eq ! ( node_txn[ 2 ] . input[ 0 ] . previous_output. txid, node_txn[ 1 ] . txid( ) ) ;
6235
+ assert_eq ! ( node_txn[ 2 ] . clone( ) . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 133 ) ;
6236
+
6237
+ let mut commitment_tx_map = HashMap :: new ( ) ;
6238
+ commitment_tx_map. insert ( commitment_tx[ 0 ] . txid ( ) , commitment_tx[ 0 ] . clone ( ) ) ;
6239
+ node_txn[ 0 ] . verify ( & commitment_tx_map) . unwrap ( ) ;
6240
+
6241
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ node_txn[ 0 ] . clone( ) ] } , 1 ) ;
6242
+ {
6243
+ let mut added_monitors = nodes[ 1 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
6244
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
6245
+ added_monitors. clear ( ) ;
6246
+ }
6247
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6248
+ assert_eq ! ( events. len( ) , 2 ) ;
6249
+ match events[ 0 ] {
6250
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6251
+ _ => panic ! ( "Unexpected event" ) ,
6252
+ }
6253
+ match events[ 1 ] {
6254
+ 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, .. } } => {
6255
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
6256
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
6257
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
6258
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
6259
+ assert_eq ! ( nodes[ 0 ] . node. get_our_node_id( ) , * node_id) ;
6260
+ } ,
6261
+ _ => panic ! ( "Unexpected event" ) ,
6262
+ } ;
6263
+
6264
+ // Broadcast legit commitment tx from A on B's chain
6265
+ // Broadcast HTLC Timeout tx by B on offered output from A commitment tx on A's chain
6266
+ let commitment_tx = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
6267
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
6268
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6269
+ assert_eq ! ( events. len( ) , 1 ) ;
6270
+ match events[ 0 ] {
6271
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6272
+ _ => panic ! ( "Unexpected event" ) ,
6273
+ }
6274
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
6275
+
6276
+ // Verify that A's ChannelManager is able to detect that HTLC is timeout by a HTLC Timeout tx and react backward in consequence
6277
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : node_txn } , 1 ) ;
6278
+ let events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6279
+ assert_eq ! ( events. len( ) , 1 ) ;
6280
+ match events[ 0 ] {
6281
+ MessageSendEvent :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
6282
+ _ => panic ! ( "Unexpected event" ) ,
6283
+ }
6284
+ }
6285
+
6171
6286
#[ test]
6172
6287
fn test_htlc_ignore_latest_remote_commitment ( ) {
6173
6288
// Test that HTLC transactions spending the latest remote commitment transaction are simply
0 commit comments