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