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