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