@@ -2136,14 +2136,21 @@ impl ChainListener for ChannelManager {
2136
2136
2137
2137
{
2138
2138
let mut channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ;
2139
- for ( preimage , hash ) in hash_to_remove {
2140
- if let Some ( preimage) = preimage {
2139
+ for ( payment_preimage , payment_hash ) in hash_to_remove {
2140
+ if let Some ( preimage) = payment_preimage {
2141
2141
if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2142
- if let Some ( mut sources ) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & hash ) {
2143
- for source in sources . drain ( ..) {
2142
+ if let Some ( mut entry ) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash ) {
2143
+ for source in entry . drain ( ..) {
2144
2144
self . claim_funds_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , preimage) ;
2145
2145
}
2146
2146
}
2147
+ } else {
2148
+ if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
2149
+ if let Some ( mut entry) = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash) {
2150
+ for source in entry. drain ( ..) {
2151
+ self . fail_htlc_backwards_internal ( channel_state. take ( ) . unwrap ( ) , HTLCSource :: PreviousHopData ( source) , & payment_hash, HTLCFailReason :: Reason { failure_code : 0x1000 | 14 , data : Vec :: new ( ) } ) ;
2152
+ }
2153
+ }
2147
2154
}
2148
2155
}
2149
2156
}
@@ -4346,6 +4353,117 @@ mod tests {
4346
4353
}
4347
4354
}
4348
4355
4356
+ #[ test]
4357
+ fn test_htlc_on_chain_timeout ( ) {
4358
+ // Test that in case of an unilateral close onchain, we detect the state of output thanks to
4359
+ // ChainWatchInterface and timeout the HTLC bacward accordingly. So here we test that ChannelManager is
4360
+ // broadcasting the right event to other nodes in payment path.
4361
+ // A ------------------> B ----------------------> C (timeout)
4362
+ // A's commitment tx C's commitment tx
4363
+ // \ \
4364
+ // B's HTLC timeout tx B's timeout tx
4365
+
4366
+ let nodes = create_network ( 3 ) ;
4367
+
4368
+ // Create some intial channels
4369
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
4370
+ let chan_2 = create_announced_chan_between_nodes ( & nodes, 1 , 2 ) ;
4371
+
4372
+ // Rebalance the network a bit by relaying one payment thorugh all the channels...
4373
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
4374
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , 8000000 ) ;
4375
+
4376
+ let ( _payment_preimage, payment_hash) = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) , 3000000 ) ;
4377
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
4378
+
4379
+ // Brodacast legit commitment tx from C on B's chain
4380
+ let commitment_tx = nodes[ 2 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_2. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
4381
+ nodes[ 2 ] . node . fail_htlc_backwards ( & payment_hash) ;
4382
+ {
4383
+ let mut added_monitors = nodes[ 2 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
4384
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
4385
+ added_monitors. clear ( ) ;
4386
+ }
4387
+ let events = nodes[ 2 ] . node . get_and_clear_pending_events ( ) ;
4388
+ assert_eq ! ( events. len( ) , 1 ) ;
4389
+ match events[ 0 ] {
4390
+ 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, .. } } => {
4391
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
4392
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
4393
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
4394
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
4395
+ assert_eq ! ( nodes[ 1 ] . node. get_our_node_id( ) , * node_id) ;
4396
+ } ,
4397
+ _ => panic ! ( "Unexpected event" ) ,
4398
+ } ;
4399
+ nodes[ 2 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
4400
+ let events = nodes[ 2 ] . node . get_and_clear_pending_events ( ) ;
4401
+ assert_eq ! ( events. len( ) , 1 ) ;
4402
+ match events[ 0 ] {
4403
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
4404
+ _ => panic ! ( "Unexpected event" ) ,
4405
+ }
4406
+ let mut funding_tx_map = HashMap :: new ( ) ;
4407
+ funding_tx_map. insert ( chan_2. 3 . txid ( ) , chan_2. 3 . clone ( ) ) ;
4408
+ commitment_tx[ 0 ] . verify ( & funding_tx_map) . unwrap ( ) ;
4409
+
4410
+ // Broadcast timeout transaction by B on received output fron C's commitment tx on B's chain
4411
+ // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence
4412
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 200 ) ;
4413
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
4414
+ assert_eq ! ( node_txn. len( ) , 8 ) ; // ChannelManager : 2 (commitment tx, HTLC-Timeout), ChannelMonitor : 6 (commitment tx, HTLC-Timeout, timeout tx) * 2 (block-rescan)
4415
+ assert_eq ! ( node_txn[ 2 ] . input[ 0 ] . previous_output. txid, node_txn[ 1 ] . txid( ) ) ;
4416
+ assert_eq ! ( node_txn[ 2 ] . clone( ) . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 133 ) ;
4417
+
4418
+ let mut commitment_tx_map = HashMap :: new ( ) ;
4419
+ commitment_tx_map. insert ( commitment_tx[ 0 ] . txid ( ) , commitment_tx[ 0 ] . clone ( ) ) ;
4420
+ node_txn[ 0 ] . verify ( & commitment_tx_map) . unwrap ( ) ;
4421
+
4422
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ node_txn[ 0 ] . clone( ) ] } , 1 ) ;
4423
+ {
4424
+ let mut added_monitors = nodes[ 1 ] . chan_monitor . added_monitors . lock ( ) . unwrap ( ) ;
4425
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
4426
+ added_monitors. clear ( ) ;
4427
+ }
4428
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
4429
+ assert_eq ! ( events. len( ) , 2 ) ;
4430
+ match events[ 0 ] {
4431
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
4432
+ _ => panic ! ( "Unexpected event" ) ,
4433
+ }
4434
+ match events[ 1 ] {
4435
+ 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, .. } } => {
4436
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
4437
+ assert ! ( !update_fail_htlcs. is_empty( ) ) ;
4438
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
4439
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
4440
+ assert_eq ! ( nodes[ 0 ] . node. get_our_node_id( ) , * node_id) ;
4441
+ } ,
4442
+ _ => panic ! ( "Unexpected event" ) ,
4443
+ } ;
4444
+
4445
+ // Broadcast legit commitment tx from A on B's chain
4446
+ // Broadcast HTLC Timeout tx by B on offered output from A commitment tx on A's chain
4447
+ let commitment_tx = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
4448
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ commitment_tx[ 0 ] . clone( ) ] } , 1 ) ;
4449
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
4450
+ assert_eq ! ( events. len( ) , 1 ) ;
4451
+ match events[ 0 ] {
4452
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
4453
+ _ => panic ! ( "Unexpected event" ) ,
4454
+ }
4455
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
4456
+
4457
+ // Verify that A's ChannelManager is able to detect that HTLC is timeout by a HTLC Timeout tx and react backward in consequence
4458
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : node_txn } , 1 ) ;
4459
+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
4460
+ assert_eq ! ( events. len( ) , 1 ) ;
4461
+ match events[ 0 ] {
4462
+ Event :: BroadcastChannelUpdate { msg : msgs:: ChannelUpdate { .. } } => { } ,
4463
+ _ => panic ! ( "Unexpected event" ) ,
4464
+ }
4465
+ }
4466
+
4349
4467
#[ test]
4350
4468
fn test_htlc_ignore_latest_remote_commitment ( ) {
4351
4469
// Test that HTLC transactions spending the latest remote commitment transaction are simply
0 commit comments